Raspberry PiでWebから操作できるラジコンクローラーを作る

Raspberry PiでWebから操作できるラジコンクローラーを作る

今回はRaspberry PiでWebから操作できるラジコンクローラーを作る方法をご紹介したいと思います。

昨年はArduinoを使用してラジコンを作成しました。それを今回はRaspberryPiで作り直してみました。

昨年の記事はこちら↓

ArduinoとXBeeとNode.jsを使用してWeb画面からラジコンを操作できるようにしてみた!

大きな変更点としては、Webカメラの映像を操作画面に表示できるようになったことと、シリアル通信ではなくWebサイトから直接ロボットを操作できるようになったため、通信で使用していたXBeeが不要になったところが大きいです。

今回の概要図

以下に作成手順を紹介していきます。

必要な材料を用意する

今回は以下の材料を用意しました。

本体部分

部品名 個数
Raspberry PI3 modelB 1
Webカメラ 「HD ウェブカメラ C270」 1
タミヤ トラック&ホイールセット 1
タミヤ ツインモーターギヤーボックス 1
タミヤ ユニバーサルプレート 1
タミヤ ロングユニバーサルアームセット 1
タミヤ ユニバーサル金具 4本セット 1
マジックテープ 1
ネジ M3 x 50mm 4本

回路部分

部品名 個数
ブレッドボード 1
DCモータドライブ「TA7267BP」 2
ジャンパーワイヤ 15本
電池ボックス 9V型 1
モバイルバッテリー 1
両面テープ 1

モーターと銅線の接続部分

部品名 個数
ハンダ 1
積層セラミックコンデンサ「0.1μF 50V」 2

工具

部品名 個数
+ドライバー 1
ハンダごて 1

Raspbian(Jessie)のインストール

RaspberryPiのOSにはRaspbian(Jessie)をインストールしておきます。後述で記載するRaspberry Piをアクセスポイント化して操作する場合にはRaspbianのJessieでないと方法を確立することができなかったためです。

今回は「Raspberry Pi3 Model B」に「NOOBS_v2_4_1」で「Raspbian Jessie」をインストールした前提で以下の手順を実施していきます。(※Raspberry Pi3 Model B+にもNOOBS_v2_4_1を入れようとしてみましたが、インストールできませんでした。B+に上記のOSは入れられないかもしれません。。)

WebIOPIのインストール

まずはWebIOPIをインストールします。これをインストールするとブラウザからRaspberryPiのGPIOを操作することが可能となります。インストール方法については別の記事にまとめましたのでこちらをご参照ください。

WebIOPIをRaspberry Piにインストールする方法

RaspberryPiを起動するとWebIOPIも同時に起動するように設定しておきます。

Mjpg-Streamerのインストール

今回はRaspberryPiに設置したWebカメラ映像を操作画面に表示するために「Mjpg-Streamer」を使用しますので以下の記事に沿ってインストールしておきます。「Mjpg-Streamer」はRaspberryPiの起動時に同時に起動するように設定しておきましょう。

RaspberryPiとMJPG-Streamerでライブストリーミングをする方法

操作プログラムの作成

ブラウザから操作するようのプログラムを用意しておきます。ブラウザの表示には「HTML」、ロボットの操作には「Python」を使用します。
コンソールを起動し、以下のコマンドでプログラムファイルを格納するフォルダを作成しておきます。

mkdir iot
mkdir iot/python
mkdir iot/html

フォルダとファイルは以下のような構成にします。

htmlフォルダに移動し、「index.html」を作成します。HTMLにはMJPG-Streamerの動画を表示する部分と、ロボットを操縦する部分で構成します。ボタンが押されたらPythonのスクリプトが呼ばれてモーターが動くようになっています。

MJPG-Streamerの映像を表示するためにIPアドレスの部分は書き換えてください。アクセスポイント化していない場合は割り当てられているIPアドレスを、アクセスポイント化しているときはアクセスポイント化の手順で設定したIPアドレスを指定します。

