3

組み込みコントローラーで実行されている C の圧力センサーによって生成されたデータ ポイントのストリームを平均化するために、循環バッファーを実装しようとしています。アイデアは、バッファの実行中の合計を維持しながら、最後の N 個の圧力読み取り値をバッファに保存することです。平均 = 合計 / N. 自明であるべきです。

ただし、私が見ている平均は、圧力の読み取り値の近くで始まる値ですが (バッファレジスタに典型的な値をプリロードします)、その後ゼロに向かっています。合計も表示すると、それも漸近的にゼロに落ちます。圧力が変化すると、平均は圧力変化の方向にゼロから離れますが、圧力が安定するとすぐにゼロ傾向に戻ります。

誰かが私が作っているエラーを見つけることができれば、それは非常に役に立ちます.

    #define ARRAYSIZE 100

    double Sum;                       // variable for running sum
    double Average;                   // variable for average
    double PressureValue[ARRAYSIZE];  // declare value array
    int i;                            // data array index

    int main(void) {

      while (1) 
      {
        if (i == ARRAYSIZE) i = 0;       // test index, reset if it reaches the upper boundary
        Sum = Sum - PressureValue[i];    // subtract the old datapoint from running sum
        PressureValue[i] = PRESSURE;     // replace previous loop datapoint with new data
        Sum = Sum + PressureValue[i];    // add back the new current value to the running sum
        Average = Sum / ARRAYSIZE;       // calculate average value = SUM / ARRAYSIZE
        ++i;                             // increment index
      }                                  // end while loop

    }                                    // end main

平均化コードは割り込みハンドラで実行されます。各 I2C 通信フェーズの最後に割り込みがトリガーされ、I2C 経由で圧力センサーからデータを読み取っています。最後の段階で、圧力データを構成する 4 バイトが取得された後、それらは完全な読み取り値に組み立てられ、次に PRESSURE 変数に含まれる PSI の 10 進数の読み取り値に変換されます。

明らかに、これは私のコードからの直接のカット アンド ペーストではありませんが、私は誰もがすべてのことを苦労する必要がないようにしたかったので、平均を計算することに関連するものだけに制限し、変数名を読みやすくします。それでも、私は自分が間違っていることを見つけることができません。

ご清聴ありがとうございました!

ダグ G.

4

2 に答える 2

1

私はあなたのコードに明らかな問題は見当たりませんが、あなたが言うように、あなたはそれをすべて提供しているわけではないので、残りの部分で何が起こっているのか誰が知っていますか (特に、初期化の方法/場合i) Sum、しかし、以下は私にとってはうまく機能します。これは基本的にあなたが持っているのと同じアルゴリズムです:

#include <stdio.h>
#include <stddef.h>

double PressureValue[8];
double Pressures[800];

int main(void) {
    const size_t array_size = sizeof(PressureValue) / sizeof(PressureValue[0]);
    const size_t num_pressures = sizeof(Pressures) / sizeof(Pressures[0]);
    size_t count = 0, i = 0;
    double average = 0;


    /*  Initialize PressureValue to {0, 1, 2, 3, ...}  */

    for ( size_t n = 0; n < array_size; ++n ) {
        PressureValue[n] = n;
    }
    double sum = ((array_size - 1) / (double) 2) * array_size;

    /*  Initialize pressures to repeats of PressureValue  */

    for ( size_t n = 0; n < num_pressures; ++n ) {
        Pressures[n] = n % array_size;
    }

    while ( count < num_pressures ) {
        if ( i == array_size )
            i = 0;
        sum -= PressureValue[i];
        PressureValue[i] = Pressures[count++];
        sum += PressureValue[i++];
    }

    average = sum / array_size;

    printf("Sum is %f\n", sum);
    printf("Counted %zu pressures\n", count);
    printf("Average is %f\n", average);

    return 0;
}

出力:

paul@local:~/src/c/scratch$ ./pressure
Sum is 28.000000
Counted 800 pressures
Average is 3.500000
paul@local:~/src/c/scratch$

もう1つの可能性として、「変数に含まれるPSIの10進数の読み取り値に変換される」と言うときPRESSURE、および他の場所で、整数除算のために物事がゼロに切り捨てられないようにしてください。さらに追加するにつれて「ゼロになる傾向」がある場合、それは私がすぐに疑うものです. たとえば、華氏を摂氏に変換する際の典型的なエラーは、 と書くことです。これは毎回ゼロに切り捨てられ、常に が残りc = (f - 32) * (5 / 9)ます。(5 / 9)c == 0

また、一般的なルールとして、「誰もがすべてを通り抜ける必要はありませんでした」ということは理解していますが、実際の問題はコードの一部ではないことに驚くでしょう。です。これが、SSCCEを提供して、コードを絞り込み、実際に問題を切り分けて再現できるようにすることが重要である理由です。コードを絞り込んで、問題を特定して再現できないことがわかった場合は、問題の原因が原因であると考えられていないことはほぼ確実です。

于 2013-10-26T03:21:39.257 に答える
0

It is also possible your code is working exactly as intended. If you are preloading your array with typical values outside of this loop and then running this code you would get the behavior you are describing. If you are preloading the array make sure you are preloading the sum and average otherwise you are essentially measuring gauge pressure with you preloaded value as atmospheric pressure.

于 2016-07-18T16:25:40.820 に答える