今回はTIMER割込みを使用して、リアルタイムに複数モーターの回転(速度)制御を個別に行う方法です。
概要
▼回転制御の確認動画▼
▲パソコンからの回転指令をArduinoで受け取ってモーター回転させてます。(この動画はL6470使用してます)
過去にL6470を使用して複数のステッピングモーターを各々で速度制御したことがあるのですが、今回はA4988で行ってみました。
L6470の場合は、SPI通信でコマンドを送信することで回転制御を行うため、複雑な回転制御もコマンドさえ覚えてしまえば割と簡単です。コマンドの使用方法が若干難しいといったことと、(私にとっては)高価などといったことがあります。
対してA4988はパルス信号でモーターを回転させるだけなので使い方は非常に簡単、半面少し凝ったことするには若干スケッチ(ソース)を作りこむ必要があります。非常に安価なのでとソースの工夫次第でいろいろ柔軟に対応できます。(A4988の基本的な使い方はこちら)
モーター制御部分を中心に説明してきたいと思います。
モーター速度制御
冒頭の動画事例ではArduinoで処理する内容がそこそこあります。
①パソコンからの命令をシリアル通信で受信
②受信した情報を処理する
③受信情報より、2個のモーターを回転速度を計算
④モーター(A4988)に回転命令を出す
おおざっぱにこういった処理を繰り返してます。がA4988ドライバは1パルスで1STEP回転するという仕組みのため、メインループの中で複数のモーターを速度制御するのは困難です。(というか私にはスマートな方法がわかりませんでした)
ですので④の処理(パルス発生)についてはTIMER割込みを使って行います。(Arduino(atmega328p)TIMER割込みの使い方はこちら)
▼パルス発生のイメージ▼
こんなイメージです。例えばTIMER割込みの間隔を「1ms」とします。割込み発生するごとにカウントしていき、10カウントでカウントをリセットします。上記の場合では周期10ms(100Hz)のパルスを発生していることになります。
カウント数をメインループ内で調整すればリアルタイムで速度(パルス周期)を可変することが可能。またモーターの数だけカウントを持たせれば複数でも対応可能です。
TIMER割込みの間隔そのものを可変すれば良いのでは?とも思いますが、それだとモーターの数だけTIMERが必要となるので複数のモーターを制御する場合はあまり現実的ではありません。(UNOの場合、1個~2個程度のモーター制御であれば割込み間隔そのものを可変させても良いかと思います。ピン数にも限界がありますし、実質、割込み間隔そのものを可変させるほうが楽かもしれません・・・。)
スケッチ(ソース)例
複数モーターの速度制御のスケッチ例の抜粋です。割込み時の処理です。
ISR (TIMER1_COMPA_vect) { CNT1++; if (CNT1 > 8000) { CNT1 = 0; } if (CNT1 == 1)digitalWrite(3, HIGH); if (CNT1 == 2)digitalWrite(3, LOW); CNT2++; if (CNT2 > 4000) { CNT2 = 0; } if (CNT2 == 1)digitalWrite(4, HIGH); if (CNT2 == 2)digitalWrite(4, LOW); }
この例では割込み間隔は20μ秒ごとに設定して、モーター2個の速度制御を行ってます。
この方法で割と柔軟に複数モーターの制御が可能かと思います。ただ、私のやり方がダメなのか原因がいまいち不明なのですがA4988では低速域でモーター回転がかなり脈打つ感じで微妙です。 倒立振子には、L6470ドライバとどちらを使用するか悩んでます・・。
コメント