今回はアクセスポイント化した後のIPアドレスを記載しています。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <meta name="viewport" content="width=device-width">
 <title>Controller</title>
 <script type="text/javascript" src="/webiopi.js"></script>
 <script type="text/javascript">
 
 var imageNr = 0; // Serial number of current image
 var finished = new Array(); // References to img objects which have finished downloading
 var paused = false;
 
 function createImageLayer() {
 var img = new Image();
 img.style.position = "absolute";
 img.style.zIndex = -1;
 img.style.marginLeft="-160px";
 img.onload = imageOnload;
 img.onclick = imageOnclick;
 img.src = "http://172.24.1.1:8080/?action=snapshot&amp;n=" + (++imageNr);
 var webcam = document.getElementById("webcam");
 webcam.insertBefore(img, webcam.firstChild);
 }
 
 // Two layers are always present (except at the very beginning), to avoid flicker
 function imageOnload() {
 this.style.zIndex = imageNr; // Image finished, bring to front!
 while (1 < finished.length) {
 var del = finished.shift(); // Delete old image(s) from document
 del.parentNode.removeChild(del);
 }
 finished.push(this);
 if (!paused) createImageLayer();
 }
 
 function imageOnclick() { // Clicking on the image will pause the stream
 paused = !paused;
 if (!paused) createImageLayer();
 }
 
 webiopi().ready(function() {
 var parts;

 parts =webiopi().createButton("forwardButton","GO",function() {
 webiopi().callMacro("forwardCrawler");
 })
 $("#forward").append(parts);
 
 parts =webiopi().createButton("stopButton","STOP",function() {
 webiopi().callMacro("stopCrawler");
 })
 $("#stop").append(parts);
 
 parts =webiopi().createButton("backwardButton","BACK",function() {
 webiopi().callMacro("backwardCrawler");
 })
 $("#backward").append(parts);


 parts =webiopi().createButton("leftButton","Left",function() {
 webiopi().callMacro("leftCrawler");
 })
 $("#left").append(parts);
 
 parts =webiopi().createButton("rightButton","Right",function() {
 webiopi().callMacro("rightCrawler");
 })
 $("#right").append(parts);

 
 $("#forwardButton").css('background-color','green');
 $("#stopButton").css('background-color','green');
 $("#backwardButton").css('background-color','green');
 $("#leftButton").css('background-color','green');
 $("#rightButton").css('background-color','green');
 
 });
 
 
 </script>
 <style type="text/css">
 input[type="range"] {
 display: block;
 width: 150px;
 height: 30px;
 -webkit-transform:rotate(-90deg);
 -moz-transform:rotate(-90deg);
 -o-transform:rotate(-90deg);
 transform:rotate(-90deg);
 transform-origin:right bottom;
 }
 input[type="range"]::-webkit-slider-thumb{
 -webkit-appearance: none;
 -moz-appearance: none;
 appearance: none;
 background-color: #666;
 text-align:center;
 width: 40px;
 height: 40px;
 border:1px solid transparent;
 border-radius:20px;
 cursor:pointer;
 -moz-box-sizing:border-box;
 -webkit-box-sizing:border-box;
 box-sizing:border-box;
 }
 button {
 display: block;
 margin: 5px 5px 5px 5px;
 width: 100px;
 height: 45px;
 font-size: 24pt;
 font-weight: bold;
 color: black;
 }
 </style>
</head>

<body onload="createImageLayer();">
 <div align="center">
 	<div id="webcam" style="width: 320px;height: 240px;" >
 	<noscript>
 	<img src="http://172.24.1.1:8080/?action=snapshot" />
 	</noscript>
 	</div>
 </div>

<div align="center">
<table>
<tr>
<td>
<table border=0 cellspacing="10″ cellpadding="0″>
<tbody>
<tr>
<td></td>
<td><div id="forward"></div></td>
<td></td>
</tr>
<tr>
<td><div id="left"></div></td>
<td><div id="stop"></div></td>
<td><div id="right"></div></td>
</tr>
<tr>
<td></td>
<td><div id="backward"></div></td>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>

</div>
</body>
</html>

次に「Python」フォルダに移動してロボット操作用の「script.py」を作成します。HTMLでボタンが押されたら呼ばれるようになっています。動作は前進、後進、左旋回、右旋回、停止の動作となるようにしています。Pythonの内容を書き換えても変更内容が反映されない場合は一度リスタートしてみてください。

import webiopi
 
GPIO = webiopi.GPIO
 
IN1 = 15
IN2 = 18
IN3 = 23
IN4 = 24
 
def setup():
 GPIO.setFunction(IN1 , GPIO.OUT )
 GPIO.setFunction(IN2 , GPIO.OUT )
 GPIO.setFunction(IN3 , GPIO.OUT )
 GPIO.setFunction(IN4 , GPIO.OUT )

@webiopi.macro
def forwardCrawler():
 GPIO.digitalWrite(IN1, True )
 GPIO.digitalWrite(IN2, False )
 GPIO.digitalWrite(IN3, True )
 GPIO.digitalWrite(IN4, False )
 
