0

私は MC68HC11 マイクロコントローラに取り組んでおり、サンプリングしたアナログ電圧信号が入っています。シナリオは計量機です。大きなピークは、オブジェクトがセンサーにぶつかったときに安定し (これが必要なサンプルです)、オブジェクトがロールオフする前に再びピークに達します。

私が抱えている問題は、プログラムがこの安定点を検出し、それを平均して全体の重みを生成する方法を考え出すことですが、その方法を理解することはできません:/. 私が考えた 1 つの方法は、以前の値を比較して、それらの間に大きな違いがないかどうかを確認することですが、成功していません。以下は、私が使用しているCコードです。

#include <stdio.h>
#include <stdarg.h>
#include <iof1.h>

void main(void)
{
/* PORTA, DDRA, DDRG etc... are LEDs and switch ports */

unsigned char *paddr, *adctl, *adr1;
unsigned short i = 0;
unsigned short k = 0;
unsigned char switched = 1; /* is char the smallest data type? */

unsigned char data[2000];

DDRA = 0x00; /* All in */
DDRG = 0xff;
adctl = (unsigned char*) 0x30;
adr1 = (unsigned char*) 0x31;

*adctl = 0x20; /* single continuos scan */

while(1)
{
    if(*adr1 > 40)
    {
        if(PORTA == 128) /* Debugging switch */
        {
            PORTG = 1;
        }
        else
        {
            PORTG = 0;      
        } 
        if(i < 2000)
        {
            while(((*adctl) & 0x80) == 0x00);
            {
                data[i] = *adr1;
            } 
                            /* if(i > 10 && (data[(i-10)] - data[i]) < 20) */
            i++;
        } 
        if(PORTA == switched)
        {   
            PORTG = 31;
            /* Print a delimeter so teemtalk can send to excel */
            for(k=0;k<2000;k++)
            {
                printf("%d,",data[k]);
            }
            if(switched == 1) /*bitwise manipulation more efficient? */
            {
                switched = 0;
            }
            else
            {
                switched = 1;
            }
            PORTG = 0;
        }
        if(i >= 2000)
        {
            i = 0;
        }
    }
}
}

提案をお待ちしております:)

(下のグラフは、これらの値がどのように見えるかを示しています。赤いボックスは、特定したい領域です。

結果

4

4 に答える 4

2

サンプル シーケンスにグリッチ (短命のトランジェント) がある場合は、レイアウトの変更、デカップリングの追加、フィルタリングの追加など、ハードウェアの改善を試みてください。

そのアプローチが失敗した場合、たとえば 5 桁の長さのメディアン フィルター [1] が最後の 5 つのサンプルを取得し、それらを並べ替えて中間のサンプルを出力するため、トランジェントの 2 つのサンプルはその出力に影響しません。(7ヶ所・・・3ヶ所トランジェント)

次に、計算効率の高い指数平均ローパス フィルター [2]

                     y(n) = y(n–1) + alpha[x(n) – y(n–1)]

アルファ (1/2^n、右シフトによる除算) を選択して、基になる応答 (約 50 サンプル) よりも小さい時定数 [3] を生成しますが、それでもノイズを除外します。有効な小数ビットを増やすと、量子化の問題が回避されます。

この改善されたサンプル シーケンスにより、しきい値とサイク​​ル カウントを適用して静止期間を検出できます。

さらに、静止期間の終わりに常に大きな急激な変化が続く場合、サンプル遅延「配列」を使用すると、急激な変化の検出が可能になりますが、ログ用に最後の静止サンプルを利用できます。

[1] http://en.wikipedia.org/wiki/Median_filter

[2] http://www.dsprelated.com/showarticle/72.php

[3] http://en.wikipedia.org/wiki/Time_constant

注 上記のフィルタリング操作のコードを追加すると、可能な最大サンプル レートが低下しますが、より高速なものを printf に置き換えることができます。

于 2013-03-03T01:20:35.553 に答える
1

現在の値と前の値からの差分を継続的に保存します。

はかりへの重量適用の開始時にデルタが減少している
場合に注意してください スケールへの重量適用の終了時にデルタが増加している場合に注意してください
小さなデルタでX個の値を取り、それらを平均します

ところで、これは 100 万回前に行われたと確信しています。検索すると、多くの情報が見つかると思いscale PIDますweight PID

于 2013-02-28T18:39:47.980 に答える
0

前の値と比較する場合は、読み取り値の間のどこかで ___delay_ms(XX) 関数を使用することを忘れないでください。コードが連続してループする場合、各ステップの違いは明らかに小さくなります。

于 2013-02-28T19:01:27.313 に答える
0

あなたの素敵なグラフを見ると、立ち下がりエッジだけを探すべきだと思います。それは立ち上がりエッジよりも一貫しています。

言い換えれば、サンプルを蓄積し、事前定義されたウィンドウ サイズで常に移動平均を計算し、参考のために以前の値の偏差を記憶し、値に大きな負の隆起がないかどうかを確認します (絶対値が現在の 10 分の 1 など)。ランニング平均)、あなたのランニング平均はあなたの価値です。少し前に戻って (平均値の最後の数個の値を無視して再計算します)、写真に表示されている負の隆起の前に見える小さな正の隆起を補正することができます...ここでは難しい計算は必要ありません。現実をより適切にモデル化することはできませんでした。次に、画像が表示されたら、コードがすべてのサンプルの終わりを検出することを確認してください。負のバンプが見逃されていないことを確認するために、サンプルを十分に速くする必要があります(そうしないと、データの平均化に大きな時間誤差が生じます)。

そして、その大きな配列は必要ありません。実行平均は、ウィンドウサイズが小さいことに基づいて優れており、負のバンプを検出した場合の残留誤差が小さくなります。

于 2013-03-18T18:14:11.090 に答える