前回unitv2からuart通信にてraspberrypiのi2cを制御しサーボモーターを駆動させました。↓
今回は最終目的である「2足歩行ロボット」を完成させたいと思います。
前回までで
unitv2→uart→raspberrypizerow→i2c→pca9685→サーボモーター
の形が出来ましたので、あとは「ロボットの骨組みを作る」「モーションの作成」で完了します。
では初めに、ロボットの骨組みを作成します。
ダイソーの¥100化粧箱
これにデバイス全て突っ込む
本当は3Dプリンターで作りたいのですが、まだ買ったばかりで開封もしていない(-_-;)ってことで、また段ボールに頼ることにしました。ダイソーで10mm×10mmのよさげな化粧箱が¥100で販売されていたので、これを使うことにしました。
これの中にunitv2,raspberrypizerow,pca9685,リポバッテリー等全てをぶち込みます。ちなみに、過去に作成したraspberrypiロボットの小さいバージョンのような感じになるので、過去記事のこんな構成になります。↓
実際に作成したのがコチラ。↓
。。かなり強引ですがなんとか入りました。
これにカバーをかぶせます。↓
いやあ~我ながら雑ですが、これでOKとします。
最後に、前進、後退、旋回のモーションを作成します。
モーションプログラム
javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
$(function(){ let motor = "STOP"; // 「前進」ボタンが押されたときのイベント処理 $('#forward').bind('touchstart', function() { // 押されたとき if(motor == 'STOP') { $(this).addClass('ledon'); change_motor('FOWARD'); ff1 = setInterval(function(){ change_motor('FOWARD'); }, 4000); } }).bind('touchend', function() { // 離したとき $(this).removeClass('ledon'); change_motor('STOP'); clearInterval(ff1); }); // 「後退」ボタンが押されたときのイベント処理 $('#backward').bind('touchstart', function() { if(motor == "STOP") { $(this).addClass('ledon'); change_motor('BACKWARD'); ff1 = setInterval(function(){ change_motor('BACKWARD'); }, 4000); } }).bind('touchend', function() { $(this).removeClass('ledon'); motor = "STOP"; change_motor('STOP'); clearInterval(ff1); }); // 「右」ボタンが押されたときのイベント処理 $('#right').bind('touchstart', function() { if(motor == "STOP") { $(this).addClass('ledon'); change_motor('RIGHT'); ff1 = setInterval(function(){ change_motor('RIGHT'); }, 2200); } }).bind('touchend', function() { $(this).removeClass('ledon'); motor = "STOP"; change_motor('STOP'); clearInterval(ff1); }); // 「左」ボタンが押されたときのイベント処理 $('#left').bind('touchstart', function() { if(motor == "STOP") { $(this).addClass('ledon'); change_motor('LEFT'); ff1 = setInterval(function(){ change_motor('LEFT'); }, 2100); } }).bind('touchend', function() { $(this).removeClass('ledon'); motor = "STOP"; change_motor('STOP'); clearInterval(ff1); }); //function change_motor2() { // motor = 'STOP'; //} // 関数:モーターを動かすマクロ呼び出し function change_motor(typee) { motor = typee; if(typee == "FOWARD") { // 前進 //w().callMacro('FW'); console.log(typee); $.ajax({ url: 'cgi-bin/recieve.py', type: 'post', data: {name: 'hhhhh' } }).done(function(data){ console.log(data); }).fail(function(){ console.log('failed'); }); } else if(typee == "BACKWARD") { //w().callMacro('BK'); console.log(typee); $.ajax({ url: 'cgi-bin/recieve.py', type: 'post', data: {name: 'iiii' } }).done(function(data){ console.log(data); }).fail(function(){ console.log('failed'); }); } else if(typee == "RIGHT") { //w().callMacro('RT'); console.log(typee); $.ajax({ url: 'cgi-bin/recieve.py', type: 'post', data: {name: 'jjjj' } }).done(function(data){ console.log(data); }).fail(function(){ console.log('failed'); }); } else if(typee == "LEFT") { //w().callMacro('LT'); console.log(typee); $.ajax({ url: 'cgi-bin/recieve.py', type: 'post', data: {name: 'kkkk' } }).done(function(data){ console.log(data); }).fail(function(){ console.log('failed'); }); } else if(typee == "STOP") { //w().callMacro('ST'); console.log(typee); $.ajax({ url: 'cgi-bin/recieve.py', type: 'post', data: {name: 'ssss' } }).done(function(data){ console.log(data); }).fail(function(){ console.log('failed'); }); } } }); |
unitv2側のプログラム修正になります。
こちらも過去記事でまとめた内容になりますが、今回、ブラウザからサーボモーターを操作するにあたって、「ボタンを押している間は動作し続ける」ように設定しました。
setInterval、clearIntervalの関数でこれを実現しています。詳しくは過去記事でまとめているので、こちらを参照ください。↓
連続押しでも動作の間隔が大きい場合や、重なって誤動作してしまう場合は、setIntervalの引数の秒数を変更してやればOKです。uart通信のタイムラグ等の兼ね合いもあるかと思いましたが、特別その辺りは計算しなくてもスムーズに動作しました。
続いて、cssも一部変更しておきます。
css
1 2 3 4 |
body { -webkit-touch-callout: none; -webkit-user-select: none; } |
bodyタグに-webkit-…を追加しておきます。これが無ければ、スマホで長押しした時にボタンのテキスト修正画面にいちいち切り替わるので厄介です。(アンドロイド専用?のcssっぽいです。)
※ちなみに今回はPCからの操作を前提としておりませんので、先ほどのjsを記述しちゃうとPCのマウスクリックは効かなくなります。
最後に、ロボットの動作モーションをpythonで作成します。
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
import time import serial import Adafruit_PCA9685 data3 = 'abc' pwm = Adafruit_PCA9685.PCA9685() pwm.set_pwm_freq(60) p = 350 i = 395 n = 350 t = 377 ser = serial.Serial('/dev/ttyS0', 115200, timeout = 0.5) while True: #global data3 #コマンドの結果を受信 time.sleep(0.1) data = ser.readline() #区切り文字0x0Aまでのデータを受信 data2 = data.strip().decode('utf-8') print(data2) #if data2 == 'hhhhh' or data2 == 'iiii' or data2 == 'kkkk' or data2 =='jjjj': #global data3 #data3 = data2 #print(data2 + "mae") #data3 = data2 # if data2 == 'hhhhh': #GPIO.output(MOTOR_A1,GPIO.HIGH) #if data2 == 'hhhhh': if data2 == 'hhhhh': while(n <= 500): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) #time.sleep(1) n = n + 1 if t <= 450: t = t + 1 while(i <= 495): pwm.set_pwm(2, 0, i) time.sleep(0.0005) #time.sleep(1) i = i + 1 while(n >= 350): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) #time.sleep(1) n = n - 1 if t >= 362: t = t - 1 while(i >= 395): pwm.set_pwm(2, 0, i) time.sleep(0.0005) #time.sleep(1) i = i - 1 while(t >= 250): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) #time.sleep(1) t = t - 1 if n >= 300: n = n - 1 while(p >= 250): pwm.set_pwm(0, 0, p) time.sleep(0.0005) #time.sleep(1) p = p - 1 while(t <= 377): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) #time.sleep(1) t = t + 1 if n <= 350: n = n + 1 while(p <= 350): pwm.set_pwm(0, 0, p) time.sleep(0.0005) #time.sleep(1) p = p + 1 #pwm.set_pwm(0, 0, 300) #time.sleep(1) #pwm.set_pwm(0, 0,450) #time.sleep(1) print('ff') elif data2 == 'jjjj': #GPIO.output(MOTOR_A2,GPIO.HIGH) #pwm.set_pwm(1, 0, 300) #time.sleep(1) #pwm.set_pwm(1, 0,450) #time.sleep(1) while(n <= 500): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) n = n + 1 if t <= 450: t = t + 1 while(i >= 295): pwm.set_pwm(2, 0, i) time.sleep(0.0005) i = i - 1 while(n >= 350): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) n = n - 1 if t >= 377: t = t - 1 while(i <= 395): pwm.set_pwm(2, 0, i) time.sleep(0.0005) i = i + 1 print("lf") elif data2 == 'kkkk': #GPIO.output(MOTOR_A3,GPIO.HIGH) #pwm.set_pwm(2, 0, 300) #time.sleep(1) #pwm.set_pwm(2, 0,450) #time.sleep(1) while(t >= 250): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) t = t - 1 if n >= 300: n = n - 1 while(p <= 450): pwm.set_pwm(0, 0, p) time.sleep(0.0005) p = p + 1 while(t <= 377): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) t = t + 1 if n <= 350: n = n + 1 while(p >= 350): pwm.set_pwm(0, 0, p) time.sleep(0.0005) p = p - 1 print('bk') elif data2 == 'iiii': #GPIO.output(MOTOR_A4,GPIO.HIGH) #pwm.set_pwm(3, 0, 300) #time.sleep(1) #pwm.set_pwm(3, 0,450) #time.sleep(1) while(n <= 500): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) n = n + 1 if t <= 450: t = t + 1 while(i >= 295): pwm.set_pwm(2, 0, i) time.sleep(0.0005) i = i - 1 while(n >= 350): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) n = n - 1 if t >= 377: t = t - 1 while(i <= 395): pwm.set_pwm(2, 0, i) time.sleep(0.0005) i = i + 1 while(t >= 250): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) t = t - 1 if n >= 300: n = n - 1 while(p <= 450): pwm.set_pwm(0, 0, p) time.sleep(0.0005) p = p + 1 while(t <= 377): pwm.set_pwm(3, 0, t) pwm.set_pwm(1, 0, n) time.sleep(0.0005) t = t + 1 if n <= 350: n = n + 1 while(p >= 350): pwm.set_pwm(0, 0, p) time.sleep(0.0005) p = p - 1 print('rt') if data2 == 'ssss': #GPIO.output(MOTOR_A1,GPIO.LOW) #GPIO.output(MOTOR_A2,GPIO.LOW) #GPIO.output(MOTOR_A3,GPIO.LOW) #GPIO.output(MOTOR_A4,GPIO.LOW) #pwm.set_pwm(0, 0, 375) #pwm.set_pwm(1, 0, 375) #pwm.set_pwm(2, 0, 375) #pwm.set_pwm(3, 0, 375) data3 = 'abc' print('st') |
raspberrypi側のpythonプログラムを変更します。
サーボモーターのスピード調整の為に、whileで決められた角度まで数値を1づつ変化させています。
他は特に特記する事はありません。
それでは、動作確認をしてみようと思います。
動作確認
unitv2のindex.htmlがある階層に移動し、そこでpython http.serverを立ち上げます。
python -m http.server 8000 –cgi
ラズパイのpythonプログラムを起動させておきます。
python3 pythonファイル名
あとは、unitv2のローカルIP:8000にアクセスすれば確認できます。(カメラ画像は一旦unitv2のローカルIP:80で起動しておく必要があります。)↓
見た目はともかく、なんとか完成致しました。
背中にしょってる単三電池は使用していませんので、リポ×2を中に突っ込んで動かしています。