アフィリエイト広告
アフィリエイト広告

Arduino のマルチタスク (4) サーボモータをクラスで動かす

Arduino のマルチタスクとクラスについて、勉強中です。

Multi-tasking the Arduino - Part 1
Once you have mastered the basic blinking leds, simple sensors and buzzing motors, it’s time to move on to bigger and better projects. That usually involves com...

前回は、C++ のクラスを使用して複数の LED を独立して点滅させてみました。

Arduino のマルチタスク (3) C++ クラス
Arduino のマルチタスクとクラスについて、勉強中です。 前回は、複数のステートマシンを組み合わせて、同時に 2 つのことを実行する方法について学びました。 でもこの方法は、同じコードを何度も繰り返すことになり、無駄があります。俺はそれ...

でもまだまだ、わかったような、さっぱりわからんような (^_^;)

理解を深めるために、今回は、クラスを使ってサーボモータを動かしてみます。

Let’s apply the same principles to some servo code and get some action going.

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-clean-sweep

いつもの方法でサーボモータを動かす

We’ll take the parts we need from it to make a “Sweeper” state machine.

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-clean-sweep

まず、いつもの方法で、いやもちろん delay() は使わない方法、ステートマシンを作って、サーボモータを動かしてみましょう。

サーボモータを動かす回路図

回路図です。

サーボモータって意外と電気食いますから、電源の 5V はしっかりしたものにしましょう。Arduino の 5V 出力は避けたほうがいいです。

電源の 330μF は、ちょっと大きすぎるかも。0.1μF は気分です (^_^;)
どちらもできるだけモータに近いところに付けます。

マルチタスクの演習なので、サーボモータを 2 台動かしたいところですが、部品箱には 1 台しかありません (;´Д`) でした。

スケッチです。

  1. #include <Servo.h>
  2. Servo myservo;
  3. const byte pin = 10;
  4. void setup() {
  5.   myservo.attach(pin);
  6. }
  7. void loop() {
  8.   static const byte updateInterval = 15;
  9.   static unsigned long lastUpdate = 0;
  10.   static byte pos = 0;
  11.   static byte increment = 1;
  12.   if (updateInterval < millis() - lastUpdate) {
  13.     lastUpdate = millis();
  14.     pos += increment;
  15.     myservo.write(pos);
  16.     if (180 <= pos || 0 >= pos) increment = -increment;
  17.   }
  18. }

ここはもう説明するほどの内容ではないです、よね。

2 台のサーボモータを動かすには、「Arduino のマルチタスク (2) 複数のステートマシン」でやったように、2 つ目のステートマシンを作成すればよいです。

サーボモータの制御をカプセル化する

上で作ったスケッチを、クラスにカプセル化してみましょう。

  1. class Sweeper {
  2.   Servo myservo;
  3.   byte updateInterval;
  4.   unsigned long lastUpdate;
  5.   byte pos;
  6.   byte increment;

まず、Sweeper クラスを宣言します。
4 行目は Servo.h ライブラリのオブジェクト myservo を生成します。つまり、このライブラリもクラスを利用しているってことですね。だんだん言葉の意味がわかってきました。
5~8 行目はメンバ変数です。

  1. public:
  2.   Sweeper(byte interval) {
  3.     updateInterval = interval;
  4.     lastUpdate = 0;
  5.     pos = 0;
  6.     increment = 1;
  7.   }

次はコンストラクタで、メンバ変数を初期化します。
コンストラクタはクラス名を関数名とします。引数にサーボモータの制御速度変数 interval を指定していて、interval ミリ秒毎にサーボモータが動作します。ただし、変数の型を byte にしていますので、引数として指定できるのは 0~255 の範囲です。
コンストラクタには戻り値がありません。void も記述しません。

  1.   void Attach(byte pin) {
  2.     myservo.attach(pin);
  3.   }

サーボモータをデジタルピンに関連付けるためのメンバ関数です。

We also need to add Attach() and Detach() functions to associate the servo with a specific pin:

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-clean-sweep

参考にしている Multi-tasking the Arduino – Part 1 では、ピンへの関連付けを解除する Detach() も定義していますが、これ使ってないのでいりません。いらないと思います。たぶん。

  1.   void Update() {
  2.     if (updateInterval < millis() - lastUpdate) {
  3.       lastUpdate = millis();
  4.       pos += increment;
  5.       myservo.write(pos);
  6.       if (180 <= pos || 0 >= pos) increment = -increment;
  7.     }
  8.   }
  9. };

サーボモータを制御するメンバ関数。いつもの方法の loop() に書いていた内容です。

以上で Sweeper クラスのカプセル化ができました。

クラスでサーボモータを動かす

これで、必要なサーボモータの数だけオブジェクトを作ることができるようになりました。生成されたオブジェクトのことをインスタンスとも呼びます。

Sweeper の各インスタンスに必要なコードは 3 行だけです。

Each instance of a Sweeper requires just 3 lines of code:
 ・One to declare the instance
 ・One to attach it to a pin in setup
 ・And one call to update in the loop

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-clean-sweep
  1. #include <Servo.h>
  2. class Sweeper {
  3.   Servo myservo;
  4.   byte updateInterval;
  5.   unsigned long lastUpdate;
  6.   byte pos;
  7.   byte increment;
  8. public:
  9.   Sweeper(byte interval) {
  10.     updateInterval = interval;
  11.     lastUpdate = 0;
  12.     pos = 0;
  13.     increment = 1;
  14.   }
  15.   void Attach(byte pin) {
  16.     myservo.attach(pin);
  17.   }
  18.   void Update() {
  19.     if (updateInterval < millis() - lastUpdate) {
  20.       lastUpdate = millis();
  21.       pos += increment;
  22.       myservo.write(pos);
  23.       if (180 <= pos || 0 >= pos) increment = -increment;
  24.     }
  25.   }
  26. };
  27. Sweeper sweeper1(15);
  28. void setup() {
  29.   sweeper1.Attach(10);
  30. }
  31. void loop() {
  32.   sweeper1.Update();
  33. }

2 台目のサーボモータを制御するには、

  • 32 行目のオブジェクトの生成を増やす
  • 35行目の接続するピン番号指定を増やす
  • 39行目の Update() の呼び出しを増やす

ということです。


では次回は、先に作った Flasher クラスを加えて、LED の点滅とサーボモータの制御を、それぞれ独立して行えるようにしてみましょう。

タイトルとURLをコピーしました