シリアル通信用のArduinoの高精度タイミング


11

Arduino Unoを使用して、シリアルポート経由で時間と電圧の情報をPythonに送信し、プロットします。ただし、連続するタイムスタンプ間の間隔のタイミングが時間の経過とともに増加しているようで、プロットに影響を与えます。これは、ボーレートが9600に設定されている場合に特に当てはまります。この場合、最初の時間差はおそらく1320で、比較的短い時間の後に16400に増加します。このレートを最大115200 bpsにすると、比較的長い送信を行った後でも、変化は遅くなり、目立たなくなります。約1340から1500です。時間はすべてマイクロ秒単位で示されます。

この影響を軽減または排除できるかどうか、そしてそれが存在する理由が理解できない場合は知りたいです。これを引き起こす割り込みと遅延について読みましたが、手元にある電子機器の複雑さを十分に理解していないので、知りたいです。

  1. タイミングの精度を上げることはできますか?
  2. このタイミングの変化の原因は何ですか?

これが私が現在持っているものです:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;    

byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

「正確」とはどういう意味ですか?カウンターによって与えられる時間はかなり正確で、正確で、良い解像度になります。あなたは時間を決定論的(すなわち常に同じ)にしたいですか?
Cyber​​gibbons 2014年


Arduino側ではなくPC側にタイムスタンプを追加するか、RTC(リアルタイムクロック)モジュールを使用します。RTCモジュールは、さまざまなウェブストアで見つけるのがかなり安価です。ストアがデータシートにリンクしていることを確認してください。別の方法は、タイマーをプログラムし、割​​り込みサービスルーチンを使用して、適度に正確なタイミングを取得することです。
ジッピー2014年

何をしeHealth.getECG()ますか?その通話は常に同じ時間続きますか?
jfpoilpret 2014年

「比較的短い期間」の継続時間を指定できますか?Arduinoを再起動した後も常に同じですか?
jfpoilpret 2014年

回答:


4

タイマーとISR(割り込みサービスルーチン)を使用して、タイミングをより正確にします。

私の1msタイミング割り込みのProof of Conceptを見てください。アイデアは、他のイベントをトリガーするために使用できる、システムに適度に正確な1msの「ハートビート」を持たせることです。PoCでは½HzでLEDを点滅させるために使用されていますが、新しい変数へのアクセス権を持つmillisecondCounterとすると、secondCounter任意のメインループにおけるトリガイベントにできます(ただし、正確に時限)瞬間を。


2
あなたのPoCは非常に興味深いですが、割り込みが有効になっているときに(2でloop())2バイトの値を読み取り、この値がISRによって変更されるという点で(修正が簡単な)欠陥があります。loop()(ISRによる変更の途中で)不正な値を読み取ることが発生する可能性があります。ブログにコメントを投稿しました。
jfpoilpret 2014年

@jfpoilpret興味深い点をここに記述します。RAMから値を取得する途中で割り込みが発生することは考えていません。今夜は分解をチェックして記事を更新します。多分別の記事を書くのも良い理由かもしれません:o)
jippie

私はあなたのPoCからサンプルを作成し、私のUNOで問題が少なくとも10秒に1回発生することを確認できました。しかし、もちろん実際にはそれはあなたが何をしているのかに大きく依存しますloop():私のサンプルはミリ秒の値を取得し、それを前の読み取り値と比較し、差> 0(カウンターを0にリセットする以外)の場合、メッセージを表示します。
jfpoilpret 2014年

@jfpoilpretが気づいたことはありません。私はそれをハートビートとして使用して、猫のフードバケットを監視し、猫が失望する可能性がある場合にLEDを点滅させます...; o)将来的にISRの使い方を変えるでしょう。
ジッピー2014年

1
これは、ブロックATMEGA16U2に接続された水晶振動子とATMEGA328P-PUに接続された共振器を示しています。16U2はシリアルインターフェイス用で、328Pは「The Arduino」です。興味深いことに、16U2はクロックを別のチップ(328Pなど)にプッシュできます。
ウドクライン14

3

シリアル書き込みタイミングの「一貫性」に影響を与える可能性があるいくつかのことを考えることができます。

  • 印刷するデータのサイズ

これは考えるべき最も明白なことかもしれませんが、実際に印刷するほど、処理に時間がかかります。

解決策:文字列を既知の長さの文字列にフォーマットします。

  • バッファシリアルを使用する

UNIXでは、バッファ付きまたはバッファなしの方法を使用してシリアルポートにアクセスできます。バッファリングされた方法を長時間使用すると、バッファが一杯になると少し遅くなる場合があります。通常、データが受信しているときよりも速くデータが受信されるときに発生します…

解決策:バッファリングされていないシリアルラインを使用します(:Darwin / OSX /dev/cu.usbmodemXXXでは/dev/tty.usbmodemXXX

  • タイマーの優先順位

TC割り込みを使用しているようで、AVRは割り込みの処理方法に優先順位があります。Atmega328の優先順位はわかりません。これは、最も文書化されている機能の1つではないため、わかりません。 TC0とUART割り込みの安全性。

解決策:割り込みの優先度に関するドキュメント/データシートをさらに調べ、必要に応じてタイマーを変更します。または、他のタイマーを実行せずにテストを実行します。

  • 読み取り中のデータは、時間をかけて読み取るのに時間がかかる

一部のドライバーは、以前の値に対していくつかの操作を平均化または実行する必要があるため、測定する値が多いほど、バッファーは長くなり、バッファーの最大サイズに達するまで、値の計算に時間がかかります。

解決策:使用しているライブラリのソースコードを確認し、最適化するか、計算がある場合は削除するか、増加する処理時間を考慮してください。

  • Arduinoフレームワークのオーバーヘッドを回避

しかし、本当に arduinoからのシリアル出力を最適化したい場合は、arduinoのオーバーヘッドの使用を避ける必要があります…しかし、あまりエレガントでなく快適に使用できません。

私が見逃している他のポイントがあると確信していますが、それはさらに掘り下げる前にチェックする最初のことです。

HTH


2

コードには、後続の測定で出力の期間が含まれます。したがって、出力の長さに応じて、異なる時間を測定します。これは、固定長出力にフォーマットすることで修正できます。

次の問題は、UNOのタイムベースが非常に悪いことです。さまざまなArduinoタイプとDCF77時間基準の比較については、こちらをご覧ください。

結論:正確なタイミングが必要な場合は、クリスタル付きのArduinoを入手するか、RTCを使用してください。DS3231 / DS3232 RTCは通常、箱から出して2 ppmの精度を達成するため、私は強くお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.