ラズパイ戦車をスマホからコントロールする

2019年11月19日

1.pythonでLチカをコントロール

前回の記事で、WebIOpiを用いてLチカを行ってみました。

確かに、スマホからボタンをクリックすることで、Lチカを実現できましたが、ラズパイのピンに電流を流すだけのことでした。

戦車を動かすには、ボタンをクリックした際、前進、後退などを実現できなければならないので、これだけでは戦車のコントロールはできないですね。

そこで、こちらのページ(WebブラウザからRaspberry Pi のGPIOを操作する(WebIOPi 利用))では、同じLチカでも、pythonとhtmlを使用した例題を載せています。

実際、このページで提示されている内容をやってみると、こんなことができました。

LED1~3をチェックすると、それに割り付けられたKEDが点滅します。さらに、点滅スピードを変えることが出来ましたね。

スポンサーリンク

戦車のプロトタイプの実行

Lチカはできましたが、戦車に応用するとなると、チェックボックスではなく、ボタンの方が良さそうです。

そして、このボタンに前進、後退・・などの名称を付けて、その動きをさせればいいわけです。

pi zero WH へ WebIOpi をセットアップ

Lチカは、pi3 で実行しました。

しかし、戦車に乗せるにはちいさな筐体がいいので、pi zero WH でコントロールしましょう。

それには、pi zero WH へ WebIOpi をセットアップしなければなりません。

前回の記事に従い、WebIOpiをインストールし、設定用の環境もセットアップします。


プロトタイプの画面

最初から完成形を目指すと時間がかかりそうなので、前進と停止だけを持つプロトタイプを作成してみます。

こんな感じです。

前進を forward、停止を stop にしています。

なんか、デザイン性を全く無視した画面ですが、プロトタイプなので気にしなくともいいでしょう。

HTMLは、次のようになります。

<!DOCTYPE html>
<html>
<head>
<title>dcmotor</title>
<script type="text/javascript" src="/webiopi.js"></script>
<script type="text/javascript">
function init() {
var btn0, ct0;
ct0 = $("#box");
btn0 = webiopi().createButton("f", "forward", click_forward);
ct0.append(btn0);
btn0 = webiopi().createButton("s", "stop", click_stop);
ct0.append(btn0);
}
function click_forward(){
webiopi().callMacro("forward");
}
function click_stop() {
webiopi().callMacro("stop");
}
webiopi().ready(init);
</script>
<style type="text/css">
button{
display:block;
margin:5px 5px 5px 5px;
width:160px;
height:45px;
font-size:24pt;
font-weight:bold;
color:black;
}
</style>
</head>
<body>
<div id="box" align="center"></div>
<input type="range" style="width:150px">
</body>
</html>

プロトタイプのプログラム

こちらが、pythonプログラムです。

色々調べましたが、webiopi の pwmWrite 命令を使えばいいようです。ピン番号は、buetoothで動かしたときの回路をそのまま流用しましたので、それをそのまま使用します。

前進は、def forward()、停止は、def stop()で指示しています。

import webiopi
# Debug
webiopi.setDebug()
GPIO = webiopi.GPIO
# GPIO 18,23が左モータ、GPIO 24,25が右モータ
MOTOR_L1 = 18
MOTOR_L2 = 23
MOTOR_R1 = 24
MOTOR_R2 = 25
duty=50
# WebIOPi起動時CALL
def setup():
webiopi.debug("Script with macros - Setup")
# GPIOのセットアップ
GPIO.setFunction(MOTOR_L1, GPIO.PWM)
GPIO.setFunction(MOTOR_L2, GPIO.PWM)
GPIO.setFunction(MOTOR_R1, GPIO.PWM)
GPIO.setFunction(MOTOR_R2, GPIO.PWM)
# 初期のデューティー比を0%に(静止状態)
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, 0)
#
def loop():
webiopi.sleep(5)
# WebIOPi終了時に呼ばれる関数
def destroy():
webiopi.debug("Script with macros - Destroy")
# GPIO関数のリセット(入力にセットすることで行う)
GPIO.setFunction(MOTOR_L1, GPIO.IN)
GPIO.setFunction(MOTOR_L2, GPIO.IN)
GPIO.setFunction(MOTOR_R1, GPIO.IN)
GPIO.setFunction(MOTOR_R2, GPIO.IN)
#defult function
@webiopi.macro
def forward():
GPIO.pwmWrite(MOTOR_L1, duty)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, duty)
GPIO.pwmWrite(MOTOR_R2, 0)
webiopi.debug("foward")
@webiopi.macro
def stop():
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, 0)
webiopi.debug("stop")

