レーザー話が多かったので久々に別のことを書いてみようと思います。
ArduinoはLEDの制御システムなどで良く使ってはいるのですが先日サーボーモーターを扱うことがあり、簡単に動きそうでなかなかうまくいかずはまったことがあったので、そのことを残しておきます。
【動きをもっと滑らかに、細かく制御したい – 基礎】
通常サーボモーターを動かす場合、こう記述するかと思います。
#include <Servo.h> Servo servo; void setup(){ servo.attach([サーボ制御で使うピン番号]); angle = 120; // 0から180の値 servo.write(angle); } void loop(){}
通常はこの書き方がだと角度で指定できるしとても簡単で良いのですが、もっと細かい角度で制御したい場合には
writeMicroseconds();
を使うと可能です。
ただ、この場合角度指定と違い、どの値がどの角度になるかは試してみないとわからなくなってしまいます。
リファレンスにもあるように、通常は1000から2000の範囲をとるようですが、サーボモーターによっては700から2300の値をとるものもあり、使う際にはどの範囲をとるのか検証が必要です。
実際に私が使ったものも1000から2000の範囲に収まらないものがありました。
Arduino リファレンス:
https://www.arduino.cc/en/Reference/ServoWriteMicroseconds
このようにwriteMicroseconds()は検証が面倒ですが設定できる値が細かいので動きが滑らかになります。
【連続的に動かない】
深堀りできていないですが、loop関数内で連続的に動かす場合、delay()を挟まないと動きませんでした。delayでなければ動かないというわけではないと思いますが、値を指定してから実際にその値の位置まで動くには時間がかかるため、その差を delayで埋めてあげる必要があるのではないかと思います。
これはサーボの種類やほかの実装とも関連しあうと思うのですが、私の場合はdelay(15); が必要でした。
【動きがカクカクしてしまう – 外部からの制御】
シリアルから連続的に値を受け取り、パースして得た値をもとにサーボの制御を行うプログラムを書いていました。
これでうまく動くと思っていたのですが実際は処理が重いのか、シリアルをつなぐとサーボの動きがカクカクして、外すと滑らかに動くという現象がありました。
原因は、SoftwareSerialを使っていたことでした。本来はハードウェアシリアル(TX,RXピンを使うもの)を使って通信するべきなのですが、開発中はUSB経由で値を取得してデバッグするためにハードウェアシリアルはPCと接続するために使っていました。
ただ、ハードウェアシリアルに比べてソフトウェアシリアルは相当処理が重いようで、特に標準のSoftwareSerialは調べてみるとなるべく使わないように、と書かれている記事もありました。
( https://arduino.stackexchange.com/questions/34126/whats-the-difference-between-all-the-software-serial-libraries-which-one-is-ar )
標準のSoftwareSerialの代替として
AltSoftSerialや
NeoSWSerialが
推奨されていましたが、私の状況では問題が改善されなかったのでデバッグの手間はかかるしプログラムの書き込みも手間がかかってしまいますが、ハードウェアシリアルを使うことにして改善しました。
とはいえこれもArduinoのスペック(秋月のArduino Pro mini 5Vを使っていました)によると思うのでサーボの数が増えるとハードウェアシリアルでもカクカクするのではないか?と懸念しています。
さらに、私のケースではサーボを6つ使い、またシリアルは無線経由で取得していたので他の問題もあったのですが、、、、、それはまた別の機会に書こうと思います。