ミルクパック マイコンロボットの作り方2(プログラム改造編)

ミルクパック マイコンロボットキットは、マイコンにプログラムが書き込まれているので、組み立てれば遊ぶことができますが、プログラムを改造することで、LEDの色を変えたり、スピードを上げたり、オリジナルのロボットにすることができます。

前回は組み立て、工作編でした。

ここでは、そのプログラムの改造の仕方をご紹介します。

Arduinoのインストール

マイコンのプログラムは、Arduionのという世界的に有名なプログラム言語で作られています。情報が多く、インターネットや書籍で簡単に調べることができるので、マイコンのプログラム言語の入門としては最適です。

Arduinoでプログラムをするには、Arduino IDEという開発環境(プログラムを書いたり、マイコンに書き込んだりすることができるソフト)をパソコンにインストールして、ちょっと設定が必要です。

牛乳パックロボットのマイコンボードは、Arduinoの中でLeonardo(レオナルド)というマイコンボードと同様のマイコンボードとなっていますので、Arduinoをインストールして、Leonardo用に設定を変更します。

Arduinoのインストールと、Leonardoの設定はこちらをご覧になって設定してください。

プログラムの改造

プログラムのダウンロード

ミルクパック マイコンロボットのプログラムはこちらです。

このzipファイルをダウンロードをして、展開すると、「milkpackRobot」というフォルダが現れます。

このフォルダの中を開くと、牛乳パックロボットのプログラムが入っています。

この「milkPackRobot.ino」をクリックすると、Arduino IDEが起動して、プログラムを改造することができるようになります。

プログラムの改造の手順

プログラムの改造の手順はこの2段階となっています。

  1. Arduino IDEでプログラムを改造する
  2. コンパイル&プログラムの書き込みを行う

簡単に改造できることは以下の通りです。

  • モーターのスピードを変える
  • LEDの色を変える
  • LEDの明るさを変える
  • まばたきの間隔を変える
  • サーボモーターのスピードを変える
  • サーボモーターの角度範囲を変える
  • ちょこちょこ動く時のちょこちょと間隔を変える
  • リモコンのボタンを押された時の動作を変更する(上級者向け)

どうやって改造するか、もっともわかりやすい改造としてLEDの色を変更しながら方法をご説明します。

Arduino IDEでプログラムを改造する

 

プログラムの18行目から20行目を見てください。

int ledR = 0; //赤のLED 0:OFF 1:ON
int ledG = 1; //緑のLED 0:OFF 1:ON
int ledB = 1; //青のLED 0:OFF 1:ON

とあります。このledRは赤いLEDを点灯させるかどうかを設定します。同様にledGは緑のLED、ledBは青いLEDを点灯させるかどうかの設定です。0だとOFF、1だとONします。

赤、緑、青の3つの色のON、OFFを組み合わせることで、下の表のように、いろんな色に変更することができます。

LEDの色ピンク水色
ledR01010101
ledG00110011
ledB00001111

最初の設定では、ledR = 0、ledG = 1、ledB = 1となっているので、LEDは水色に光っています。

試しに、ピンクにしてみましょう。ピンクは表によると、ledR = 1、ledG = 0、ledB = 1です。プログラムを以下のように改造します。

int ledR = 1; //赤のLED 0:OFF 1:ON
int ledG = 0; //緑のLED 0:OFF 1:ON
int ledB = 1; //青のLED 0:OFF 1:ON

コンパイル&プログラムの書き込みを行う

改造ができたら、左上の右矢印をクリックすると、プログラムがマイコンの命令に変換(コンパイルと言います)されて、マイコンに書き込まれます。

水色に光っていたLEDが一旦消えて、ピンクに光り出します。

プログラムの改造が成功しました。

エラーが出た場合

全角で数字を入力してしまった場合

このようなエラーが出た場合、全角の文字「0」「1」で数字が書かれています。プログラムは半角の文字しか使えないので、日本語入力を英語入力に変更して「0」「1」で書き直してください。
マイコンが接続されていない場合

「スケッチ書き込み通にエラーが発生しました」と表示された場合は、マイコンとパソコンがUSBで接続されていません。
[ツール]->[シリアルポート]でマイコンがつながっているシリアルポートを指定します。macの場合は、usbmodem****(*は数字)と表示されています。windowsの場合には、COM**(*は数字)となっています。

その他の改造項目

LEDの色と同じように、上の場所の数字を変更することで、

  • モーターのスピード
  • LEDの色
  • LEDの明るさ
  • まばたきの間隔
  • サーボモーターのスピード
  • サーボモーターの角度範囲
  • ちょこちょこ動く時のちょこちょこ間隔

を簡単に変更できます。ぜひ、いろいろ変更して、プログラムの改造を楽しんでください。

ロボットプログラムの構成

ロボットのプログラムは常にループ

ロボットのプログラムは単純化すると以下のようになっています

  1. センサの情報を取得
  2. どう動くか決める
  3. モーター、サーボなどを動かす