プロトタイプ実行

これらをセッティングしたので、WebIOPi サービスの設定を変更します。先ほどの記事に従って、「/etc/webiopi/config」ファイルを設定します。

sudo vi /etc/webiopi/config

[SCRIPTS] セクションの「myscript =」を変更します。

#myscript = /home/pi/webiopi/examples/scripts/macros/script.py
myscript = /home/pi/work/webiopi/script.py

次に、[HTTP] セクションの「doc-root =」及び「welcome-file =」を変更します。

#Use doc-root to change default HTML and resource files location
#doc-root = /home/pi/webiopi/examples/scripts/macros
doc-root = /home/pi/work/webiopi/
#Use welcome-file to change the default "Welcome" file
#welcome-file = index.html
welcome-file = index.html

これで、プロタイプ実行の準備ができました。

それでは、WebIOPi のサービスを開始します。

sudo systemctl start webiopi

現在、プロトタイプのため、pi zero WH は直電源で行っているので、キャタピラは取り外しています。

それでは、スマホに画面を出して実行してみます。ラズパイのアドレスに:8000を追加して画面を出します。

https://192.XXX.XXX.XXX:8000

認証ダイアログが表示されます。以下の値を入力してログインしてください。

ユーザー名:webiopi
パスワード:raspberry

おおっ!!60爺にしては、素直に動きましたね。

戦車をスマホからコントロール

それでは、今の考え方を戦車のコントロールに応用してみましょう。

出来上がった戦車は、 ブレッドボードがでかすぎて、ちょっと、格好悪いですね!電池ボックス、ラズパイ電源となるモバイル電池も大きいので武骨な形になってます。

この先、別の戦車を拵えるときは、もっと小さなブレッドボードを使用するようにします。

戦車コントロール画面

戦車コントロール画面ですが、こんなイメージです。

これを、HTMLで書きます。

左折(Turn Left)、右折(Turn right)及び後退(Back)のボタンを追加すると共に、実行時のマクロの呼び出しを追加します。

また、上記の画面デザインに合わせて、編集を行います。行ごとに載せるボタンの数が違いますので、コードが追加となります。

<!DOCTYPE html>
<html>
<head>
<title>dcmotor</title>
<script type="text/javascript" src="/webiopi.js"></script>
<script type="text/javascript">
function init() {
var btn0;
btn0 = webiopi().createButton("r", "Turn Right", click_right);
$("#r").append(btn0);
btn0 = webiopi().createButton("l", "Turn Left", click_left);
$("#l").append(btn0);
btn0 = webiopi().createButton("f", "Forward", click_forward);
$("#f").append(btn0);
btn0 = webiopi().createButton("b", "Back", click_back);
$("#b").append(btn0);
btn0 = webiopi().createButton("s", "Stop", click_stop);
$("#s").append(btn0);
}
function click_right() {
webiopi().callMacro("right");
}
function click_left() {
webiopi().callMacro("left");
}
function click_forward(){
webiopi().callMacro("forward");
}
function click_back(){
webiopi().callMacro("back");
}
function click_stop() {
webiopi().callMacro("stop");
}
webiopi().ready(init);
</script>
<style type="text/css">
button{
display:block;
margin:5px 5px 5px 5px;
width:160px;
height:100px;
font-size:24pt;
font-weight:bold;
color:black;
}
</style>
</head>
<body>
<div align="center"></div>
<table>
<tr>
<td>
<table border=0 cellspacing="10″ cellpadding="0″>
<tbody>
<tr>
<td> </td>
<td><div id="f"></div></td>
<td> </td>
</tr>
<tr>
<td><div id="l"></div></td>
<td><div id="s"></div></td>
<td><div id="r"></div></td>
</tr>
<tr>
<td> </td>
<td><div id="b"></div></td>
<td> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>

