前の状態から以下のハードウェアを追加
- 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操作盤画面スクショ
表示された画面をタップすると小さくなる
動作の動画
ソースコード
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 |
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; |
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 |
<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> |
次のステップ
外部公開して遠隔から家の中見るとかガードロボにするとかかな..?