Arduino Brain:パルス位置センサー

今日の課題:インクリメンタルエンコーダーの回転角度を決定する方法



今日、brain arduinoに関する一連の出版物で、少しの実験といくつかのレシピを含む短い記事です。 私の過去の記事の1つに対するコメントで、 私は arduinoでエンコーダパルスをカウントしたと非難されました

光学的には、エンコーダを使用するためのハードウェア回路のないエンコーダ1000 /革命およびATMega(STM32シリーズなど)は行き止まりです。

さらにコメントには、多くの理論化がありましたが、スキップする方が良いでしょう。 これがどのようにデッドロックになるかをハードウェアでテストしてみましょう。 手始めに、インクリメンタルエンコーダとは何ですか? プレ光学マウスの時代を覚えている人なら誰でも確実に答えを知っています。 エンコーダー内にはスロットのあるディスクがあります。そのため、わかりやすくするために、500スロットのディスクの写真を撮りました。







このディスクの片側にLEDが配置され、もう一方の側にフォトダイオードが配置されます。







回転すると、ディスクは光をフォトダイオードに渡します(スロットがLEDとフォトダイオードのペアの反対側にある場合)、通過しません。 フォトダイオードの出力で一定の回転速度で、美しい正弦波が得られます(光の流れを部分的にブロックできることを忘れないでください)。 この信号がコンパレータを通過すると、矩形信号が得られます。 信号のパルス数をカウントすると、センサーシャフトがどれだけ回転したかがわかります。



回転の方向はどのように決定されますか? 非常に簡単:センサーでは、1つではなく、2組のLEDフォトダイオード。 ディスクを描画してみましょう。ポイントAとBは、光センサーの位置を示しています。 エンコーダシャフトを回転させるとき、これらの光センサーから2つの信号を削除します。







センサーは、一定の速度で回転すると、1/4の期間ねじれた蛇行が発生するような距離に設定されます。 これは、光センサーAがスロットの中央にあるとき、光センサーBは正確にスロットの境界にあることを意味します。 センサーが(条件付きで)時計回りに回転すると、信号Bの立ち上がりエッジで、信号Aは1に等しくなります。 センサーが反対方向に回転し、上向きのエッジがある場合、信号B aはゼロになります。



これはすべて素晴らしいことですが、自分のプロジェクトに何をコピーアンドペーストする必要がありますか?



ここにあります:



volatile long angle = 0; volatile char ABprev = 0; const int increment[16] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0}; ISR (PCINT0_vect) { // D8 or D9 has changed char AB = PINB & 3; angle += increment[AB+ABprev*4]; ABprev = AB; } void setup() { pinMode(8, INPUT); // A pinMode(9, INPUT); // B PCICR |= (1 << PCIE0); // interrupt will be fired on any change on pins d8 and d9 PCMSK0 |= 3; ABprev = PINB & 3; Serial.begin(115200); } void loop() { Serial.println(angle); delay(100); }
      
      





このコードの仕組みを説明しましょう。 ATmega328p(Arduino nano)でコードをテストしています。エンコーダー出力は、arduino nanoのピンd8とd9に設定されています。 ATmega328pに関しては、これはPINBポートの下位2ビットがエンコーダーの現在の状態を与えることを意味します。 ISR関数は、これらの2ビットが変更されると呼び出されます。 割り込み内で、エンコーダーの状態を変数ABに保存します。



  char AB = PINB & 3; // ,  digitalRead() , //     
      
      





何のために? 前のチャートを見てみましょう。その中の破線は、割り込み呼び出しの瞬間を示しています(信号の前面)。 割り込み呼び出しごとに、以下の数字はAB変数の状態です。







時計回りに回転すると、変数ABは次の4つの値の周期で変化します。231023102310。反時計回りに回転すると、変数ABは0132 0132 0132に変化します。



両方の光センサーがオーバーラップし(変数AB = 0)、割り込みが呼び出されたときにABが2に等しくなると、センサーは時計回りに回転し、カウンターに1を追加します。 ABが0から1になった場合、センサーは反時計回りに回転し、カウンターから1を引きます。 変数ABに対する他の変更についても同じことを行い、テーブルを作成しましょう。







テーブルが完全に埋められていないことに注意してください。 疑問符の代わりに何を挿入しますか? たとえば、理論的には、テーブルの主な対角線は使用しないでください。変数ABが変更されると割り込みが呼び出されるため、0-> 0の遷移は発生しません。 しかし、人生は大変であり、マイクロコントローラーがビジーの場合、いくつかの中断をスキップして呼び出すことができます。 この場合、明らかにデータが不足しているため、何も加算または減算しないことを提案します。 不足しているセルをゼロで埋めます。ここに表を示します。



 const int increment[16] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};
      
      





これで、コードが完全に理解されたことを願っています。



その結果、信号Aの1周期に対して4つの割り込みが発生し、センサーが一方向に回転すると、カウンターが1ではなく4ずつ増加します。つまり、インクリメンタルエンコーダーに2000PPRが書き込まれた場合(ディスク上の2000スロット)、解像度は1/8000回転です。



バウンスはどうですか?



コンパレータに正弦波を通すと、方形波のエッジで必然的にバウンスが発生します。 拡大鏡を見て、正面の1つを見てみましょう。







