今回は電子工作の記事です。
雑記ブログ的にのんびり書いていきたいと思います。
Arduinoでシリアル通信で角度を入力してサーボモーターをその角度に動かしてみました。
簡単に思えるのですが、いろいろと学んだことがあるので備忘録的に書いておこうと思います。
やりたいこと
シリアルモニターで角度を入力してその角度にサーボモーターを動かすことです。
動いたらその角度で静止していてほしいです(下は30°の場合)。

ピンアサイン
ピンは以下のように接続します。

サーボモーターSG90の黄色にDIGITAL 13ピンを接続します。
オレンジのケーブルに3.3V電源、茶色のケーブルにGNDを接続します。
コード
コードは以下です。
#include <Servo.h>
// サーボインスタンスを生成
Servo myServo;
// サーボピンと角度変数を宣言
const int servoPin=13;
int servoAngle;
void setup() {
// put your setup code here, to run once:
// サーボピンにサーボを割り当て
myServo.attach(servoPin);
// 初期角度を設定
servoAngle=0;
myServo.write(servoAngle);
// シリアル通信の通信速度を設定
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
// シリアル通信をしたときのみif文内を実行する
if(Serial.available()>0){
// シリアルモニターで入力した角度にサーボモーターを動かす
servoAngle=Serial.parseInt();
myServo.write(servoAngle);
// 入力した角度を表示する
Serial.print("servoAngle: ");
Serial.println(servoAngle,DEC);
}
}
まずサーボインスタンスを生成し、サーボモーターを操作する準備をします。
続いてサーボピンを割り当て、初期角度を0°にします。
シリアルモニターを使うためにシリアル通信の通信速度を設定します。
これらは初期設定なので1回しか実行しません。
よってsetup関数内に書きます。
loop関数でモーターを動かします。
Serial.parseInt()でシリアルモニターに入力した整数を読み取ります。
Servoインスタンスのwriteメソッドで読み取った角度をサーボモーターに指示します。
これでサーボモーターが指示された角度に動きます。
シリアルモニターの設定を”No Line Ending”にしないと0°に戻る
ところが上記のコードでシリアルモニターで角度を入力して動かしても一定時間経過後にサーボの角度が0°に戻ってしまいました(下の動画)。
やりたいのは入力した角度にとどまることなのでこれでは困ってしまいます。
どうやらこれは、シリアルモニターの設定が”New Line”になっているのと、Serial.parseIntが、bufferにあるデータが有効でない場合にタイムアウト時間経過後に0を出力するようになっているのが原因みたいです。

シリアルモニターの設定が”New Line”だとEnter(改行)もArduinoのbufferに送られます。
シリアルモニターで角度を入力してEnterを押す
↓
角度の情報がArduinoのbufferに送られる
↓
if文の条件であるSerial.available()>0がtrueになる
↓
if文内が実行されてサーボモーターが入力した角度に動く
↓
設定が”New Line”なのでEnterもArduinoのbufferに送られる
↓
if文の条件であるSerial.available()>0がtrueになる
↓
if文内が実行されるが、EnterはparseIntにとって有効なデータではないのでタイムアウト時間が経過してparseIntは0を出力する
↓
サーボモーターの位置が0°になる
これを解決するにはシリアルモニターの入力ボックスのすぐ横にあるプルダウンで”No Line Ending”にすればいいだけです。こうするとEnter(改行)がArduinoに送られなくなります。

※上記はArduinoの英語版リファレンスに偶然たどり着いて知ったことです。やはりリファレンスを読むのは大事ですね。
成功
実際に動かしてみると成功しました。
動画では4秒あたりで90°に動かしています。
90°でそのまま静止しています。


コメント