Arduino Mega2560割り込みピンとロータリーエンコーダーを使用したポートマッピング

割り込みでポート操作を使用してロータリーエンコーダーを読み取ろうとしています。 Unoのコードを見つけたので、ピン2と3のポート呼び出しは異なります。メガではそれぞれPORTH3とPORTH4だと思います。コードが機能していません。ポートが間違っていますか?私はこれを読んでみましたが、Bxxxxxxxxの部分を完全には理解していません。これが間違っている可能性があると思います。これは、割り込みの1つを含むコードの一部です。

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2 static int pinB = 3; // Our second hardware interrupt pin is digital pin 3 volatile byte aFlag = 0; // let us know when we"re expecting a rising edge on pinA to signal that the encoder has arrived at a detent volatile byte bFlag = 0; // let us know when we"re expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set) volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255 volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor) volatile byte reading = 0; void setup () { pinMode(pinA, INPUT); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases) pinMode(pinB, INPUT); attachInterrupt(0, PinA, RISING); // set an interrupt on PinA, //looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below) attachInterrupt(1, PinB, RISING); // set an interrupt on PinB, //looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below) } void PinA() { //CCW cli(); //stop interrupts happening before we read pin values reading = PORTH & 0xC; // read all eight pin values then strip away all but pinA and pinB"s values if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin"s rising edge encoderPos --; //decrement the encoder"s position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00000100) bFlag = 1; //signal that we"re expecting pinB to signal the transition to detent from free rotation sei(); //restart interrupts } 

コメント

  • これを機能させたことがありますか?私もArduino Megaを使用して、3つの割り込みでオムロンエンコーダの角度位置を追跡したいと思っていました。インデックスの割り込みの1つは、毎回0にリセットされます。 1回転します。方向を見つけるために回転するマストを追跡するために使用します。コードはありますが、完全なものはありません。完了しましたか?[email protected]

回答

Re「ピン2と3は異なります。メガでは、それぞれPORTH3とPORTH4だと思います」、Arduinoデジタルピン2は確かです。 3つはUnoとMega2560ボードの異なるポートに属しています。

Mega2560には6つのINTxピンがありますが、Unoには2つあります。メガでは、INT0 … INT3はPD0 … PD3であり、INT4、INT5はPE4、PE5です。宇野では、INT0、INT1はPD2、PD3です。 「328(宇野)」で外部割り込みを一緒にORすることはできますか?の回答で、適切なマスクを表示するルーチンをいくつか示しています。さまざまなArduinoのピン。 「PCIに他のピンを使用する」および「ISRフレームワークを生成するスケッチ」のセクションを参照してください。


質問に示されているコードに関するいくつかの問題があります。

  1. aFlagはゼロに初期化され、示されているコードでゼロ以外に設定されることはありません。したがって、PinA()の最初のif条件が満たされることはありません。

  2. PinA()は割り込みハンドラーであり、attachInterrupt()呼び出しによって割り込みに接続されます。ハードウェアは割り込みハンドラに入る前に割り込みを無効にするため、割り込みハンドラが割り込みをオフにする必要はありません。つまり、PinA()cli()を削除します。同様に、PinA()の最後にあるsei()を削除します。これは、RETI命令の実行時にハードウェアが割り込みステータスを復元するためです。

  3. Arduinoソフトウェア環境は、名前と一致するバイナリ値を持つB00001100のような定数を定義します。つまり、Arduinoソフトウェア環境では、定数B00001100の値は0B00001100です。私の意見では、これは「ばかげた不要な機能です。バイナリ定数値を使用する場合は、コードで0B00001100のような標準のC表記を使用することをお勧めします。

  4. encoderPos--の代わりにencoderPos --を書くことを倒錯と見なし、その不要なスペースを削除することをお勧めします。

  5. PinB()割り込みハンドラーを表示していないため、encoderPos++の場合。示されているコードから判断すると、バウンスエラーや断続的なエラーを正しく処理できない方法を使用しています。次の回答に示されているように、ピン変更割り込みとステートマシン方式を使用することをお勧めします。
    Digisparkを使用したKY-040ロータリーエンコーダーからの読み取り
    Arduinoでステータス変更方法を使用して高速ローテーションのためにRPSを読み取る方法は?
    PulseInの代わりに割り込みを使用してRCレシーバーチャネルを読み取ります
    「328(宇野)」で外部割り込みをORで結合できますか?

回答

メガでは、PINEでピンを読み取ります。

したがって、PinAのコードは次のように変更されます。

 reading = PINE & 0b00110000; if(reading == 0b00110000 && aFlag) { encoderPos --; bFlag = 0; aFlag = 0; } else if (reading == 0b00010000) bFlag = 1;  

Iここで必要なマスキングについて話している素晴らしい議論を見つけました: https://forum.arduino.cc/index.php?topic=561741.0

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です