ProjectSRのアイコン画像
ProjectSR 2023年01月29日作成 (2023年01月29日更新)
製作品 製作品 閲覧数 770
ProjectSR 2023年01月29日作成 (2023年01月29日更新) 製作品 製作品 閲覧数 770

消防ロボット SUIJIN MK-1

消防ロボット SUIJIN MK-1

🔳概要・基本構成

①送信側のArduinoがオペレータのジョイスティックの操作量,ボタンの信号,放水量調整可変抵抗を読み取ります.

②操作量に応じたモータの回転速度を計算し,受信側のArduinoへ数値を送ります.

③メカハードは,車体,タンク,電子バルブ,3Dで制作したポンプと砲座で構成されています.

🔳解説

ユーチューブ ニコニコ動画 にて 動作しているPVを公開しています.
(本編は2:15~)

ここに動画が表示されます

ニコニコ動画

[https://www.nicovideo.jp/watch/sm41604261)

構成解説編は現在準備中です.
後日作成次第,公開します.

ポイント

●モータを制御するため,送信側のArduinoが操作量を読み取る事
●複数のモータの回転速度に関係する複数の数値を送受信する事
●水漏れが無いようにパッキン,シールを用いること
です.

今回は,Arduino+XBeeのを使ったジョイスティックワイヤレスコントローラシステムを応用して
水を放出し,火を消す 消防ロボットを製作しました.

1⃣本体構成

①内部構成

簡単な車体内部構成をポンチ絵程度の断面図で示します.(拡大できます)
キャプションを入力できます

車体は,コントローラから無線で信号を受信し,砲座,ポンプを回転 水路の開閉を行う電磁弁には
ON/OFF指令を出力します.
キャプションを入力できます

電磁弁は開いた状態で初めてポンプが回るように,プログラムを組んでいます.
砲座と車体の履帯(クローラ)は電磁弁の状態によらず,動作可能です
(後程プログラムチャートを示します)
キャプションを入力できます

各種用機器の画像は以下になります
キャプションを入力できます

②タンク

タンク外観です.
ポリタンクやペットボトル等検討しましたが,車体に合わせられる形状にしたかったので,
自作することにしました.
キャプションを入力できます

タンクの材質は塩ビ板で,ホームセンターで売られている
塩ビ三角棒と接着剤で補強し,水漏れが発生しないように,
シリコンシーラントを使っています.
キャプションを入力できます

タンクとL字の塩ビパイプを接続する配管は
金属パテで固定し,ゴムで水漏れを防ぐようにしています.
キャプションを入力できます

③メインポンプ

メインポンプの外観です.
タンクと接続する配管は,接着と水漏れ防止をするため,金属パテを使っています.
キャプションを入力できます

ポンプは,モータRS775とビームカップリングで接続されています.
キャプションを入力できます

続いてポンプ内側です.
ポンプは渦巻ポンプというもので,羽が回転することで,
水を回転方向へ押し出します.
ハウジングや,羽は3Dプリンターで製作しています.
(調べたところ,消防車も同じ形式のものを使っているそうです.)
キャプションを入力できます

↑の羽は,ネジでアルミ製の軸と締結されています.
この軸は,ビームカップリング・モータの順番に接続されているのですが,
ビームカップリングと羽の間に,ポンプカバーとベアリングホルダーがあります.
カバーとベアリングホルダーには,軸を通す穴が開いています.
キャプションを入力できます

製作当初,隙間から水が漏れてしまう事態が発生するので,
PDUパッキンという,回転軸から水が漏れないようにする部品があり,利用しています.
ただ,材質がゴムのため,軸とパッキンで摩擦が発生し,モータが回らない事態が発生しました.
(プロジェクト中止を覚悟しました)
ただ,パッキンと軸にシリコングリスを塗り付けて,摩擦を弱めることに成功!
キャプションを入力できます

また,ベアリングを,ベアリングホルダーにはめる際,
外周をアロンαで接着しています.
目的は,ベアリングが外れる事の防止と,水漏れ防止です.
キャプションを入力できます

④砲座

ノズルは取り外した,砲座外観です.
キャプションを入力できます

砲座は,X,Z軸の回転が可能で,回りすぎを防止するため.
各回転軸に対して,可変抵抗を設けています.
キャプションを入力できます

モータ,可変抵抗,砲座回転軸にギアが取り付けられており,
モータが回転したら,可変抵抗と砲座軸のギアが回り,
可変抵抗の値が所定の位置に達したらモータが停止する
プログラムを組んでいます.
キャプションを入力できます

Z軸回転の砲座も,ギアは可変抵抗,回転軸,モータに取り付けられ,
モータが回ることで,回転軸と可変抵抗が回り,
可変抵抗の値が所定の位置に達した際に,モータは停止します.
上段にギアボックス,下段に可変抵抗と回転軸の軸受けがあります.
砲座Z軸

上段内部

下段内部

2⃣電子回路

続いて電子回路の説明をします.
まずは,受信側回路 ロボットの回路
NUE MK-2とTele Fenix MK-1を併用し,電磁弁と制御用のリレーを追加しています.
キャプションを入力できます

続いて送信側 コントローラの回路です
ソレノイド制御用リレーへ指令を送るトグルスイッチと
ポンプモータの回転数を調整する,可変抵抗を追加しています.
キャプションを入力できます

3⃣制御フロー プログラム

①配列の設定

配列を用意して,モータの回転方向回転速度,電磁弁のON/OFFの送受信を行います.

制御フローチャート

送信側,受信側の制御フローチャートを記載します.
送信は長いので,2つ図を作成しています.

送信側①

キャプションを入力できます

送信側②

キャプションを入力できます

受信側

キャプションを入力できます

プログラム

送信側

int SendBuf[8]; int i; int HDatain,VDatain,HDataout,VDataout,SUITONin,SUITONout; int button2 =2; int button3 =3; int button4 =4; int button5 =5; int button6 =6; int DirR; int DirL; int SUITON_under_R_read; int SUITON_under_L_read; int SUITON_top_U_read; int SUITON_top_D_read; int SUITONDirup_out; int SUITONDirunder_out; int Duty1,Duty2,Duty3; int SubSolenoid_read; int SubSolenoid_out; int countn=0; int solenoidout=0; int SUINTONin ; 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: VDatain = analogRead(A0); VDataout = map(VDatain,0,1023,0,220); HDatain = analogRead(A1); HDataout = map(HDatain,0,1023,0,220); SUITONin = analogRead(A5); SUITONout = map(SUITONin,0,1023,0,255); SUITON_under_R_read = digitalRead(button2); SUITON_under_L_read = digitalRead(button3); SUITON_top_U_read = digitalRead(button4); SUITON_top_D_read = digitalRead(button5); SubSolenoid_read = digitalRead(button6); //前進後退 if(VDataout>120){ if(HDataout>140){ DirL = 0; DirR = 0; Duty1 =VDataout; Duty2 =HDataout; } else if(140>=HDataout && 100<HDataout){ DirL = 0; DirR = 0; Duty1 =(VDataout-110)*2; Duty2 =(VDataout-110)*2; } else{ DirL = 0; DirR = 0; Duty1 =(200-HDataout); Duty2 =VDataout; } } else if(VDataout<=120 && VDataout>=95){ if(HDataout>110){ DirL = 1; DirR = 0; Duty1 =(HDataout-115)*2; Duty2 =(HDataout-115)*2; } else if(HDataout<110){ DirL = 0; DirR = 1; Duty1 =(108-HDataout)*2; Duty2 =(108-HDataout)*2; } else{ DirL = 2; DirR = 2; Duty1 =0; Duty2 =0; } } else{ if(HDataout>150){ DirL = 1; DirR = 1; Duty1 =(HDataout-120)*2; Duty2 =(120-VDataout)*2; } else if(150>=HDataout && HDataout>100){ DirL = 1; DirR = 1; Duty1 =(120-VDataout)*2;//(110-VDataout)*2 Duty2 =(120-VDataout)*2;//(110-VDataout)*2 } else{ DirL = 2; DirR = 2; Duty1 =(120-HDataout)*2; Duty2 =(120-VDataout)*2; } } if(SUITON_under_R_read==LOW || SUITON_under_L_read==LOW){ //砲台下側左右 if(SUITON_under_R_read==LOW){ SUITONDirunder_out=1; } else{ SUITONDirunder_out=0; } } else{ SUITONDirunder_out=2; } if(SUITON_top_U_read==LOW || SUITON_top_D_read==LOW){ //砲台上側上下 if(SUITONDirup_out==LOW){ SUITONDirup_out=1; } else{ SUITONDirup_out=0; } } else{ SUITONDirup_out=2; } //for無限ループからのbreakで脱出 if (SubSolenoid_read==HIGH) { solenoidout=0; } else{ solenoidout=1; } //SendBuf[0] = 0xFF; //SendBuf[1] = 0xFF; SendBuf[0] = DirL; SendBuf[1] = Duty1; SendBuf[2] = DirR; SendBuf[3] = Duty2; SendBuf[4] = SUITONDirunder_out; SendBuf[5] = SUITONDirup_out; SendBuf[6] = solenoidout; SendBuf[7] = SUITONout; //SendBuf[4] = 0; Serial.write(255); Serial.write(255); //Serial.print(255); //Serial.println(255); for(i=0;i<8;i++){ //Serial.println(SendBuf[i]); Serial.write(SendBuf[i]); } Serial.write(0); //Serial.println(0); //Serial.print("VDataout"); //Serial.println(VDataout); //Serial.print("HDataout"); //Serial.println(HDataout); //Serial.println(SubSolenoid_read); delay(200); }

受信側

/*int PIN_OUT1=22; int PIN_OUT2=23; int PIN_OUT3=24; int PIN_OUT4=25;//←メインモータの回転方向*/ int PIN_VREF4=4; int PIN_VREF5=5; int PIN_VREF6=6; int PIN_VREF7=7;//←ここまで砲台モータ int PIN_VREF2=2; int PIN_VREF3=3; int PIN_VREFD8=8; int PIN_VREFD9=9;//←ここまでメインモータ int PIN_SUITON=10;//←放水モータ int PIN_solenoid=11;//電磁弁ONOFF int PIN_SUITOND=12;//←放水モータ方向 int RcvData=0; int RcvBuf[8];//配列数は送られてきたデータの数n カウント数はn-1 //int MT_Rin=5; //int MT_Lin=6; int MT_RoutSerial=0; int MT_LoutSerial=0; int MT_RoutSerial2=0; int MT_LoutSerial2=0; int MT_RSuboutSerial=0; int MT_LSuboutSerial=0; int i=0; int RcvState=0; //int RcvCountF=0; //int RcvCountS=0; int RcvC=0; int MT1D=0; int MT2D=0; int MT1S=0; int MT2S=0; int RcvCount=0; int SUITONvalue=0; int analogupper; int analoglower; int VDataout1; int VDataout2; void setup() { Serial.begin(9600); // 9600bpsでシリアルポートを開く /*pinMode(PIN_OUT1,OUTPUT); pinMode(PIN_OUT2,OUTPUT); pinMode(PIN_OUT3,OUTPUT); pinMode(PIN_OUT4,OUTPUT);*/ pinMode(PIN_VREF2,OUTPUT); pinMode(PIN_VREF3,OUTPUT); pinMode(PIN_VREF4,OUTPUT); pinMode(PIN_VREF5,OUTPUT); pinMode(PIN_VREF6,OUTPUT); pinMode(PIN_VREF7,OUTPUT); pinMode(PIN_VREFD8,OUTPUT); pinMode(PIN_VREFD9,OUTPUT); pinMode(PIN_SUITON,OUTPUT); pinMode(PIN_solenoid,OUTPUT); pinMode(PIN_SUITOND,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 >=9){ RcvCount=0; RcvState = 3; //Serial.print(" RcvData*"); //Serial.println(RcvData); } break; case 3: MotorCnt(); RcvState=0; break; } //Serial.print(" RcvCount*"); //Serial.println(RcvCount); } //Serial.print(" RcvData*"); //Serial.println(RcvData); } void MotorCnt(){ //モータ1の制御 //digitalWrite(13, HIGH ); //delay(100); //digitalWrite(13, LOW ); //delay(100); //digitalwriteが先でanalogWriteが後!! analogupper = analogRead(A0); VDataout1 = map(analogupper,0,1023,0,255); analoglower = analogRead(A1); VDataout2 = map(analoglower,0,1023,0,255); if(RcvBuf[0]==0 || RcvBuf[0]==1){ if(RcvBuf[0] == 0){ MT_LoutSerial = RcvBuf[1]; //Serial.print("左前"); //Serial.print(MT_LoutSerial); digitalWrite(PIN_VREFD8,HIGH); analogWrite(PIN_VREF2,MT_LoutSerial); } else{ MT_LoutSerial = RcvBuf[1]; //Serial.print("左後"); //Serial.print(MT_LoutSerial); digitalWrite(PIN_VREFD8,LOW); analogWrite(PIN_VREF2,MT_LoutSerial); } if(RcvBuf[2] == 0){ MT_RoutSerial = RcvBuf[3]; //Serial.print("右前"); //Serial.println(MT_RoutSerial); digitalWrite(PIN_VREFD9,HIGH); analogWrite(13,MT_RoutSerial); } else{ MT_RoutSerial = RcvBuf[3]; //Serial.print("右後"); //Serial.println(MT_RoutSerial); digitalWrite(PIN_VREFD9,LOW); analogWrite(13,MT_RoutSerial); } } else{//MT_RoutSerial2とLoutSerial2は回転方向表示用変数 また,回転速度の表示を行うと,ジョイスティックが中立になっても,受信側の値が0にならないので,analogwrite(PWM出力)の値は強制的に0にしている //MT_RoutSerial2 = RcvBuf[0]; //MT_LoutSerial2 = RcvBuf[2]; //Serial.print("停止 "); //Serial.print("左回転方向"); //Serial.print(MT_LoutSerial2); //Serial.print("右回転方向"); //Serial.print(MT_RoutSerial2); //Serial.print("回転速度"); //Serial.print(MT_LoutSerial); //Serial.print(" "); //Serial.println(MT_RoutSerial); digitalWrite(PIN_VREFD8,LOW); digitalWrite(PIN_VREFD9,LOW); analogWrite(PIN_VREF2,0); analogWrite(PIN_VREF3,0); } if(RcvBuf[4]==0 || RcvBuf[4]==1){ if(RcvBuf[4] == 0){//ここから配列 ボタン入力の処理を描いてゆく if(VDataout1<170){ analogWrite(PIN_VREF4,50); analogWrite(PIN_VREF5,0); Serial.print("砲座X"); Serial.println(1); } else{ //角度が大きければ停止 analogWrite(PIN_VREF4,0); analogWrite(PIN_VREF5,0); Serial.print("砲座X"); Serial.println(2); } } else if(RcvBuf[4] == 1){ if(VDataout1>50){ analogWrite(PIN_VREF4,0); analogWrite(PIN_VREF5,50); Serial.print("砲座X"); Serial.println(3); } else{ //角度が大きければ停止 analogWrite(PIN_VREF4,0); analogWrite(PIN_VREF5,0); Serial.print("砲座X"); Serial.println(4); } } } else{ //ボタンが押されていないので停止 analogWrite(PIN_VREF6,0); analogWrite(PIN_VREF7,0); Serial.print("砲座X"); Serial.println(5); } if(RcvBuf[5]==0 || RcvBuf[5]==1){ if(RcvBuf[5] == 0){ if(VDataout2<190){ analogWrite(PIN_VREF6,70); analogWrite(PIN_VREF7,0); Serial.print("砲座Z"); Serial.println(1); } else{ analogWrite(PIN_VREF6,0); analogWrite(PIN_VREF7,0); Serial.print("砲座Z"); Serial.println(2); } } else if(RcvBuf[5] == 1){ if(VDataout2<30){ analogWrite(PIN_VREF6,0); analogWrite(PIN_VREF7,70); Serial.print("砲座Z"); Serial.println(3); } else{ analogWrite(PIN_VREF6,0); analogWrite(PIN_VREF7,0); Serial.print("砲座Z"); Serial.println(4); } } } else{ analogWrite(PIN_VREF6,0); analogWrite(PIN_VREF7,0); Serial.print("砲座Z"); Serial.println(5); } if(RcvBuf[6] == 1){ SUITONvalue = RcvBuf[7]; digitalWrite(PIN_SUITOND,HIGH); analogWrite(PIN_SUITON,SUITONvalue); digitalWrite(PIN_solenoid,HIGH); } else{ SUITONvalue = 0; digitalWrite(PIN_SUITOND,HIGH); analogWrite(PIN_SUITON,0); digitalWrite(PIN_solenoid,LOW); } Serial.print("可変抵抗⇓"); Serial.println(VDataout2); delay(100); }

電子部品

最後に本製作例で使用した電子部品を紹介します.

部品名 購入先
Arduino uno 秋月電子通商orマルツパーツor千石電商
Polplu24V21 朱雀技研
モータRS775 朱雀技研
モータRS775ギアヘッド 朱雀技研
トグルスイッチ小 秋月電子通商orマルツパーツor千石電商
トグルスイッチ大 アマゾン
バイクバッテリー アマゾン
電線 秋月電子通商orマルツパーツor千石電商or近くのホームセンター
Arduino変換基盤 秋月電子通商orマルツパーツor千石電商
XBeeと変換基盤 秋月電子通商orマルツパーツor千石電商
ジョイスティックレバー 秋月電子通商orマルツパーツor千石電商
ピンヘッダとピンソケット 秋月電子通商orマルツパーツor千石電商
電子基板 秋月電子通商orマルツパーツor千石電商

また,記載されている内容で不備や,不足しているところ,追加してほしい内容が
ありましたら,ご連絡ください.
(レスポンスは悪いかもしれませんが)

  • ProjectSR さんが 2023/01/29 に 編集 をしました。 (メッセージ: 初版)
  • ProjectSR さんが 2023/01/29 に 編集 をしました。 (メッセージ: 初版を投稿します.)
ログインしてコメントを投稿する