web-dev-qa-db-ja.com

Arduino UnoPWMピンの競合

タンクの2つのモーターを制御するためにL298Nチップに基づいて このモーターシールド を作成しました。 1つのモーターにはピン5と6を使用し、もう1つのモーターにはピン10と11を使用します。

IRリモートでタンクを制御するために TSOP 4838 を追加しようとしているときに、ピン10/11のモーターを逆方向に動かすと全速でしか機能しないことに気づきました-つまり、HIGH(255 )ピン11の値。この値を下回ると、ピン11には何も出力されません(これらのピンで測定された電圧は0 Vです)。

リモートの場合、私は このライブラリ を使用します。 [〜#〜] ir [〜#〜] レシーバーはピン2に接続されています(ただし、ピンは関係ありません)。問題はライブラリコード自体です。 IRリスニングを有効にする行irrecv.enableIRIn();が問題の原因です。内部ArduinoタイマーとシールドによってPWMに使用されるピンの競合があることを学びました。

これは逆にモーターに電力を供給するコードです:

_#include <IRremote.h>

// IR receiver configuration
const int irPin = 2;
IRrecv irrecv(irPin);

// Motors configuration
const int mLeftPin1  = 10;
const int mLeftPin2  = 11;
const int mRightPin1 = 5;
const int mRightPin2 = 6;

void setup()
{
  // Start IR
  irrecv.enableIRIn();

  // Setup motors
  pinMode(mLeftPin1, OUTPUT);
  pinMode(mLeftPin2, OUTPUT);
  pinMode(mRightPin1, OUTPUT);
  pinMode(mRightPin2, OUTPUT);

  // Move left motor in reverse, slower speed
  analogWrite(mLeftPin2, 100); // This works only with 255 instead of 100
  digitalWrite(mLeftPin1, LOW);
}
_

さて、 ここ のタイマーが使用するピンは Arduino Uno であることがわかりました:

  • ピン5および6:Timer0によって制御されます
  • ピン9および10:Timer1によって制御されます
  • ピン11および3:Timer2によって制御

だから私の質問は:

  1. インストラクタブルのシールドがPWMにピン10と11を使用するのはなぜですか?それらは2つの異なるタイマーに対応します。なぜ9と10ではないのですか?

  2. IRをモーターシールドと一緒に使用するには、使用するIRライブラリをどのタイマーで構成する必要がありますか?

  3. 答えが2の場合、_IRremoteInt.h_の行のコメントを外す必要があります。私はUnoが68行目でelse分岐を取ると思いますが、timer1とtimer2しかありません。なぜtimer0が宇野に使えなかったのかしら。

最後の選択肢として、痕跡の切断と再はんだ付けを残したいのですが、別の可能性は、シールドが使用するピンを変更することですが、どれですか?これは、タイマーをデフォルト以外のピンでPWMに構成することとも組み合わせられると思いますが、タイマー/割り込みについては何も知りません。ArduinoとCに関する知識は限られています。

問題を解決するだけでなく、学びたいので、長い質問をしましたので、質問以上に気軽に説明してください。

解決策を探しているときに、 [〜#〜] pwm [〜#〜] またはタイマーを使用するときに留意する必要がある他の競合も見つけました:

  • Timer0は8ビットタイマーで、最大値255を保持できます。delay()およびmillis()、それでそれをいじると結果があります
  • Timer1は16ビットタイマーで、最大65535(符号なし16ビット整数)を保持できます。 Arduinoサーボライブラリはこのタイマーを使用します
  • Timer2は、Arduino tone()関数で使用される8ビットタイマーです

そしてもちろん、IRremoteライブラリは_TIMER_RESET_を使用するため、使用するタイマーによっては、関連するピンと競合する可能性があります。

13
binar
  1. すべてのハードウェアが最良の方法で設計されているわけではありません。 10と11を使用すると、2つのタイマーが必要になるため、実際に無駄になります。

2/3。理想的には、Timer0ではないタイマーを使用します。タイマー/割り込みの詳細は次のとおりです。

Arduinoチップ(328P)には3つのタイマーがあります。各タイマーは複数の用途に使用できますが、タイマーごとに有効にできるタイマー割り込みは1つだけであることに注意してください。

Timer0を例にとってみましょう。 delay()メソッドとdelay_us()メソッドに適切な遅延を生成するために割り込みます。これは、ピン5および6のPWM出力にも使用されます。これは、PWM出力がタイマー割り込みを使用せず、別個の出力比較モジュールを使用するために発生する可能性があります。

ここで特に問題を見ると、should正常に動作します。timer2を使用するPWM出力がある場合でも、PWMはtimer2で割り込みを受け取らないため、IRライブラリはその割り込みを自由に使用できます。ただし、IRライブラリコードを調べると、次のコードが表示されます。

ISR(TIMER_INTR_NAME)
{
   TIMER_RESET; 

中断するたびに、タイマーのカウントがリセットされるようです。これが、PWM出力が正しく機能していない理由である可能性があります。出力比較モジュールは特定のティックカウントを待機しており、それに達することはありません。

なぜ255で機能するのかについて、analogWriteコードを見てみましょう:

void analogWrite(uint8_t pin, int val)
{
    // We need to make sure the PWM output is enabled for those pins
    // that support it, as we turn it off when digitally reading or
    // writing with them.  Also, make sure the pin is in output mode
    // for consistenty with Wiring, which doesn't require a pinMode
    // call for the analog output pins.
    pinMode(pin, OUTPUT);
    if (val == 0)
    {
        digitalWrite(pin, LOW);
    }
    else if (val == 255)
    {
        digitalWrite(pin, HIGH);
    }

したがって、255を書き込むことにより、analogWriteコードはPWMと出力の比較全体を無視し、ピンをHighに書き込むだけです。

最後に、あなたの問題を解決するために、私は個人的に11番ピンと3番ピン(timer2)を使用しない方法をとります。はい、少し再配線する必要がありますが、そうすれば、IRライブラリが使用できるようにtimer2を解放できます。

または、IRライブラリを調べて、カウントをリセットせずに機能させることもできます。

14
user2461391

使用するボードに注意してください。ArduinoUnoを使用する場合、責任のあるコードは次のようになります。// Arduino Duemilanove、Diecimila、LilyPad、Mini、Fioなどelse // define IR_USE_TIMER1 // tx = pin 9 define IR_USE_TIMER2 // tx =ピン3endif

1
sky10

ビルド済みの L298 V2 モーターシールドでも同じ問題が発生しました。

ピンはシールドに次のようにマークされています。

モーター1:ピン3および5モーター2:ピン6および9

私は3ではなくPIN10を使用し、小さな回避策を使用しています。SHIELDにPIN10からPIN3へのワイヤを配置します。私のプロジェクトは、SAMSUNG TVリモコンでロボットを制御することでした。

0
sky10