この3つを高速に繰り返して、細かい時間間隔ごとにロボットが動いています。この間隔を制御周期と言います。普通のロボットは、1秒間にだいたい100回程度の速さでこのループを繰り返していますが、工場のロボットのようなもっと高速で精密な動作が必要なロボットは、1秒間に1000回以上で繰り返しています。牛乳パックロボットでは、そこまで速くなくてもいいので、1秒に10回程度とゆっくりした速度でループしています。

このループを、牛乳パックロボットのプログラムに当てはめると、

  1. リモコンのどのスイッチが押されているかチェック
  2. スイッチの組み合わせによってモーターの方向を決める
  3. サーボを動かしたりやまばたき動作をする

となっています。

リモコンのどのスイッチが押されているかチェック

プログラムの132行目の「リモコン判定」という行から163行目までが、そのプログラムとなります。

リモコンのスイッチは、上と下のスイッチ、左と右のスイッチでペアになっていて、それぞれ

  • 何も押されていない場合:5V
  • 上(左)が押された場合:3V
  • 下(右)が押された場合:2.5V
  • 上(左)と下(右)両方押された場合:1.9V

のような電圧となります。この信号をADコンバータでデジタル値に変換します。

 int upDownSwitch_ADValue = analogRead(UpDownSwitchPin);     //前後ボタンの入力ピンの読み取り
  int LRSwitch_ADValue = analogRead(LRSwitchPin);     //左右ボタンの入力ピンの読み取り

この値を、if文によって区別して、どのボタンが押されたが判定しています。

 if( upDownSwitch_ADValue < switchADValue_AB ) { //ADした値がswitchADValue_AB値よりも小さかったらup Dowm両方押されている
    upSwitch = 1;
    downSwitch = 1;
  }else if( upDownSwitch_ADValue < switchADValue_B ) { //ADした値がswitchADValue_B値よりも小さかったらDowmが押されている
    upSwitch = 0;
    downSwitch = 1;
  }else if( upDownSwitch_ADValue < switchADValue_A ) { //ADした値がswitchADValue_A値よりも小さかったらupが押されている
    upSwitch = 1;
    downSwitch = 0;
  }else { //ADした値がa値よりも大きかったら何も押されていない
    upSwitch = 0;
    downSwitch = 0;
  }

スイッチの組み合わせによってモーターの方向を決める

上下左右どのスイッチが押されているかわかったので、その組み合わせで、どう動くのか決めます。プログラムでは、170行目「リモコンの応じて動作」から438行目までとなっています。