信号Aは一定であるため、プレートによれば、信号Bの立ち上がりエッジで1を加算し、下方向エッジで減算します。 その結果、バウンスのすべての面を解決できれば、アルゴリズムはそれを完全に飲み込みます。 そして、ここでそれは面白くなりますが、私たちのアルドゥインカはそのような魅力を解決できますか? あなたは長い間理論化することができます、実験をしましょう。



理論から実践へ



パルスを3つの方法でカウントします。



3つの方法はすべてまったく同じ方法でパルスをカウントしますが、もちろん、ハードウェアの方法はポーリング信号の速度が非常に高速です。 エンコーダーは、Omron E6B2-CWZ6C(2000PPR)によって使用されます。



接続



ソフトウェアカウンター



接続は簡単で、2本のワイヤーをエンコーダーからd8およびd9アルデュインの足まで持っていくだけで十分です。



HCTL-2032



hctl-2032をarduinoに接続すると、次のようになります。







アルドゥインのすべての足を占有しないように、74hc165を追加しました。



ビーグルボーンブルー







BeagleBone Blueには直交デコーダが組み込まれているため、3.3Vエンコーダを適切なコネクタに簡単に接続できます。 私のエンコーダーには5Vロジックがあるので、 双方向のレベルコンバーターをbss138に追加しました。







実験1



振り子を持って立ちました。







キャリッジは移動せず、振り子エンコーダーに3つのカウンターを掛けるだけです。 なぜ振り子なのか? 重力は垂れ下がらないマーカーを与えるため、振り子が落ち着くたびに、カウンターには8000の倍数が表示されます(エンコーダー2000pprがあります)。



上から順に、bigbon、ソフトウェアカウンター、hctl2032の3つのカウンターが並列に接続されています。 このテストでは、キャリッジモーターのPWMドライバーは使用されません。







テストの開始時、振り子は静止しており、2つのシリアルポートモニターと、sshを介して実行されるビーグルカウンターがあります。







私の手で振り子を完全に1回転させ、下の位置で再び落ち着くまで待ちます。







3つのカウンターはすべて、予想どおり正確に8000を示しています! まあ、私たちは、バウンスのために、振り子の低速ではソフトウェアカウンターが非常に間違っている必要があることを学びました。 この手順を10回繰り返します。振り子を1回転させるように振り、完全に落ち着くまで待ちます。 それからもう一度振って、落ち着くまで待ちます。 摩擦は低く、1回の反復には数分かかります。その結果、約30分のカウンターが動作します。







ハ、しかし、再び、誰も間違っていませんでした!



二回目の実験



したがって、現実のバウンスは、見た目ほど怖くはありませんでした。 振り子を外し、ドライバーでエンコーダーの軸に引っ掛けます。







次に、速度をゆっくりと上げ、定期的に停止し、3つのカウンターすべてが何が起こっているのかを確認します。 そのため、ウィンドウの1つにエンコーダシャフトの回転速度の推定値があります。



100 rpm-注文。 500 rpm-注文、完全合意。 900 rpm:AHA! ドライバーを停止します。







ハードウェアカウンターは相変わらず一致していますが、ソフトウェアはかなり遅れています。 これが理論とどのように一致するかを考えてみましょう。 ATmega328pマニュアルは、(空の)割り込みの処理は、マイクロコントローラーの最低10クロックサイクルであると述べています。 スタックの操作、割り込み内のコードのビット-これは、割り込みごとに合計40クロックサイクルです。 40サイクル= 1秒あたり4800000サイクルの場合、1分あたり900回転(1秒あたり15回転)で80万回の割り込み。 一般的に、私たちの推定値は、arduinoのクロック周波数、つまり1000 rpmからそれほど遠くありません。これは、割り込み用の高解像度エンコーダーのカウンターの上限であり、それ以外は何も行いません。



毎分2000回転で、両方のハードウェアカウンターがミスマッチなしで機能し、ドライバーを追加することはできません。



要約すると:



1.毎秒15回転の割り込みを数えることは非常に可能です-これはまだ非常にまともな速度です。 ただし、複数のカウンターを処理する必要がある場合、すべてが著しく悪化します。 優れたエンコーダーではチャター抑制が内部にあるため、エンコーダーの選択は強力な役割を果たします。したがって、優れたエンコーダーとペニー8ビットマイクロコントローラーは非常に優れたソリューションです。



2.ハードウェアカウンターは信頼性が高くなりますが、より高価です。



3. hctl2032はBeagleBone Blueよりも大幅に安価ですが、コントローラー、ビーグル、コントローラー自体への接続が難しく、一度に4つのエンコーダーを処理できます。 はい、エンジン用のアンプがすでに搭載されているため、振り子の付いたスタンドはほとんど血液を使わずに組み立てることができます。 一方、非常にエキゾチックな場合でも、hctl-2032は1つ5ドルの費用がかかり、何らかのピークやアトメルのある回路がすでにあり、あまり変更したくない場合に状況を節約できます。



4.彼らは、stm32は安価で、ハードウェアカウンターを持っていると言います。 しかし、(時間の意味で)質問に参加することの代償は痛々しいほど噛みつきます。



一般に、いつものように、理想的な解決策はありません。すべてはタスクと利用可能なリソースに依存します。



All Articles