ラズパイ戦車をスマホからコントロール!見事に動かすことが出来た

2019年11月19日

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

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

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

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

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

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

Lチカはできましたが、戦車に応用するとなると、チェックボックスではなくボタンの方が良さそうです。そして、このボタンに前進、後退・・などの名称を付けて、その動きをさせればいいわけです。

それをベースに戦車をスマホで動かしてみましょう。

スポンサーリンク

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

まずは、スマホを戦車で動かすためのプロトタイプを作成してみましょう。次の手順で実施していきましょう。

  1. pi zero WH へ WebIOpi をセットアップ
  2. プロトタイプの画面
  3. プロトタイプのプログラム
  4. プロトタイプの実行

この4つの手順で、プロトタイプの確認を行いましょう。

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 のサービスを開始し、スマホに画面を出して実行してみます。

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

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

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

スポンサーリンク

最後に

ラズパイ戦車をスマホからコントロールするために、色々な準備をしてきました。

今回、前回使用したWebIOPiをzero WHに搭載して、戦車をコントロールします。

まずは、プロトタイプを作成して、スマホ画面や戦車の動きを模索した後、実際の戦車をスマホから動かしてみました。

それほど、大きな失敗もなく戦車が動いた時はうれしかったですなあ。

■思えば「リモコンタンク」の記事も増えてきました。

参考
Raspberry Pi で作るラジコン戦車 (その4: スマホで制御 WebIOPi)
『RaspberryPiで学ぶ電子工作』でラジコン操作につまったときの対処 その3

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

60爺

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