pythonプログラム

上記のボタンがクリックされた際のpythonプログラムがこちらです。

プロトタイプのプログラムに、右折(Turn Right)、左折(Turn Left)、後退(Back)を追加します。

import webiopi
# Debug
webiopi.setDebug()
GPIO = webiopi.GPIO
# GPIO 18,23が左モータ、GPIO 24,25が右モータ
MOTOR_L1 = 18
MOTOR_L2 = 23
MOTOR_R1 = 24
MOTOR_R2 = 25
duty=50
# WebIOPi起動時CALL
def setup():
webiopi.debug("Script with macros - Setup")
# GPIOのセットアップ
GPIO.setFunction(MOTOR_L1, GPIO.PWM)
GPIO.setFunction(MOTOR_L2, GPIO.PWM)
GPIO.setFunction(MOTOR_R1, GPIO.PWM)
GPIO.setFunction(MOTOR_R2, GPIO.PWM)
# 静止状態
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, 0)
#
def loop():
webiopi.sleep(5)
# WebIOPi終了時
def destroy():
webiopi.debug("Script with macros - Destroy")
# GPIO関数のリセット(入力にセットすることで行う)
GPIO.setFunction(MOTOR_L1, GPIO.IN)
GPIO.setFunction(MOTOR_L2, GPIO.IN)
GPIO.setFunction(MOTOR_R1, GPIO.IN)
GPIO.setFunction(MOTOR_R2, GPIO.IN)
#defult function
@webiopi.macro
def forward():
GPIO.pwmWrite(MOTOR_L1, duty)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, duty)
GPIO.pwmWrite(MOTOR_R2, 0)
webiopi.debug("foward")
@webiopi.macro
def left():
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, duty)
GPIO.pwmWrite(MOTOR_R1, duty)
GPIO.pwmWrite(MOTOR_R2, 0)
webiopi.debug("left")
@webiopi.macro
def stop():
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, 0)
webiopi.debug("stop")
@webiopi.macro
def right():
GPIO.pwmWrite(MOTOR_L1, duty)
GPIO.pwmWrite(MOTOR_L2, 0)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, duty)
webiopi.debug("right")
@webiopi.macro
def back():
GPIO.pwmWrite(MOTOR_L1, 0)
GPIO.pwmWrite(MOTOR_L2, duty)
GPIO.pwmWrite(MOTOR_R1, 0)
GPIO.pwmWrite(MOTOR_R2, duty)
webiopi.debug("back")

スマホから戦車をリモートコントロール

上記2.(4) で示した通り、/etc/webiopi/config の内容を設定します。

WebIOPi のサービスを開始し、スマホに画面を出して実行してみます。

動画を載せますので見てください。

動きが鈍い感じもしますが、まア、こんなものでしょう!

スマホに設定したボタンを押すと、それに対応して戦車が動くのが確認できました。

スポンサーリンク

モーター制御からリモコン操作に至る過程の記事です。他の記事もぜひ、ご覧ください。

参考
Raspberry Pi でブラウザから操作できるラジコン戦車を作る! – WebIOPi から DC モーターを制御する –
『RaspberryPiで学ぶ電子工作』でラジコン操作につまったときの対処 その3

スポンサーリンク
この記事を書いた人

60爺

60路を越え、RaspberryPi と出会い、その関係でブログ開設(2017/2~)となりました。始めてみると、コツコツやるのが性に合ってしまい、漢字の記事から家の補修・将棋・windows10関係・別名・言い方などジャンルを拡大して今に至ってます。まだまだ、元気なので新たな話題を見つけて皆様に提供できればと思っています。「プロフィールはこちら