计算运行平均值

时间:2017-02-09 19:14:02

标签: c arrays msp430 circular-buffer code-composer

由圆形阵列计算的运行平均值产生的常数<1。当平均值应始终在0和1之间时,平均值为0。

我正在为MSP430设备编写固件,该设备使用LED和光电二极管来检测墨水上的特定类型。该设备扫描大约155us,扫描仪下的样品范围从0.1m / s到3.3m / s。该设备的目标是测试墨水并测量墨水(通过)以测试(未通过)比率,当比率在相应值之间时打开绿色LED,而当不是时,打开红色LED。我使用静态整数数组将连续传递和测试值的值存储到每个数组的相同索引号。在数组的最后一个索引之后,索引被设置回零并且旧值被写入。

GREEN_LED_ON;和类似的定义是我的MCU的端口定义,并验证是正确的。

事件是测试结果。如果检测到墨水,则事件=已检测到,反之亦然

测试将是GUI设置的平均值,但是现在它没什么,因为我的功能没有这部分工作

通常情况下,我会通过附带的GUI设置变量平均值,但出于测试目的,我设置平均值&lt; 0只是为了弄清楚LED在错误的时间出现的原因并且我发现我得到的平均值<0 。平均值应始终为0 =

注意:

  • 我尝试使用LED输出检查代码的各个部分是否正常工作。我注释掉了控制LED的平均部分,并通过打开和关闭LED来验证事件==部分是否正常工作。然后我尝试将该代码放在flag ==部分,并且LED也按预期与该部分对应。
  • 我发现数组值有问题。一旦n > size它只测试一次而不是等待下一个标志更改。我不能有n&gt;大小,因为在我的代码中进一步向下,n++将等于7,这是超出界限

我添加了一段代码以确保不会发生翻转。选择值8,000和30,000以匹配最慢的运行速度。

我还改变了数组索引递增的位置,并确保它在数组的范围内。

这是更新的功能:

void display(char event, char test) {

static int size=5;
static int array[6]={0};  //array with number of passes for each n
static int n=0;
static float sum=0;//total number of passes
static float average=0;//average pass rate over n
static int consecpass=0; //consecutive passes
static int consecfail=0; //consecutive fails
static int totalnumberoftests[6]={0}; //total number of tests conducted.  Counts the number of passing or failing tests for the nth value
static float counter=1; //used to count the total number of tests
static int flag=0;


    if (event == DETECTED)
    {
        if (flag==0)
        {

            sum=sum-array[n];
            counter=counter-totalnumberoftests[n];
            array[n]=0;
            totalnumberoftests[n]=consecfail;
            sum=sum+array[n];
            counter=counter+totalnumberoftests[n];

            flag=1;
            consecpass++;

            n++;
            if(n>=size)n=0;
            //GREEN_LED_ON;
            //RED_LED_OFF;
        }else{

        consecfail=0;
        consecpass++;
        //GREEN_LED_ON;
        //RED_LED_OFF;

        }

    } if (event==NOT_DETECTED){

        if(flag==1)
        {

            sum=sum-array[n];
            counter=counter-totalnumberoftests[n];
            array[n]=consecpass;
            totalnumberoftests[n]=consecpass;
            sum=sum+array[n];
            counter=counter+totalnumberoftests[n];

            flag=0;
            consecfail++;

            n++;
            if(n>=size)n=0;
            //RED_LED_ON;
            //GREEN_LED_OFF;
        }else{


        consecpass=0;
        consecfail++;
        //RED_LED_ON;
        //GREEN_LED_OFF;


        }
    }

    if (consecpass>8000)
    {
        sum=sum-array[n];
        counter=counter-totalnumberoftests[n];
        array[n]=consecpass;
        totalnumberoftests[n]=consecpass;
        sum=sum+array[n];
        counter=counter+totalnumberoftests[n];
        consecpass=0;
        n++;
        if(n>=size)n=0;
    }

    if(consecfail>30000)
    {
        sum=sum-array[n];
        counter=counter-totalnumberoftests[n];
        array[n]=0;
        totalnumberoftests[n]=consecfail;
        sum=sum+array[n];
        counter=counter+totalnumberoftests[n];
        consecfail=0;
        n++;
        if(n>=size)n=0;
    }

    average=sum/counter;

    if(average<.6 && average > .1)
    {
        GREEN_LED_ON;
        RED_LED_OFF;
    }else{
        GREEN_LED_OFF;
        RED_LED_ON;
    }


}

