LEGO Wall-E with Arduino
コンポーネントと消耗品
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 3 | ||||
| × | 20 |
必要なツールとマシン
> |
|
アプリとオンラインサービス
> |
|
このプロジェクトについて
映画「ウォーリー」(知らない場合は、今すぐ見に行ってください!)と、地球をきれいにしようとしている黄色いヒーローを誰もが知っています。このプロジェクトでは、私は小さな友達のレゴバージョンを使用して、障害物を回避する方法を彼に教えました。これは私の最初のプロジェクトであり、電子機器の基礎を理解するための素晴らしい学習体験でした。
ステップ1-コード
貿易によるソフトウェア開発者として、私は彼に何をしてほしいかを考え、コードから始めました。
//このプログラムは、Wall-Eレゴロボットを制御するためのものです。//Wall-Eが走り回っています。障害物を見つけると、彼は周りを見回して別のパスを選択します。//ArduinoNanoには、digitalReadおよびdigitalWriteに使用できる21個のピンがあります// PWMピン3、5、6、9、10、11はに使用できますanalogWrite //ピン0と1はTTLに使用できます//ピン2と3は外部割り込みに使用できます//ピン10、11、12、13はSPI通信をサポートします//ピン13は内部LEDになります//ピン14から21はアナログピンA0〜A7でもあり、analogRead#define INFRA_RED 9に使用できます//任意のpin#define GREEN_LED 7 //任意のピンにできますが、抵抗が必要です。おそらく220オーム-またはグランドピンは1 kOhm#になりますdefine RED_LED 8 //任意のピンにすることができますが、抵抗が必要です。おそらく220オーム-またはグランドピンは1 kOhm#define BUZZER 10 //周波数を設定するにはPWMピンである必要があり、抵抗が必要です。おそらく1 kOhm // MRは右モーター、MLは左モーターです。#defineMR_1 A1 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう。#define MR_2 A2 //任意のピンにすることができるので、 p L289Nシールドの番号で#defineMR_ENABLE 5 //速度制御にはPWMピンである必要があります#defineML_1 A3 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう#defineML_2 A4 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう。#defineML_ENABLE 6 //速度制御にはPWMピンである必要があります//通常の速度をmaximumconstに設定しますintNORMAL_SPEED =255; void setup(){ //リセットボタンを押した直後に、少し待って、電圧スパイクによるコンポーネントの損傷なしに彼をオフにできるようにしますdelay(2000); // LEDとブザーを初期化しますpinMode(GREEN_LED、OUTPUT); pinMode(RED_LED、OUTPUT); // pinMode(BUZZER、OUTPUT); //不要// LEDを緑色にリセットdigitalWrite(RED_LED、LOW); digitalWrite(GREEN_LED、HIGH); // DCモーターピンを設定しますpinMode(MR_ENABLE、OUTPUT); //モーター右pinMode(MR_1、OUTPUT); pinMode(MR_2、OUTPUT); pinMode(ML_ENABLE、OUTPUT); //モーター左pinMode(ML_1、OUTPUT); pinMode(ML_2、OUTPUT); //赤外線を初期化しますpinMode(INFRA_RED、INPUT); //ランダムターンの乱数ジェネレータを初期化しますrandomSeed(analogRead(0)); // hello playHello();} void loop(){//通常の操作driveForwards(NORMAL_SPEED); // LEDを緑色に設定digitalWrite(RED_LED、LOW); digitalWrite(GREEN_LED、HIGH); //障害物をチェックif(digitalRead(INFRA_RED)==LOW){// LOWは障害物が検出されたことを意味します// LEDを赤に変更しますdigitalWrite(GREEN_LED、LOW); digitalWrite(RED_LED、HIGH); //モーターを停止しますstopDriving(); // uh-ohサウンドを再生しますplayUhOh(); //左をチェックturnLeft(500);ブール障害Left =false; if(digitalRead(INFRA_RED)==LOW){obstructionLeft =true; } //中央に戻るdelay(100); turnRight(500); //少し待ってください、急いでいるように見えたくないdelay(500); //右をチェックturnRight(500);ブール障害Right =false; if(digitalRead(INFRA_RED)==LOW){obstructionRight =true; } //中央に戻るdelay(100); turnLeft(500); //ここから抜け出す方法を確認しますif(obstacleLeft &&障害物Right){driveBackwards(NORMAL_SPEED / 3); //(int i =0; i <5; i ++){tone(BUZZER、1000、500);の場合、5秒間後方に移動しながらビープ音を鳴らします。 delay(1000); } //どこかで立ち往生するのを避けるために、旅を続ける前にランダムに方向を変えてくださいrandomTurn(800、1600); } else if(obstacleLeft){turnRight(1000); } else if(obstacleRight){turnLeft(1000); } else {randomTurn(1000、1800); }} //相互作用を増やすためにランダムな処理を行うintnumber =random(100); // 0から99までの乱数を作成しますif(number ==0){randomTurn(200,2000); }} void driveForwards(int speed){//モーターを同じ方向に移動するように設定digitalWrite(MR_1、LOW); digitalWrite(MR_2、HIGH); digitalWrite(ML_1、HIGH); digitalWrite(ML_2、LOW); setSpeed(speed);} void driveBackwards(int speed){//モーターを反対方向に移動するように設定digitalWrite(MR_1、HIGH); digitalWrite(MR_2、LOW); digitalWrite(ML_1、LOW); digitalWrite(ML_2、HIGH); setSpeed(speed);} void turnLeft(int duration){//右輪で前進して左に曲がり、左輪で後ろに曲がるdigitalWrite(MR_1、HIGH); digitalWrite(MR_2、LOW); digitalWrite(ML_1、HIGH); digitalWrite(ML_2、LOW); //速度を落とし、setSpeed(NORMAL_SPEED / 2);をオンにします。 delay(duration); stopDriving();} void turnRight(int duration){//右のホイールで後方に移動し、左のホイールで前方に移動して右に曲がるdigitalWrite(MR_1、LOW); digitalWrite(MR_2、HIGH); digitalWrite(ML_1、LOW); digitalWrite(ML_2、HIGH); //速度を落とし、setSpeed(NORMAL_SPEED / 2);をオンにします。 delay(duration); stopDriving();} void stopDriving(){//すべてのモーターピンをオフにしますdigitalWrite(MR_1、LOW); digitalWrite(MR_2、LOW); digitalWrite(ML_1、LOW); digitalWrite(ML_2、LOW); // ENABLEピンをどうするかわからないが、それらをオフにしても問題はない。digitalWrite(MR_ENABLE、LOW); digitalWrite(ML_ENABLE、LOW);} void setSpeed(int speed){//速度は0から255の間でなければなりませんspeed =constant(speed、0、255); //モーターをオンにする速度を設定しますanalogWrite(MR_ENABLE、speed); analogWrite(ML_ENABLE、speed);} void randomTurn(int minimum、int maximum){unsigned long time =millis(); int期間=ランダム(最小、最大); if(time%2){turnRight(duration); } else {turnLeft(duration); }} void playHello(){tone(BUZZER、262、250); // C4 delay(300);を再生しますトーン(ブザー、330、250); // E4 delay(300);を再生しますトーン(ブザー、392、250); // G4 delay(300);を再生しますトーン(ブザー、523、500); // C5を再生しますdelay(550);} void playUhOh(){tone(BUZZER、523、250); // C5 delay(300);を再生しますトーン(ブザー、415、500); // Gis4 delay(600);}
を再生します
動作中のモーターを切断すると、電圧スパイクが発生し、電子機器が損傷する可能性があります。したがって、私はWall-Eに2秒間待機させてから、彼が何かをします。つまり、Arduinoのリセットボタンを押すだけで、何も損傷することなくバッテリーをすばやく切断できます。
彼は目を覚ますと運転を開始するときに少しメロディーを演奏します。彼は障害物を見ると立ち止まり、「うーん」という音を鳴らし、周りを見回して最善の方法を決定します。私が使用したタイプの赤外線センサーの背面には、信号を生成する距離を決定するための小さなネジがあります。そのため、コードには距離の計算がありません。 (最初に超音波センサーを使用したかったのですが、彼の目には合いません。)
Wall-Eは、最初に左側がクリアであるかどうかをチェックし、次に右側がクリアであるかどうかをチェックします。両側が塞がれていると、工事現場で重機のようにビープ音を鳴らしながら後退し、ランダムな方向に向きを変えて進みます。片側だけがブロックされている場合、彼は反対側に進みます。両側が空いている場合、彼はランダムに1つを選び、続行します。
私は彼にランダムなターンをさせようとしましたが、その部分はまだ完全ではありません。内蔵のArduinoタイマーを使おうとしています。最適化する方法があれば、コメントで教えてください!
ステップ2-彼を配線する
まず、赤外線センサーを目に組み込んで、目立たないようにすることでした。私はそれを分解し、レゴピンをセンサーに超接着して(彼の目が上下に動くことができるように)、青いタックを使用してレゴのピースをセンサーの周りに戻しました:
ウォーリーのホイールのセットアップは動くのにかなりの力を必要とするので、モーターについて最も重要なことは、それらが十分なトルクを持っているということでした。ワイヤーをモーターにはんだ付けし、レゴにしっかりと接続するように取り付ける必要がありました。そこで私は彼の車輪を分解し、レゴテクニックのピンでいっぱいのバッグ全体を注文し、モーターシャフトの周りに絆創膏テープを巻き付け(それはあなたの肌に付着する可能性のある柔らかいテープのようなものです)、2つのピンに貼り付けましたそれが各ホイールのメインアクスルになりました。これは数分間機能しましたが、摩擦が高すぎてテープの接着剤を保持できませんでした。幸いなことに、Technicピンの側面には小さな溝があるので、テープには保持する場所がありました。これは、瞬間接着剤に浸した後、喜んで行いました。
私はまた、LEDを突き刺すために彼の胸を少し外しました。次に、すべてのパーツとArduinoを接続しました。
モーターシールドちょうど おなかにフィットする:
ダイアグラムもあまり明確ではありませんが、概要をわかりやすくするために、ワイヤーを色分けしてみました:
慣例に従い、すべての赤い線は正(「電気を送る」)で、すべての黒い線は負(「電気を受け取る」)です。右上の黄色いワイヤーは、赤外線センサーの信号を伝送します。オレンジと緑のワイヤーは3ピンの2色LED用で、紫色のワイヤーはモーターシールドにモーターを回転させる方向を指示し、青色のケーブルはモーターシールドにモーターを回転させる速度を指示します。
>モーターシールドには、接続と使用を簡単にする非常に優れたチュートリアルがありました。残念ながら、フリッツの部分には速度を設定するための2つのピンがなかったため、青いケーブルは図のモーターシールドにランダムに配置されます。
すべてをくっつけているときに直面したもう1つの問題は、電圧ピンと接地ピンの不足でした。モーターをモーターシールドから直接供給して、できるだけ多くの電力を供給できるようにしたかったのですが、どういうわけか、Arduinoと赤外線センサーにも5Vを供給しなければなりませんでした。だから私はウェブ上のほとんどの人がすべきではないと言ったことをしました:モーターシールドの5V出力を入力としてArduinoの5Vピンに接続しました。私が使用しているシールドを使用すると、Arduinoに損傷を与える可能性のある厄介なスパイクがなく、安定化された5Vを出力することを絶対に確信できます。安定していない電源をそのピンに接続すると、おそらく何かを揚げることになります。最初はVinピンを使いたかったのですが、そこにはすべてを調整するメカニズムが組み込まれているので、5Vは3.8V程度になり、Arduinoが正しく機能するには不十分です。代わりに、ケーブルスプリッターがなく、そこから5Vが出てくることもわかっていたので、無料のVinを使用して5Vで赤外線センサーに電力を供給しました(!)。ええ、それはこの時点でフランケンシュタインのように少し感じ始めました。しかし、うまくいきました!
ステップ3-Wall-Eの動作
これが彼の行動を示すビデオです:
そして、ここで私は彼が隅で立ち往生した場合に彼が何をするかをテストしました:
それで、これは私の最初の小さなプロジェクトでした。私は今、ケーブル接続を最適化し、おそらく彼が頭を回せるようにサーボモーターを追加することを計画しています。スプリッターと小さなモーターシールドとボードを購入して、すべてを彼のおなかに収めることもできます。
そして そう ウォーリー 生きた 幸い これまで 後。 終了。
コード
- Wall_e_control
Wall_e_control Arduino
これはWall-Eの中央制御ファイルです。基本ですが、現時点で必要なのはすべてです。//このプログラムはWall-Eレゴロボットを制御するためのものです。//Wall-Eが走り回っています。障害物を見つけると、彼は周りを見回して別のパスを選択します。//ArduinoNanoには、digitalReadおよびdigitalWriteに使用できる21個のピンがあります// PWMピン3、5、6、9、10、11はに使用できますanalogWrite //ピン0と1はTTLに使用できます//ピン2と3は外部割り込みに使用できます//ピン10、11、12、13はSPI通信をサポートします//ピン13は内部LEDになります//ピン14から21はアナログピンA0〜A7でもあり、analogRead#define INFRA_RED 9に使用できます//任意のpin#define GREEN_LED 7 //任意のピンにできますが、抵抗が必要です。おそらく220オーム-またはグランドピンは1 kOhm#になりますdefine RED_LED 8 //任意のピンにすることができますが、抵抗が必要です。おそらく220オーム-またはグランドピンは1 kOhm#define BUZZER 10 //周波数を設定するにはPWMピンである必要があり、抵抗が必要です。おそらく1 kOhm // MRは右モーター、MLは左モーターです。#defineMR_1 A1 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう。#define MR_2 A2 //任意のピンにすることができるので、 p L289Nシールドの番号で#defineMR_ENABLE 5 //速度制御にはPWMピンである必要があります#defineML_1 A3 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう#defineML_2 A4 //任意のピンにすることができるので、L289Nシールドのピン番号に対応させましょう。#defineML_ENABLE 6 //速度制御にはPWMピンである必要があります//通常の速度をmaximumconstに設定しますintNORMAL_SPEED =255; void setup(){ //リセットボタンを押した直後に、少し待って、電圧スパイクによるコンポーネントの損傷なしに彼をオフにできるようにしますdelay(2000); // LEDとブザーを初期化しますpinMode(GREEN_LED、OUTPUT); pinMode(RED_LED、OUTPUT); // pinMode(BUZZER、OUTPUT); //不要// LEDを緑色にリセットdigitalWrite(RED_LED、LOW); digitalWrite(GREEN_LED、HIGH); // DCモーターピンを設定しますpinMode(MR_ENABLE、OUTPUT); //モーター右pinMode(MR_1、OUTPUT); pinMode(MR_2、OUTPUT); pinMode(ML_ENABLE、OUTPUT); //モーター左pinMode(ML_1、OUTPUT); pinMode(ML_2、OUTPUT); //赤外線を初期化しますpinMode(INFRA_RED、INPUT); //ランダムターンの乱数ジェネレータを初期化しますrandomSeed(analogRead(0)); // hello playHello();} void loop(){//通常の操作driveForwards(NORMAL_SPEED); // LEDを緑色に設定digitalWrite(RED_LED、LOW); digitalWrite(GREEN_LED、HIGH); //障害物をチェックif(digitalRead(INFRA_RED)==LOW){// LOWは障害物が検出されたことを意味します// LEDを赤に変更しますdigitalWrite(GREEN_LED、LOW); digitalWrite(RED_LED、HIGH); //モーターを停止しますstopDriving(); // uh-ohサウンドを再生しますplayUhOh(); //左をチェックturnLeft(500);ブール障害Left =false; if(digitalRead(INFRA_RED)==LOW){obstructionLeft =true; } //中央に戻るdelay(100); turnRight(500); //少し待ってください、急いでいるように見えたくないdelay(500); //右をチェックturnRight(500);ブール障害Right =false; if(digitalRead(INFRA_RED)==LOW){obstructionRight =true; } //中央に戻るdelay(100); turnLeft(500); //ここから抜け出す方法を確認しますif(obstacleLeft &&障害物Right){driveBackwards(NORMAL_SPEED / 3); //(int i =0; i <5; i ++){tone(BUZZER、1000、500);の場合、5秒間後方に移動しながらビープ音を鳴らします。 delay(1000); } //どこかで立ち往生するのを避けるために、旅を続ける前にランダムに方向を変えてくださいrandomTurn(800、1600); } else if(obstacleLeft){turnRight(1000); } else if(obstacleRight){turnLeft(1000); } else {randomTurn(1000、1800); }} //相互作用を増やすためにランダムな処理を行うintnumber =random(100); // 0から99までの乱数を作成しますif(number ==0){randomTurn(200,2000); }} void driveForwards(int speed){//モーターを同じ方向に移動するように設定digitalWrite(MR_1、LOW); digitalWrite(MR_2、HIGH); digitalWrite(ML_1、HIGH); digitalWrite(ML_2、LOW); setSpeed(speed);} void driveBackwards(int speed){//モーターを反対方向に移動するように設定digitalWrite(MR_1、HIGH); digitalWrite(MR_2、LOW); digitalWrite(ML_1、LOW); digitalWrite(ML_2、HIGH); setSpeed(speed);} void turnLeft(int duration){//右輪で前進して左に曲がり、左輪で後ろに曲がるdigitalWrite(MR_1、HIGH); digitalWrite(MR_2、LOW); digitalWrite(ML_1、HIGH); digitalWrite(ML_2、LOW); //速度を落とし、setSpeed(NORMAL_SPEED / 2);をオンにします。 delay(duration); stopDriving();} void turnRight(int duration){//右のホイールで後方に移動し、左のホイールで前方に移動して右に曲がるdigitalWrite(MR_1、LOW); digitalWrite(MR_2、HIGH); digitalWrite(ML_1、LOW); digitalWrite(ML_2、HIGH); //速度を落とし、setSpeed(NORMAL_SPEED / 2);をオンにします。 delay(duration); stopDriving();} void stopDriving(){//すべてのモーターピンをオフにしますdigitalWrite(MR_1、LOW); digitalWrite(MR_2、LOW); digitalWrite(ML_1、LOW); digitalWrite(ML_2、LOW); // ENABLEピンをどうするかわからないが、それらをオフにしても問題はない。digitalWrite(MR_ENABLE、LOW); digitalWrite(ML_ENABLE、LOW);} void setSpeed(int speed){//速度は0から255の間でなければなりませんspeed =constant(speed、0、255); //モーターをオンにする速度を設定しますanalogWrite(MR_ENABLE、speed); analogWrite(ML_ENABLE、speed);} void randomTurn(int minimum、int maximum){unsigned long time =millis(); int期間=ランダム(最小、最大); if(time%2){turnRight(duration); } else {turnLeft(duration); }} void playHello(){tone(BUZZER、262、250); // C4 delay(300);を再生しますトーン(ブザー、330、250); // E4 delay(300);を再生しますトーン(ブザー、392、250); // G4 delay(300);を再生しますトーン(ブザー、523、500); // C5を再生しますdelay(550);} void playUhOh(){tone(BUZZER、523、250); // C5 delay(300);を再生しますトーン(ブザー、415、500); // Gis4 delay(600);}を再生します
回路図
ケーブルの色の意味: 赤=電圧(正)
黒=アース(負)
黄色=赤外線センサーの信号
オレンジと緑=赤と緑のLED入力の接続
紫=モーター方向制御
青=モーター速度制御(残念ながら、Fritzing部分には、モーターブリッジがこれらの接続用に持っていた2つのピンがなかったため、現時点ではワイヤーが緩んでいるように見えます) wall-e2_3P6X71BCnP.fzz
製造プロセス