@webiopi.macro
def backwardCrawler():
 GPIO.digitalWrite(IN1, False )
 GPIO.digitalWrite(IN2, True )
 GPIO.digitalWrite(IN3, False )
 GPIO.digitalWrite(IN4, True )
 
@webiopi.macro
def stopCrawler():
 GPIO.digitalWrite(IN1, False )
 GPIO.digitalWrite(IN2, False )
 GPIO.digitalWrite(IN3, False )
 GPIO.digitalWrite(IN4, False )

@webiopi.macro
def leftCrawler():
 GPIO.digitalWrite(IN1, True )
 GPIO.digitalWrite(IN2, False )
 GPIO.digitalWrite(IN3, False )
 GPIO.digitalWrite(IN4, True )

@webiopi.macro
def rightCrawler():
 GPIO.digitalWrite(IN1, False )
 GPIO.digitalWrite(IN2, True )
 GPIO.digitalWrite(IN3, True )
 GPIO.digitalWrite(IN4, False )

回路の作成

RaspberryPiからモーターを動かすために回路を作成します。回路は以下のような構成にしました。

ロボットの組み立て

ロボットは以下のような構成で組み立てます。タミヤのクローラーセットをベースにしていきます。横から見やすいようにクローラーのベルトは取り外していますが、本来は車輪にベルトが巻かれています。

①ツインモーターギヤーボックスを組み立て、モーターの端子に銅線をハンダ付けしておく

②ユニバーサル金具をL字に曲げ、ユニバーサルプレートとツインモーターギヤーボックスを固定

③二段目にロングユニバーサルアームを固定

④ロングユニバーサルアームセットの上にRaspberryPiをマジックテープで固定

⑤RaspberryPiの上にブレッドボードを両面テープで固定

⑥Webカメラを設置し、USBケーブルをRaspberryPiに差し込む

⑦一段目と二段目の間にモバイルバッテリーと9V電池を格納

WebカメラとRaspberry Piを外してみると以下のようになっています。

RaspberryPiのアクセスポイント化

WiFiなどがない場所で操縦したい場合はRaspberryPiのアクセスポイント化を実施しておきます。そうすることで直接PCやスマホなどからRaspberryPiを操作することができるようになります。アクセスポイント化の方法は以下の記事にまとめてありますのでこちらをご参照ください。

Raspberry Pi3(Raspbian Jessie)をアクセスポイント化してWiFiで動画配信する

ラジコンクローラーの操作方法

以下にラジコンクローラーの操作方法を記載していきます。

①モバイルバッテリーを接続してRaspberryPiの電源を入れる

②MJPG-Streamerを起動する(自動起動を設定していない場合のみ)

もしRaspberryPiの起動時に「MJPG-Streamer」の自動起動を設定していない場合は、モニターに接続して以下のコマンドでMJPG-Streamerを起動しておきましょう。

mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so -d /dev/video0 -y  -r 320x240 -f 15" -o "/usr/local/lib/mjpg-streamer/output_http.so -p 8080 -w ./www"

③他の端末からRaspberryPiのWiFiに接続する

他のPCかスマホで「http://プライベートIPアドレス:8000/」もしくは「http://アクセスポイント化で設定したIPアドレス:8000/」に接続して画面が表示されることを確認します。ポート番号の間違いにご注意ください。

画面が表示されたらモニターはもう必要ないので引き抜いておきます。

④他の端末に表示された操作画面からラジコンを操作する

これでボタンを押せばラジコンを前後左右に動作させることができます。動かない場合はこれまでの手順を見直してみてください。

実際に動かしてみる

実際に動かすとこのような動きになります。今回は公園に持っていって動かしてみました。真っ直ぐ動かしてもつまらないのでスラロームを作ってコースっぽくしています。

左右のクローラーのバランスが悪かったり、旋回が速すぎたりすると操作が難しいです。まだまだ改良の余地はありそうです。カメラの映像だけを見て操作するのも難しかったです。カメラの映像だけで操作するときは、カメラの角度を下向きにしてあげるとコーンが見えて操縦しやすかったです。

まとめ

今回はRaspberry PiでWebから操作できるラジコンクローラーを作ってみました。

上記のラジコンを作る過程で一番つまったのはRaspberryPiのアクセスポイント化でした。

アクセスポイント化するには、ラズパイとOSの組み合わせが重要になってくるようです。最新のバージョンでもできるようになってくれると嬉しいですよね。。

このラジコンをベースにして他の機能を設置したり、また別のラジコンを作ったりすることもできると思うので

また今後試してみたいと思います。

IoTカテゴリの最新記事