例として、187行目からの上が押された時のプログラムをみてみます。

 if( upSwitch == 1 & downSwitch == 0 & RSwitch== 0 & LSwitch== 0 ) {

ここでは、スイッチの押されている組み合わせを指定します。upSwitch == 1 & downSwitch == 0 & RSwitch== 0 & LSwitch== 0
と書くと、上スイッチがONで、下スイッチが0FFで、右スイッチがOFFで、左スイッチがOFFの時、すなわち上スイッチだけ押されている時となります。

この時に、

//LEDの色を指定する指定する
digitalWrite(ledRPin, ledR);
digitalWrite(ledGPin, ledG);
digitalWrite(ledBPin, ledB);

各LEDの色をもともと設定しておいた値にします。

//モーターのスピードを指定する
analogWrite( motorR_PWMPin, speedR );
analogWrite( motorL_PWMPin, speedL );

モーターのスピードをもともと設定しておいた値にします。

//前進する
digitalWrite(motorR_APin, HIGH);
digitalWrite(motorR_BPin, LOW);
digitalWrite(motorL_APin, HIGH);
digitalWrite(motorL_BPin, LOW);

モーターにはAとBの2つの信号があって、AをON(HIGH)、BをOFF(LOW)にするとモーターが前進し、AをOFF(LOW)、BをON(HIGH)にするとバックします。A,B両方OFF(LOW)にするとモーターが停止します。

このプログラムでは前進したいので、両方のモーターのAをON、BをOFFして、前に進みます。

//両腕の角度を変える
servoRAngle = servoRAngle + servoSpeed;
servoLAngle = servoLAngle + servoSpeed;

サーボモーターの角度を計算します。現在の角度(servoRAngle)に、もともと設定しておいた角度(servoSpeed)を足し合わせます。これで角度が増えて、サーボの腕の角度が変化します。

このように、スイッチの状態によって、これからの動作を決定しています。

ちょっとおもしろ機能として、上と下を両方押すとダッシュ、右と左を両方押すとちょこちょこ動く、隠し動作があります。
「ダッシュ」の場合のプログラムは417行目からになります。

//--- 上と下が両方押されていた時の動作 ---
if( upSwitch == 1 & downSwitch == 1 & RSwitch== 0 & LSwitch== 0 ) {
  
  //LEDを赤くする
  digitalWrite(ledRPin, HIGH);
  digitalWrite(ledGPin, LOW);
  digitalWrite(ledBPin, LOW);

  //モーターのスピードを最大にする
  analogWrite( motorR_PWMPin, 255 );
  analogWrite( motorL_PWMPin, 255 );

LEDを強制的に赤に設定して、モーターのスピードも強制的に255と最大にしています。これで、目が赤く光って、最大速度でダッシュします。

サーボを動かしたりやまばたき動作をする

プログラムの442行目「LED まばたき動作」から479行目までになります。

まずは、まばたき動作から
mabatakiCounter = mabatakiCounter -1; //まばたきカウンターを1減らす
if( mabatakiCounter == 1 ) {          //まばたきカウンターが1だったらLEDを消してまばたきする
  
  ledRSave = digitalRead(ledRPin);     //現在のLEDの色を保存する
  ledGSave = digitalRead(ledGPin);
  ledBSave = digitalRead(ledBPin);
  
  digitalWrite(ledRPin, LOW );        //LEDを消してまばたきする
  digitalWrite(ledGPin, LOW );
  digitalWrite(ledBPin, LOW );
}

まばたきは、最初に作られたランダムな値をループが1回終了するごとに1減らしていって、最後の1だけ残っている時に、LEDをOFFします。こうすることで、ランダムな時間に1回、LEDがOFFしてまばたきしているように見えます。

if( mabatakiCounter <= 0 ) {          //まばたきカウンターが0以下になったらLEDを光らせて
  digitalWrite(ledRPin, ledRSave);
  digitalWrite(ledGPin, ledGSave);
  digitalWrite(ledBPin, ledBSave);
  
  mabatakiCounter = random(mabatakiMin, mabatakiMax);    //ランダムな数をカウンターにセットする    
}

OFFにした次の周期には、LEDをもともと設定した色に変更します。そして、次のまばたきのまでの時間をランダムに設定します。

サーボで腕を振る
servoRAngle = servoRAngle % 360;  //角度の値を0から360の範囲にする
servoLAngle = servoLAngle % 360;

int servoRAngleTemp = sin( (double)servoRAngle/180.0*3.14 )*servoMax+90;  //90度を中心にプラスマイナス指定した角度の範囲内で角度が変化する
int servoLAngleTemp = sin( (double)servoLAngle/180.0*3.14 )*servoMax+90;

複雑な式を使って、サーボモーターの角度が前後に揺れるように、角度を計算しています。

servoR.write(servoRAngleTemp);  //サーボに角度を設定する
servoL.write(servoLAngleTemp);

その角度を、サーボに伝えて、角度を変更します。

ループの時間間隔

このロボットのループは1秒間に10回です。この時間の間隔を決めているのが、489行目です。

 delay(100);

delay(100)は100ミリ秒待つという、命令です。100ミリ秒は1秒に10回を意味しています。

100を10にすることで、ループの時間が10ミリ秒になり、1秒間に100回ループを繰り返えすようになります。10にすることで、ループが速くなるため、まばたきが速くなり、腕を振るスピードが速くなります。

逆に1000にすると、ループが遅くなるため、リモコンの反応が鈍くなり、まばたきや腕を振るスピードが遅くなります。

スイッチを押された時の動きを改造

上級者向きですが、スイッチを押された時の動作を改造してみましょう。

戦車のように方向転換する

右のスイッチが押されると右に動いて、左のスイッチが押されると左に動きますが、この時モーターがどう動いているかというと、

右に動く時

  • 左のモーターは前進
  • 右のモーターは停止

左に動く時

  • 左のモーターは停止
  • 右のモーターは前進

しています。こうすることで、右に動いたり、左に動いたりしているのですが、もっと急に曲がるように改造できます。停止しているモーターを逆に回転されることで、戦車のように、その場で回転できるようになります。

右に動く時

  • 左のモーターは前進
  • 右のモーターは逆回転

左に動く時

  • 左のモーターは逆回転
  • 右のモーターは前進

と改造します。それでは改造してみましょう。

まずは235行目「右が押されていた時の動作」以降の248行目から251行をみてみす。

//左のモーターを回して右に回転する
digitalWrite(motorR_APin, LOW);
digitalWrite(motorR_BPin, HIGH);
digitalWrite(motorL_APin, HIGH);
digitalWrite(motorL_BPin, LOW);

motorR_BPinを「HIGH」に改造します。これで右のモーターが停止から逆回転に改造できました。

さらに、258行目「左が押されていた時の動作」以降の271行目から274行目をみてみます。

digitalWrite(motorR_APin, HIGH);
digitalWrite(motorR_BPin, LOW);
digitalWrite(motorL_APin, LOW);
digitalWrite(motorL_BPin, HIGH);

motorL_BPinを「HIGH」に改造します。これで左のモーターが停止から逆回転に改造できました。

これで、改造は完了です。

左上の右矢印ボタンをクリックして、コンパイル&マイコンに書き込んでみましょう。

右、左のボタンを押すと、その場で回転するようになりました。

このように、いろいろ改造することが可能です。もしコンパイルでエラーが出て、どうにもできなくなったら、また、元のプログラムをダウンロードして、それから改造してみてください。

このプログラムで遊べるロボットは、こちらで販売しています

コメント