tanaka's Programming Memo

プログラミングについてのメモ。

Arduinoの勉強メモ

息をマイクに吹きかけると、ナースコールボタンを押せるようにする機械が作りたく、Arduinoを勉強することにしました。

手が自由に使えない患者向けにそのような医療用機器があったのですが、設備がない病院もあります。息を吹きかけることでサーボモーターを動かして、ボタンを押すような仕組みが作れないかと考えています。

Raspberry Piの方が性能が高くて音声認識も可能なのですが、今回の用途であればArduinoでも問題がなさそうなので、安さを優先してArduinoにしました。

勉強材料

教材として、以下を購入しました。

Arduinoをはじめよう 第3版 (Make:PROJECTS)

Arduinoをはじめよう 第3版 (Make:PROJECTS)

Arduinoをはじめようキット

Arduinoをはじめようキット

開発は、WindowsmacLinuxのどれでも大丈夫なので、mac book airにしました。

IDEのインストール

  • Arduino - Software から、自分の環境に合わせたソフトウェアをクリック
  • 資金提供をすることが可能。まず使ってみたい場合は、[JUST DOWNLOAD]をクリックして、ソフトウェアを実行する
  • 実行したら、[Arduino]という名前でアプリが解凍されるので、アプリケーションフォルダーなどに移動。zipファイルは削除して良い
  • macとUSBケーブルで接続すると、ONのLEDが点灯、LというオレンジのLEDが点滅する
  • インストールした[Arduino]アプリを起動
  • [ツール]メニューから[シリアルポート]を選択して、[/dev/cc.usbmodem・・・]を選択
  • [ツール]メニューから[ボード]を選択して、[Arduino/Genuino Uno]を選択

最初のスケッチ

スケッチとは、Arduinoを実行するためのプログラムのことです。

LEDを光らせます。点滅しているLのLEDは、簡単に実験できるように最初から乗っている13番ピンに接続されていることになっているLEDです。

LEDの短い足(カソード)をGNDに、長い足(アノード)を13番に指すと、Lと同じ振る舞いをさせることができます。

ポイント

  • 開発言語は、C言語ベースなので、C言語JavaC#などに馴染みがあればすぐに使える
  • pinMode(ピン番号, ) で、ピンの入出力を設定
  • digitalWrite(ピン番号, ) で、ピンの出力をONかOFFに切り替え
  • HIGHは1、LOWは0
  • Example4-2 は、以下のように整理できる
const int LED = 13;
const int BUTTON = 7;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
}

void loop() {
  digitalWrite(LED, digitalRead(BUTTON));
}
  • 物理ボタンは、仕組みの関係でボタンを押した直後にONとOFFが繰り返される場合がある。これをバウンシングという。delay(10)などで遅延させることで、この症状を軽減できる
    • 自分の環境では、delay(100)を入れても時々失敗する。そういうものなのか、自分のボタンの不良なのか、今の所判断つかず。まあ、そんなものということで進める

高度な入力と出力

  • ティルトスイッチ(傾きセンサー)は、「チルト」で探した方が見つかる
  • パルス幅変調(PWM)を使って、LEDの明るさ調整や、モーターの速度調整ができる
    • ONとOFFを細かく繰り返して調整する方法
    • デジタルピンのチルダが描かれているもの(3,5,6,9,10,11)は、ハードウェアのPWMが対応していて、設定をするとloopが停止していても作動する
    • analogWrite(ピン番号, 0~255) で設定。0が0%。255が100%
  • millis()で、Arduinoの時計ボードがリセットされてからの経過ミリ秒を取得できる。型は unsigned long
  • ArduinoRaspberry Piに比べて圧倒的に低速とはいえ、1秒間に1,600万ステップ(16MHzなので)も実行できる。delayやmillis()を使わないとすごい速さでループを繰り返す。単純なセンサーやアクチュエーター相手であれば、十分な速度を持っている
  • Arduino基盤に流す電流は20mA以下にする

アナログ入力

  • アナログピンに刺して、 analogRead(ピン番号)で取得する
  • 0〜5Vの電圧を、0〜1023の値で返す
  • デジタルのようにpinModeによる初期化は不要
  • Unoでは、pinModeでOUTPUTを指定すると、アナログピンをデジタル出力として利用できる。また、digitalRead(A0)などとすると、デジタル入力としても利用できる

PCとシリアル通信

  • Serial.begin(bps数。9600など)で開始
  • Serial.println(値)で送信
  • PC側で、シリアルモニターを表示すれば、値が表示される