if (n >= size)语句后面的标志语句,以避免我的数组的最终值为1.这是更改(它在if(flag ==)语句中都有:

if (flag == 1) {
    sum = sum - array[n];
    counter = counter - totalnumberoftests[n];
    array[n] = consecpass;
    totalnumberoftests[n] = consecpass;
    sum = sum + array[n];
    counter = counter + totalnumberoftests[n];

    flag = 0;
    consecfail++;

    n++;
    if (n >= size)
        n = 0;

以下是原始代码:

void display(char event, char test) {

    static int size = 6;
    static int array[6] = { 0 };  //array with number of passes for each n
    static int n = 0;
    static float sum = 0;//total number of passes
    static float average = 0;//average pass rate over n
    static int consecpass = 0; //consecutive passes
    static int consecfail = 0; //consecutive fails
    static int totalnumberoftests[6] = { 0 }; //total number of tests conducted.  Counts the number of passing or failing tests for the nth value
    static float counter = 1; //used to count the total number of tests
    static int flag = 0;    

    if (n >= size) {    
        n = 0;    
    }

    if (event == DETECTED) {
        if (flag == 0) {
            n++;
            sum = sum - array[n];
            counter = counter - totalnumberoftests[n];
            array[n] = 0;
            totalnumberoftests[n] = consecfail;
            sum = sum + array[n];
            counter = counter + totalnumberoftests[n];

            flag = 1;
            consecpass++;               
        } else {    
            consecfail = 0;
            consecpass++;               
        }    
    } 

    if (event == NOT_DETECTED) {    
        if (flag == 1) {
            n++;
            sum = sum - array[n];
            counter = counter - totalnumberoftests[n];
            array[n] = consecpass;
            totalnumberoftests[n] = consecpass;
            sum = sum + array[n];
            counter = counter + totalnumberoftests[n];

            flag = 0;
            consecfail++;               
        } else {        
            consecpass = 0;
            consecfail++;               
        }
    }

    average = sum / counter;

    if (average < 0) {
        GREEN_LED_ON;
        RED_LED_OFF;
    } else {
        GREEN_LED_OFF;
        RED_LED_ON;
    }        
}

2 个答案:

答案 0 :(得分:1)

你有UB。

在顶部你做if (n>=size) n = 0;。这仍然允许nsize-1

但是,在访问数组之前,您需要进一步向下n++ 。这样您就可以访问array[size],即UB。

我相信您希望在进行计算后将n++移至if部分的底部,。而且,您可能希望将两者结合使用if (++n >= size) n = 0;

<强>更新

  

我设置尺寸= 5,我仍然得到负数。现在这些数组都在边界内吗?

可能。但是,有一些事情。

只有average需要[或应该]为float

你有&#34; parallel&#34;阵列。我改为使用结构。

我已经超过了你的逻辑几次,我仍然不确定你想要实现的目标。

所以,我重构了尝试删除任何可能的琐碎错误。

我有点怀疑计数器的减法然后加回,特别是在切换点上。这只是可以获得负数的地方。

可能将该功能插入到模拟各种墨水长度/无墨水流数据的单元测试程序中会有所帮助。然后你可以断点。这可以测试/验证您的逻辑,而不必使用实时系统(即单元测试程序是您可以在PC上运行的普通应用程序)。您可以有条件地编译/输出LED代码而不是&#34;中止负值&#34;如下所述。

无论如何,这是我对简化的看法,可能有助于澄清[请原谅无偿的风格清理]:

// NOTE: in the long term, an int could wrap to a negative -- adjust this
// as needed
typedef long long ctr;

struct event {
    ctr testcount;
    ctr passcount;
};

// NOTE: moved this outside function to guarantee all values are zero at start
#define EVENTMAX    6
struct event events[EVENTMAX];

void
display(char event, char test)
{
    static int n = 0;
    static ctr sum = 0;             // total number of passes
    static double average;          // average pass rate over n
    static ctr consecpass = 0;      // consecutive passes
    static ctr consecfail = 0;      // consecutive fails
    static ctr testcount = 1;       // used to count the total number of tests
    static int flag = 0;
    struct event *cur;

    cur = &events[n];

    if (event == DETECTED) {
        if (flag == 0) {
            sum -= cur->passcount;
            testcount -= cur->testcount;

            cur->passcount = 0;
            cur->testcount = consecfail;

            sum += cur->passcount;
            testcount += cur->testcount;

            flag = 1;

            if (++n >= EVENTMAX)
                n = 0;
        }
        else {
            consecfail = 0;
        }

        consecpass++;
    }

    if (event == NOT_DETECTED) {
        if (flag == 1) {
            sum -= cur->passcount;
            testcount -= cur->testcount;

            cur->passcount = consecpass;
            cur->testcount = consecpass;

            sum += cur->passcount;
            testcount += cur->testcount;

            flag = 0;

            if (++n >= EVENTMAX)
                n = 0;
        }
        else {
            consecpass = 0;
        }

        consecfail++;
    }

    // add code to abort program if _either_ sum _or_ testcount is negative
    // here ...

    average = sum;
    average /= testcount;

    if (average < 0) {
        GREEN_LED_ON;
        RED_LED_OFF;
    }
    else {
        GREEN_LED_OFF;
        RED_LED_ON;
    }
}

更新#2:

  

我发现其中一个问题是翻身。我用if语句修复了它,如果它们高于8,000或30,000,则存储值。当我处于调试模式时,数组的值看起来像我期望的那样,但我偶尔会在sum和counter中得到负数。如何减去错误的索引?

你可以从过时的#34;中减去即使索引有效也要输入。我意识到你正在尝试一个RLE impl。

猜猜......

您更改&#34;当前&#34;进入,但在++n之后,&#34;其他&#34;方可能得到&#34; next&#34;在需要之前的条目时进入。

即,您减去array[0],应用内容,设置array[0]然后增加n

另一方现在减去array[1],需要减去array[0]并设置array[1]

所以,你可能有一个&#34;关闭一个&#34;错误,从逻辑上讲。

说不上。

使用单元测试应用程序,您可以为所有内容添加调试printf。当负值发生时,停止。然后分析日志。单元测试可以/应该测试所有边缘情况。

如果将(例如)1x10,0x3,1x5,0x20的序列输入到函数中,则这些序列应显示在arrays / struct中。存储的条目应与输入序列匹配。

因此,转储数组以验证计数是否符合预期。

什么值达到8000/30000?

答案 1 :(得分:0)

如果有人回到这里,这就是我正在使用的代码,我的平均运行效果非常好

 void display(char event, char test) {

   static int size=9; //size of the array
   static int array[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  //array with number of passes for each n
   static int n=0; //number for the index in both arrays
   static long int sum=0;//total of passes
   static double average=0;//rate of passes per tests.  The sum of the values in array[n] divided by total tests in totalnumberoftest[n] attay
   static int consecpass=0; //consecutive passes
   static int consecfail=0; //consecutive fails
   static int totalnumberoftests[10]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //total number of tests conducted.  Counts the number of passing or failing tests for the nth value
   static long int counter=1; //used to count the total number of tests
   static int flag=0;//flag used to indicate when the input goes from event==DETECTED to event==NOT_DETECTED
   static int lowlimitb=0;// integer value from low limit b in desert for average setting.  Value entered should be the positive tests/total tests percentage


        sum=sum-(float)array[n]; //subtract the nth value of array from sum
        counter=(float)counter-totalnumberoftests[n];
        array[n]=0;//set the nth value to zero, because the previous state of event was NOT_DETECTED, meaning there were no positive tests
        totalnumberoftests[n]=consecfail; //add the number of negative tests to total tests
        sum=sum+(float)array[n]; //add array index n to sum (should be zero)
        counter=counter+(float)totalnumberoftests[n]; //counter is the total number of tests.  Add totalnumberoftests with the last index n adds the last consecfail to counter

        flag=1; //set flag==1 to indicate the last event was DETECTED
        consecpass++; //count a pass
        consecfail=0;

        n++; //set the next index for the arrays
        if(n>size)n=0;  //if array index is greater than the size of the array, set the index back to zero. This will overwrite the data in array index zero
        //GREEN_LED_ON;
        //RED_LED_OFF;
    }else{ //the last event=DETECT, no need to change array indices


    consecpass++;
    //GREEN_LED_ON;
    //RED_LED_OFF;

    }

} if (event==NOT_DETECTED){

    if(flag==1) //flag gets set to 1 in event==DETECTED
    {

        sum=sum-(float)array[n];    //subtract the nth value of array from current sum of passes
        counter=counter-(float)totalnumberoftests[n];
        array[n]=consecpass; //set array[n] equal to the number of consecutive passes
        totalnumberoftests[n]=consecpass; //set the number of tests for index n = number of passes
        sum=sum+(float)array[n]; //add the last number of consecutive passes (stored in array[n]) to the current sum of passes
        counter=counter+(float)totalnumberoftests[n];

        flag=0; //set the flag==0 so the array indices do not change until event changes
        consecfail++;

        n++; //set the next index for the arrays
        if(n>size)n=0;//if array index is greater than the size of the array, set the index back to zero. This will overwrite the data in array index zero
        //RED_LED_ON;
        //GREEN_LED_OFF;
    }else{

    consecpass=0;
    consecfail++;
    //RED_LED_ON;
    //GREEN_LED_OFF;


    }
}

if (consecpass>8000) //used to prevent rollover and to indicate failure if device is standing still.  8000 was selected because the absolute minimum speed will be 10cm/s
{
    sum=sum-(float)array[n];
    counter=counter-(float)totalnumberoftests[n];
    array[n]=consecpass;
    totalnumberoftests[n]=consecpass;
    sum=sum+(float)array[n];
    counter=counter+(float)totalnumberoftests[n];
    consecpass=0;
    n++;
    if(n>size)n=0;
}

if(consecfail>30000) //used to prevent rollover and to indicate failure if device is standing still.  30000 was selected because the absolute minimum speed will be 10cm/s
{
    sum=sum-(float)array[n];
    counter=counter-(float)totalnumberoftests[n];
    array[n]=0;
    totalnumberoftests[n]=consecfail;
    sum=sum+(float)array[n];
    counter=counter+(float)totalnumberoftests[n];
    consecfail=0;
    n++;
    if(n>size)n=0;
}

average=(double)sum/(double)counter; //average is a float.  The total number of positive tests/total number of tests


if(average<.35 && average > .25 //acceptable passing range
{
    GREEN_LED_ON;
    RED_LED_OFF;


} else {

    GREEN_LED_OFF;
    RED_LED_ON;
    }



  }
   }