概要・基本構成
①送信側の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軸回転の砲座も,ギアは可変抵抗,回転軸,モータに取り付けられ,
モータが回ることで,回転軸と可変抵抗が回り,
可変抵抗の値が所定の位置に達した際に,モータは停止します.
上段にギアボックス,下段に可変抵抗と回転軸の軸受けがあります.
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
に
編集
をしました。
(メッセージ: 初版を投稿します.)
ログインしてコメントを投稿する