0

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

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

绿色_LED_ON;和类似的定义是我的 MCU 的端口定义,并且经过验证是正确的。

event 是测试结果。如果检测到墨水,则 event=DETECTED,反之亦然

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

通常我会通过随附的 GUI 设置变量平均值,但出于测试目的,我设置平均值 <0 只是为了找出 LED 在错误时间亮起的原因,我发现平均值 <0。平均值应始终为 0=

笔记:

  • 我尝试使用 LED 输出检查代码的各个部分是否正常工作。我注释掉了控制 LED 的平均部分,并通过打开和关闭 LED 验证了 event== 部分是否有效。然后我尝试将该代码放入 flag== 部分,并且 LED 也按预期与该部分相对应。
  • 我发现数组值有问题。一旦n > size它只测试一次,而不是等待下一个标志更改。我不能有 n>size 因为在我的代码中再往下,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;
    }        
}
4

2 回答 2

1

你有UB。

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

但是,在访问数组n++ 之前,您需要进行更深入的操作。这将允许您访问array[size]UB。

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


更新:

我设置 size=5 仍然得到负数。数组现在都在边界内正确吗?

可能。但是,有几件事。

average需要[或应该] a float

您有“并行”数组。我会改用结构。

我已经看过你的逻辑几次了,但我仍然不确定你想要达到什么目的。

因此,我进行了重构以尝试消除更多可能的微不足道的错误。

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

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

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

// 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 中得到负数。如何减去错误的索引?

即使索引有效,您也可能会从“陈旧”条目中减去。我意识到您正在尝试 RLE impl。

一个推测 ...

您更改了“当前”条目,但在 之后++n,“另一方”在需要上一个条目时可能会获得“下一个”条目。

也就是说,你减去array[0],应用东西,设置array[0]然后增加n

对方现在是减法array[1],需要减法的时候array[0]再设定array[1]

因此,从逻辑上讲,您可能会遇到“差一”错误。

不知道。

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

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

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

什么值达到 8000/30000?

于 2017-02-09T19:53:17.180 回答
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;
    }



  }
   }
于 2017-02-24T19:10:28.730 回答