ProjectSR が 2021年12月30日17時46分35秒 に編集
初版
タイトルの変更
無線遠隔操作式ビーダマン Tele Fenix MK-1
タグの変更
Arduino
XBee
ラジコン
ビーダマン
Youtube
ニコニコ動画
メイン画像の変更
記事種類の変更
製作品
本文の変更
ラジコン操作ができる戦車型ビーダマンの構成解説です. 本製作例で,電子工作,プログラミング,物理学を中心に扱っています. 🔳知れる事 --- ◇ビー玉の射出機構解説 ◇Arduinio + XBeeの無線遠隔操縦 ◇射出の物理的な考え方←筆者の独自解釈もあります 解説動画 --- ユーチューブ ニコニコ動画 にて 解説もしています. どのような動作をされるか見たい方は,ご参照ください. **PV** @[youtube](https://www.youtube.com/watch?v=Afr1vsBRU4M) **遠隔操作式ビーダマン Tele Fenix MK-1 前編 メカハード・物理学中心** @[youtube](https://www.youtube.com/watch?v=TsZfzMtiPfc) **遠隔操作式ビーダマン Tele Fenix MK-1 前編 電気ハード・プログラム中心** @[youtube](https://www.youtube.com/watch?v=1JN1bEVtOow) 🔳概要・基本構成 --- 基本構成は, ①平歯車とラック歯車を使った射出機構+クローラ走行 ②Arduino+Xbee通信で,モータを制御 🔳解説 --- **【背景】** 最近のラジコン玩具は,赤外線で対戦相手を攻撃する対戦形式のシステムが搭載されています. また,ROBOMASTERの様にビービー弾を打つ戦車タイプのラジコンロボットにカメラを搭載して PC越しで操作しながら対戦するものも出てきています. また,amazonでは,Arduinoやraspberrypiを標準搭載した,ロボットも販売されており,プログラム学習等 遊び以外にも利用する目的で使われています. そうしたコンテンツをビーダマンに盛り込んでみようと思い,試作目的で1号機を作成してみました. 構造 --- 動画でも解説しておりますので,併せてご覧いただけると,より分かりやすいかと思います  **車体内** 車体内は,タミヤギアボックスとArduino,モータドライバーで構成されています.  **砲塔内・射出機構** 砲塔内部は,平歯車とラック歯車を使っています. 動画でも解説しておりますが, ・ラック歯車に穴を開けて引きばねを装着. ・車体側にも引きばねを装着 ・平歯車の歯一部を削っておく ・平歯車が回るとラック歯車が移動し, 削られた箇所に達すると,バネの弾性力で 元の位置に戻り,その際ビー玉が射出されます.  物理的な考え --- 一応,物理的な設計思想も書いておきます. **飛距離と威力** 射出されたビー玉の飛距離と,威力は ビー玉の射出初速度に依存します.  **初速度** 初速度は,バネが引っ張られた分,蓄えられた位置エネルギーが運動エネルギーに変換されると 考えて,積分を行いながら導き出せます.  **摩擦によるエネルギー損失(今回は考えていません)** エネルギー変換の間に,砲筒での摩擦が考えられますが,摩擦係数を考慮する必要があります. ですが,摩擦係数は,環境や使用回数によって変化するので,今回は考えておりません.  **飛距離の算出** 飛距離は,重力により,ビー玉が地面に落ちるまでの時間を初速度に掛ければ求められます.  **威力** 威力は,ビー玉の初速度と質力を掛けることで求められる力積,つまり衝撃力で求められます. ※厳密には,衝撃力を詳しく見てゆくと,物体が壊れ始める時のエネルギー等も考慮する必要があります.  モータを回転させて,今回で言うバネを引く際に,徐々にモータにかかる力が大きくなります. そのため,力が大きくなると,モータが必要とするエネルギー量も増えてきます. この時間帯あたりで必要とするエネルギーに違いが出てくるので,単位時間当たりの消費エネルギーや出力できる エネルギーを見てゆく必要があります. モータでは仕事率,電池では電力という考え方が相当します. モータの仕事率が,電池が出力できる最大電力を上回らないように,メカ・電気面でシステムを組む必要があります.  TeleFenixでは,ギアボックスのギア比が高いものを利用しています. これで,モータにかかる負荷を下げ,その分ギア比で稼ぐのが狙いです. 但し,回転速度は落ちてしまうのがデメリットです. 回路図 --- **車体側**  車体側では,GNDをモータドライバーとArduinoで共通にするようにしてください. つまり,GNDは接続させてくださいという事ですね. 出ないと,PWMの値が,波を打ってしまいます. というのも,GNDという,共通する電圧のレベルが無いので,基準でノイズなどがのっかってしまい,PWM出力の波形がノイズみたいな波形になります. また,今回はモータドライバーはMDD3Aを利用しています.そのため,Arduinoの5V出力とモータドライバーはつなげていません. **コントローラ側**  コントローラ側は,タクトスイッチでもOKですが,もう少し大きめのスイッチを用意すると スイッチを押しやすくていいです. **モータドライバー MDD3A**  今回使っているモータドライバーMDD3Aです. こちらは,緑色の端子に電池をつなげば,左側にあります,5Vから電圧が出力される仕様になっており, 5V GNDをArduinoを接続すれば,Arduinoが 起動できる仕様になっています. また,このモータドライバーは,タクトスイッチも装備されており,マイコンなしで,モータを回すことができます. 朱雀技研様で販売されていたので購入しました. プログラム --- **車体側** **制御フロー**  ```html:□Program 車体側 #define PIN_OUT1 2 #define PIN_OUT2 4 #define PIN_OUT3 7 #define PIN_OUT4 8 #define PIN_OUT5 12 #define PIN_OUT6 13 #define PIN_OUT7 A0 #define PIN_OUT8 A1 #define PIN_VREF1 3 #define PIN_VREF2 5 #define PIN_VREF3 6 #define PIN_VREF4 9 #define PIN_VREF5 10 #define PIN_VREF6 11 int RcvData=0; int RcvBuf[2];//配列数は送られてきたデータの数n カウント数はn-1 int i=0; int RcvState=0; //int RcvCountF=0; //int RcvCountS=0; int RcvCount=0; void setup() { Serial.begin(9600); // 9600bpsでシリアルポートを開く pinMode(PIN_OUT1,OUTPUT); pinMode(PIN_OUT2,OUTPUT); pinMode(PIN_OUT3,OUTPUT); pinMode(PIN_OUT4,OUTPUT); pinMode(PIN_OUT5,OUTPUT); pinMode(PIN_OUT6,OUTPUT); pinMode(PIN_OUT7,OUTPUT); pinMode(PIN_OUT8,OUTPUT); /*pinMode(PIN_VREF1,OUTPUT); pinMode(PIN_VREF2,OUTPUT); pinMode(PIN_VREF3,OUTPUT); pinMode(PIN_VREF4,OUTPUT);*/ } void loop() { while(Serial.available() > 0){ RcvData=Serial.read(); //Serial.println(RcvData); //Serial.println(RcvState); switch(RcvState){ case 0: if(RcvData==255){ RcvState = 1; //Serial.print("RcvData1"); //Serial.println(RcvState); } break; case 1: if(RcvData==255){ RcvState = 2; //Serial.print(" RcvData2"); //Serial.println(RcvData); } else{ RcvState = 0; } break; case 2: RcvBuf[RcvCount]=RcvData; RcvCount++; if(RcvCount >=2){ RcvCount=0; RcvState = 3; //Serial.print(" RcvData*"); //Serial.println(RcvData); } break; case 3: MotorCnt(); RcvState=0; break; } } } void MotorCnt(){ if(RcvBuf[0] == 1){//ここから配列 ボタン入力の処理を描いてゆく //digitalWrite(PIN_OUT1,HIGH); analogWrite(PIN_VREF1,0); //digitalWrite(PIN_OUT3,HIGH); analogWrite(PIN_VREF2,250); //Serial.print("クローラ:"); analogWrite(PIN_VREF3,0); analogWrite(PIN_VREF4,250); //Serial.print(RcvBuf[0]); } else if(RcvBuf[0] == 2){ //digitalWrite(PIN_OUT1,LOW); analogWrite(PIN_VREF1,0); //digitalWrite(PIN_OUT2,HIGH); analogWrite(PIN_VREF2,180); //Serial.print("クローラ:"); //Serial.print(RcvBuf[0]); analogWrite(PIN_VREF3,180); analogWrite(PIN_VREF4,0); } else if(RcvBuf[0] == 3){ //digitalWrite(PIN_OUT1,HIGH); analogWrite(PIN_VREF1,250); //digitalWrite(PIN_OUT2,LOW); analogWrite(PIN_VREF2,0); //Serial.print("クローラ:"); //Serial.print(RcvBuf[0]); analogWrite(PIN_VREF3,250); analogWrite(PIN_VREF4,0); } else if(RcvBuf[0] == 4){ //digitalWrite(PIN_OUT1,HIGH); analogWrite(PIN_VREF1,180); //digitalWrite(PIN_OUT2,LOW); analogWrite(PIN_VREF2,0); //Serial.print("クローラ:"); //Serial.print(RcvBuf[0]); analogWrite(PIN_VREF3,0); analogWrite(PIN_VREF4,180); } else{ //digitalWrite(PIN_OUT1,HIGH); analogWrite(PIN_VREF1,0); //digitalWrite(PIN_OUT2,LOW); analogWrite(PIN_VREF2,0); //Serial.print("クローラ:"); //Serial.print(RcvBuf[0]); analogWrite(PIN_VREF3,0); analogWrite(PIN_VREF4,0); } if(RcvBuf[1] == 1){ //Serial.println(RcvBuf[1]); //digitalWrite(PIN_OUT5,HIGH); //digitalWrite(PIN_OUT6,LOW); analogWrite(PIN_VREF5,250); //digitalWrite(PIN_OUT7,HIGH); //digitalWrite(PIN_OUT8,LOW); analogWrite(PIN_VREF6,250); //Serial.print(" バスターキャノン:"); //Serial.print(RcvBuf[1]); } else{ //Serial.println(RcvBuf[1]); //digitalWrite(PIN_OUT5,HIGH); //digitalWrite(PIN_OUT6,LOW); analogWrite(PIN_VREF5,0); //digitalWrite(PIN_OUT7,HIGH); //digitalWrite(PIN_OUT8,LOW); analogWrite(PIN_VREF6,0); //Serial.print(" バスターキャノン:"); //Serial.print(RcvBuf[1]); } //Serial.print(" クローラー:"); //Serial.println(RcvBuf[0]); //Serial.print(" バスターキャノン:"); //Serial.println(RcvBuf[1]); // delay(10); } ``` **コントローラ側** **制御フロー**  int SendBuf[2]; ```html:□Program コントローラ側 int i; //const int analogPin(0) = A0; //const int analogPin(1) = A1; int HDatain,VDatain,HDataout,VDataout; int button2 =2; int button3 =3; int button4 =4; int button5 =5; int button6 =6; int Cmotor1; int Cmotor2; int Cmotor3; int Cmotor4; int SCmotor; int Bmotor; int SBmotor; void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(button2,INPUT); pinMode(button3,INPUT); pinMode(button4,INPUT); pinMode(button5,INPUT); pinMode(button6,INPUT); } void loop() { // put your main code here, to run repeatedly: Cmotor1 = digitalRead(button2); Cmotor2 = digitalRead(button3); Cmotor3 = digitalRead(button4); Cmotor4 = digitalRead(button5); Bmotor = digitalRead(button6); //前進後退 if(Cmotor1==HIGH){ SCmotor=1; } else if(Cmotor2==HIGH){ SCmotor=3; } else if(Cmotor3==HIGH){ SCmotor=2; } else if(Cmotor4==HIGH){ SCmotor=4; } else{ SCmotor=0; } if(Bmotor==HIGH){ //バスターキャノンON OFF SBmotor=1; } else{ SBmotor=0; } //SendBuf[0] = 0xFF; //SendBuf[1] = 0xFF; SendBuf[0] = SCmotor; SendBuf[1] = SBmotor; //SendBuf[4] = 0; Serial.write(255); Serial.write(255); //Serial.print(255); //Serial.println(255); for(i=0;i<2;i++){ //Serial.println(SendBuf[i]); Serial.write(SendBuf[i]); } Serial.write(0); //Serial.println(0); delay(10); } ``` 参考文献 --- 参考文献 ●物理参考文献 山本義隆 新物理入門 駿台文庫 神戸大学(理系−前期日程) (2022年版大学入試シリーズ) 数学社 ⇚ビー玉の初速度計算 電力計算 EDN JAPAN DCモーターの性能線図を理解して高効率駆動について考えてみよう https://edn.itmedia.co.jp/edn/article... EDN JAPAN 電池の基本構成と充放電の原理 https://edn.itmedia.co.jp/edn/article... Tech Note powerd by IPROS モータの基礎知識 https://www.ipros.jp/technote/basic-m... Urban Cafeteria 小学生でも分かるパワーとエネルギーの違い https://macasakr.sakura.ne.jp/poweren... DEVICE PLUS モータにトルク負荷をかけた時のモータ電流について https://deviceplus.jp/glossary/qa_008/ オリエンタルモータ株式会社 Q&Aモーター出力を求める計算方法はありますか? https://www.orientalmotor.co.jp/tech/... CQ出版 小型DCモータの基礎・応用 https://www.cqpub.co.jp/hanbai/books/... プログラミング ●参考文献 References 「作る、できる/基礎入門電子工作の素」 後閑哲也 著 技術評論社 https://gihyo.jp/book/2021/978-4-297-... 「Arduinoでロボット工作をたのしもう!」 鈴木美朗志 著 秀和システム https://www.shuwasystem.co.jp/book/97...