モーターや電球などを利用する

  • Arduinoの通常の5Vよりも大きい電圧が必要な場合は、MOSFETを利用する
  • Vinピンで外部電源の電圧が利用できる。VinとGNDと信号をMOSFETに接続して、信号を与えると外部電源の入力を制御することがPWMで利用できるようになる。これで、よくあるモーターや電球を駆動する
  • サーボモーターは4.8Vで動くので、MOSFETは使わず、Arduinoの5Vで良さそう

サーボモーターを動かす

SG-90を利用する場合のヒントです。 その9 Arduinoでサーボモータをキュイキュイ動かす! を参考にしました。

  • コネクタはJRタイプ
    • 茶色:GND
    • 赤:Vcc(+電源)
    • オレンジ:信号線
  • 信号線に、PWMで指示を与えれば良い
  • Servoライブラリで制御可能

まとめ

ここまで、二日もあれば把握できました。書籍の残り半分ぐらいは、仕様解説やリファレンスマニュアルになっているので、知りたいことを索引で調べて見つけることができます。サーボモーターを駆動するServoや、センサやアクチュエーターの通信で出てくるI2C通信するためのWireなど、あると便利な多くのライブラリが最初から使えます。また、外部ライブラリを組み込みむこともできます。

ライブラリが充実しているため、予想していたよりも手間がかかずに簡潔に開発ができる環境でした。ここで紹介している書籍とキットがあれば、基礎を身につけることができると思います。秋月電子さんのページなどに掲載されている多彩なセンサーやアクチュエーターと組み合わせて、大いに楽しめそうです。

マイクロサーボ SG-90 を Arduino で制御する

akizukidenshi.com

akizukidenshi.com

以上を接続して、制御してみます。

駆動にはArduinoの標準ライブラリであるServoを利用します。

配線

シンプルなので、直接Arduinoのpinにサーボモーターのコードをさします。

動作の決定

Servoライブラリでは、以下の2つの関数でサーボモーターを制御できます。

  • write(0〜180)
    • サーボの角度が指示の度数になるように回転させる
    • 連続回転タイプのサーボの場合は、0で振るスピード回転。180で逆方向に振るスピード回転。90で静止
    • SG-90は連続回転タイプではないので、角度のしていになる
  • writeMicroseconds(約1000〜2000)
    • マイクロ秒単位で、角度を指定
    • 標準的なサーボモーターでは、1000で反時計回りいっぱい、1500が中央,2000が時計回りいっぱい。ただし、この範囲外が使えるものもある

writeの0と180の方向や、writeMicrosecondsの意味がよくわからないので、その辺りを試せるスケッチを作成しましょう。以下のステップで動かすことにします。

  • 開始したら、write(0)を実行
  • 2秒待つ
  • write(180)を実行
  • 2秒待つ
  • write(90)を実行
  • 2秒待つ
  • writeMicroseconds(1000)を実行
  • 2秒待つ
  • writeMicroseconds(2000)を実行
  • 2秒待つ
  • writeMicroseconds(1500)を実行
  • 4秒待つ

スケッチの作成

Arduinoアプリを起動して、以下のコードを書きます。

#include <Servo.h>

// サーボのピン番号
const int SERVO_PIN = 9;
// サーボのインスタンス
Servo servo;

// INITがtrueの時は、モーターの位置を0にするだけ
const bool INIT = true;

void setup() {
  // put your setup code here, to run once:
  servo.attach(SERVO_PIN);
  servo.write(0);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (INIT) return;

  servo.write(0);
  delay(2000);
  servo.write(180);
  delay(2000);
  servo.write(90);
  delay(2000);
  servo.writeMicroseconds(1000);
  delay(2000);
  servo.writeMicroseconds(2000);
  delay(2000);
  servo.writeMicroseconds(1500);
  delay(4000);
}

実行

上記のスケッチをビルドして、プログラムを書き込むと、サーボモーターが0の位置に移動して停止します。この状態で、プロペラをわかりやすい位置になるように取り付けましょう。

プロペラが取り付けられたら、以下のようにスケッチ内のINITの宣言をfalseに変更して、ビルドしてプログラムを書き込みます。

const bool INIT = false;

これで、テスト内容が動きます。これにより、SG-90の挙動として以下のことが把握できました。

  • write(0)は、時計回りで端まで動く
  • write(180)は、反時計回りの端まで動く
  • write(90)は、上記の中央に動く
  • writeMicroseconds(1000)は、時計回りで45度ぐらいのところに動く
  • writeMicroseconds(2000)は、反時計回りで135度ぐらいのところに動く
  • writeMicroseconds(1500)は、write(90)と同じ場所になる


以上で、テスト完了です。回転速度が変わるわけでもなさそうで、writeMicroseconds()の使い所がよく分かりませんが、まあそれはいいでしょうということで。write()で進めます。