
【ラズパイ】raspberry pi zero でロボットを作製中(続1)
2017/01/28
前の状態から以下のハードウェアを追加
- 5年くらい前のwebカメラ
- 11acに対応したWLANドングル
やったこと
- node.jsを使ってGPIOをweb画面上から操作(これでラジコンみたいになった)
- 同じくweb画面にmjpgを使ってwebカメラの画像を表示
- web画面からオート操縦させる(前はpythonのコードを使ってHC-SR04 を制御していたが、今回はnode.jsのr-pi-usonicというライブラリを使った)
node.js ライブラリ
- express → nodeフレームワーク使用するため
- async → オート操縦を非同期で行うため
- sleep → オート操縦時の処理待ち時間設定のため
- r-pi-usonic → HC−SR04を使用するため
- onoff → GPIOを使用するため
web操作盤画面スクショ
表示された画面をタップすると小さくなる
動作の動画
ソースコード
var express= require('express'); var router = express.Router(); var async = require('async'); var sleep = require('sleep'); var usonic = require('r-pi-usonic'); var sensor = null; usonic.init(function (error) { if (!error) { sensor = usonic.createSensor(23, 17, 500); } }); var GPIO = require('onoff').Gpio; var onePlus = new GPIO(19, 'out'); var oneMinus = new GPIO(20, 'out'); var twoPlus = new GPIO(21, 'out'); var twoMinus = new GPIO(26, 'out'); var FORWARD = 'forward'; var BACKWARD = 'backward'; var LEFT = 'left'; var RIGHT = 'right' var LEFT_TURN = 'left_turn'; var RIGHT_TURN = 'right_turn'; var STOP = 'stop'; var AUTO = 'auto'; /* GET users listing. */ router.get('/', function(req, res, next) { // console.log(req.query); var action = req.query.action; var msg = ''; res.header("Content-Type", "application/json; charset=utf-8"); if (sensor == null) { msg = '超音波センサーが認識されていません!'; } switch (action) { case FORWARD : forward(); msg = '前進';// + (sensor != null ? 'Distance: ' + sensor().toFixed(2) + ' cm' : ''); break; case BACKWARD : backward(); msg = '後退'; break; case LEFT : onePlus.write(0); oneMinus.write(1); twoPlus.write(1); twoMinus.write(0); msg = '左折'; break; case RIGHT : onePlus.write(1); oneMinus.write(0); twoPlus.write(0); twoMinus.write(1); msg = '右折'; break; case LEFT_TURN : leftTurn(); msg = '方向転換(左)'; break; case RIGHT_TURN : rightTurn(); msg = '方向転換(右)'; break; case STOP : stop(); msg = '停止'; break; case AUTO : msg = "オート操縦"; if (sensor != null) { var turnCount = 0; var allCount = 0 ; forward(); async.whilst(function test(){ return allCount < 10; }, function func(callback) { if (sensor().toFixed(2) < 6) { turnCount++; } else { turnCount--; if (turnCount < 0) { turnCount = 0; } } if (3 < turnCount) { backward(); sleep.usleep(600000); leftTurn(); sleep.usleep(1000000); forward(); turnCount = 0; allCount++; } sleep.usleep(1000); callback(); }, function result(err){ if (err) { console.error(err); } else { sleep.sleep(2); stop(); console.log('finished'); } }); } else { msg += "不能"; } } res.send(msg); }); function leftTurn(){ onePlus.write(0); oneMinus.write(1); twoPlus.write(1); twoMinus.write(0); } function rightTurn(){ onePlus.write(1); oneMinus.write(0); twoPlus.write(0); twoMinus.write(1); } function forward(){ onePlus.write(0); twoPlus.write(0); oneMinus.write(1); twoMinus.write(1); } function backward(){ oneMinus.write(0); twoMinus.write(0); onePlus.write(1); twoPlus.write(1); } function stop(){ onePlus.write(0); oneMinus.write(0); twoPlus.write(0); twoMinus.write(0); } module.exports = router;
<html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,user-scalable=no" > <title>操作盤</title> <link rel="stylesheet" href="/stylesheets/style.css" type="text/css" /> <script type="text/javascript" src="/javascripts/jquery-2.2.2.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ var isAuto = false; var isW = false; $("button").on("touchstart", function(){ var id = $(this).attr("id"); if (id != 'auto') { $("#response").load("/users?action="+id); } else { isAuto = !isAuto; if (isAuto) { $("#response").load("/users?action="+id); $(this).css("background-color","#FF3333"); $("#forwad #left #right #backward").attr("disable",true); } else { $("#response").load("/users?action=stop"); $(this).css("background-color","#248"); $("#forwad #left #right #backward").attr("disable",false); } } }); $("button").on("touchend", function(){ var id = $(this).attr("id"); if (id != 'auto') { $("#response").load("/users?action=stop"); } }); $("#webcam img").click(function(){ if (!isW) { isW=true;$(this).css("width","20%"); } else { isW=false;$(this).css("width","100%"); } }); }); </script> </head> <body ontouchmove="event.preventDefault()" > <div id="webcam" style="text-align:center;"><img style='width:100%;' src="http://192.168.0.152:9000/?action=stream" /></div> <div style="margin-bottom: -3px;"><button style='width:100%;' id='forward'>⬆️</button></div> <div> <button style='width:49.89%;' id='left'>⬅️</button> <button style='width:49.89%;float:right;' id='right'>➡️</button> </div> <div style='clear:both;'></div> <div style="margin-top: -3px;margin-bottom: -3px;"><button style='width:100%;' id='backward'>⬇️</button></div> <div style="margin-top: 10px;margin-bottom: -3px;text-align:left;"><button style='width:30%;' id='auto'>🔁</button></div> <!-- <div> <button style='width:49.89%;' id='left_turn'>↪️</button> <button style='width:49.89%;float:right;' id='right_turn'>↩️</button> </div> --> <div style='clear:both;'></div> <div id="response"></div> </body> </html>
次のステップ
外部公開して遠隔から家の中見るとかガードロボにするとかかな..?