Hashimoto.Kojiのアイコン画像

obniz 2個使いでロボットアームを遠隔制御してみた

Hashimoto.Koji 2021年05月16日に作成  (2021年05月16日に更新)

はじめに

遠隔医療などのデモ用にグローブに搭載された加速度センサーを利用して、ロボットアームを制御するシステムを構築しました。

説明資料

設計書::タイトル
システム構成図
ロボットアームの操作方法

デモ動画

ここに動画が表示されます

ソースコード

ロボットアーム制御(2つのobnizでコード共有)

<!-- HTML Example --> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script> <script src="https://unpkg.com/obniz@3.7.1/obniz.js" crossorigin="anonymous" ></script> </head> <body> <div id="obniz-debug"></div> <h3>ハンド操作 <button id="hand_close" style="width: 80px; height: 30px;float: right;">とじる</button> <button id="hand_open" style="width: 80px; height: 30px;float: right;">ひらく</button> </h3> <h3>アーム1操作 <button id="arm1_close" style="width: 80px; height: 30px; float: right;">した</button> <button id="arm1_open" style="width: 80px; height: 30px; float: right;">うえ</button> </h3> <h3>アーム2操作 <button id="arm2_close" style="width: 80px; height: 30px; float: right;">した</button> <button id="arm2_open" style="width: 80px; height: 30px; float: right;">うえ</button> </h3> <h3>アーム3操作 <button id="arm3_close" style="width: 80px; height: 30px; float: right;">した</button> <button id="arm3_open" style="width: 80px; height: 30px; float: right;">うえ</button> </h3> <h3>土台操作 <button id="base_right" style="width: 80px; height: 30px; float: right;">右まわり</button> <button id="base_left" style="width: 80px; height: 30px; float: right;">左まわり</button> </h3> <script> var obniz = new Obniz("3047-9097"); document.body.style.webkitUserSelect = 'none'; obniz.onconnect = async function () { var obniz2 = new Obniz("3363-3232"); /*var pwm = obniz.getFreePwm(); pwm.start({io:10}); pwm.freq(10000); // 10k hz pwm.duty(99) // 50%*/ // 初期値設定 obniz.io0.output(true); // 開く obniz.io1.output(true); // 閉じる obniz.io2.output(true); // アーム1を上げる obniz.io3.output(true); // アーム1を下げる obniz.io4.output(true); // アーム2を下げる obniz.io5.output(true); // アーム2を上げる obniz.io6.output(true); // アーム3を上げる obniz.io7.output(true); // アーム3を下げる obniz.io8.output(true); // 右に回る obniz.io9.output(true); // 左に回る obniz.io10.output(false); // LED obniz2.onconnect = async function () { // 3軸加速度センサー var sensor = obniz2.wired("KXR94-2050", { vcc:0, gnd:1, x:3, y:4, z:5, enable:7, self_test:8 }); var status = { none: { value : 0, string : '真っすぐ'}, front_front: { value : 1, string : '表で前'}, front_back: { value : 2, string : '表で後ろ'}, front_left: { value : 3, string : '表で左'}, front_right: { value : 4, string : '表で右'}, back_front: { value : 5, string : '裏で前'}, back_back: { value : 6, string : '裏で後ろ'}, back_left: { value : 7, string : '裏で左'}, back_right: { value : 8, string : '裏で右'} }; const status_strings = ['真っすぐ', '表で前', '表で後ろ', '表で左', '表で右', '裏で前', '裏で後ろ', '裏で左', '裏で右'] var prev_status = status.none.value, current_status = status.none.value, stable_status = status.none.value, count = 0; sensor.onChange = function(values){ // console.log("status:" + current_status + "x:" + values.x + " y:" + values.y + " z:" +values.z); // console.log(" z:" +values.z); // 現在の状態を判定 // 上向き if(values.z > 0.2) { if(values.x > 0.2){ // console.log("表で前に傾いてる"); current_status = status.front_front.value; }else if(values.x < -0.5){ // console.log("表で後ろに傾いてる"); current_status = status.front_back.value; }else if(values.y > 0.2){ // console.log("表で左に傾いてる"); current_status = status.front_left.value; }else if(values.y < -0.5){ // console.log("表で右に傾いてる"); current_status = status.front_right.value; }else{ // console.log("表で真っすぐ"); current_status = status.none.value; } }else if(values.z < -0.5){ // 下向き if(values.x > 0.2){ // console.log("裏で前に傾いてる"); current_status = status.back_front.value; }else if(values.x < -0.5){ // console.log("裏で後ろに傾いてる"); current_status = status.back_back.value; }else if(values.y > 0.2){ // console.log("裏で右に傾いてる"); current_status = status.back_right.value; }else if(values.y < -0.5){ // console.log("裏で左に傾いてる"); current_status = status.back_left.value; }else{ // console.log("裏で真っすぐ"); current_status = status.none.value; } }else{ // console.log("裏で真っすぐ"); current_status = status.none.value; } // 前の状態と比較 if(current_status == prev_status) count++; else count = 0; // 閾値を超えたら安定した状態とする // 安定状態が変化したときだけ動かす // if(count > 15 && stable_status != current_status) if(((current_status == status.none.value && count > 2) || (current_status != status.none.value && count > 15) ) && stable_status != current_status) { console.log(status_strings[current_status]); stable_status = current_status; switch (current_status) { case status.none.value:  // 全部止める、trueで止まる,LEDはfalseで消える obniz.io0.output(true); // 開く obniz.io1.output(true); // 閉じる obniz.io2.output(true); // アーム1を上げる obniz.io3.output(true); // アーム1を下げる obniz.io4.output(true); // アーム2を下げる obniz.io5.output(true); // アーム2を上げる obniz.io6.output(true); // アーム3を上げる obniz.io7.output(true); // アーム3を下げる obniz.io8.output(true); // 右に回る obniz.io9.output(true); // 左に回る obniz.io10.output(false); // LED console.log("止まる"); break; case status.front_front.value: obniz.io4.output(false); // アーム2を下げる console.log("アーム2を下げる"); break; case status.front_back.value: obniz.io5.output(false); // アーム2を上げる console.log("アーム2を上げる"); break; case status.front_left.value: obniz.io0.output(false); // 開く obniz.io10.output(true); console.log("開く"); break; case status.front_right.value: obniz.io1.output(false); // 閉じる obniz.io10.output(true); console.log("閉じる"); break; case status.back_front.value: obniz.io3.output(false); // アーム1を下げる console.log("アーム1を下げる"); break; case status.back_back.value: obniz.io2.output(false); // アーム1を上げる console.log("アーム1を上げる"); break; case status.back_left.value: obniz.io9.output(false); // 左に回る console.log("左に回る"); break; case status.back_right.value: obniz.io8.output(false); // 右に回る console.log("右に回る"); break; } } // 前回の状態を保存 prev_status = current_status; } $("#slider").on('input', async function() { }); $("#hand_close").on('touchstart mousedown', function() { obniz.io0.output(true); obniz.io1.output(false); // obniz.io10.output(true); }); $("#hand_close").on('touchend mouseup', function() { obniz.io0.output(true); obniz.io1.output(true); // obniz.io10.output(false); }); $("#arm1_close").on('touchstart mousedown', function() { obniz.io2.output(true); obniz.io3.output(false); }); $("#arm1_close").on('touchend mouseup', function() { obniz.io2.output(true); obniz.io3.output(true); }); $("#arm2_close").on('touchstart mousedown', function() { obniz.io4.output(false); obniz.io5.output(true); }); $("#arm2_close").on('touchend mouseup', function() { obniz.io4.output(true); obniz.io5.output(true); }); $("#arm3_close").on('touchstart mousedown', function() { obniz.io6.output(true); obniz.io7.output(false); }); $("#arm3_close").on('touchend mouseup', function() { obniz.io6.output(true); obniz.io7.output(true); }); $("#base_left").on('touchstart mousedown', function() { obniz.io8.output(true); obniz.io9.output(false); }); $("#base_left").on('touchend mouseup', function() { obniz.io8.output(true); obniz.io9.output(true); }); $("#hand_open").on('touchstart mousedown', function() { obniz.io0.output(false); obniz.io1.output(true); // obniz.io10.output(true); }); $("#hand_open").on('touchend mouseup', function() { obniz.io0.output(true); obniz.io1.output(true); // obniz.io10.output(false); }); $("#arm1_open").on('touchstart mousedown', function() { obniz.io2.output(false); obniz.io3.output(true); }); $("#arm1_open").on('touchend mouseup', function() { obniz.io2.output(true); obniz.io3.output(true); }); $("#arm2_open").on('touchstart mousedown', function() { obniz.io4.output(true); obniz.io5.output(false); }); $("#arm2_open").on('touchend mouseup', function() { obniz.io4.output(true); obniz.io5.output(true); }); $("#arm3_open").on('touchstart mousedown', function() { obniz.io6.output(false); obniz.io7.output(true); }); $("#arm3_open").on('touchend mouseup', function() { obniz.io6.output(true); obniz.io7.output(true); }); $("#base_right").on('touchstart mousedown', function() { obniz.io8.output(false); obniz.io9.output(true); }); $("#base_right").on('touchend mouseup', function() { obniz.io8.output(true); obniz.io9.output(true); }); }; }; (function(console){ console.save = function(data, filename){ if(!data) { console.error('Console.save: No data') return; } if(!filename) filename = 'console.json' if(typeof data === "object"){ data = JSON.stringify(data, undefined, 4) } var blob = new Blob([data], {type: 'text/json'}), e = document.createEvent('MouseEvents'), a = document.createElement('a') a.download = filename a.href = window.URL.createObjectURL(blob) a.dataset.downloadurl = ['text/json', a.download, a.href].join(':') e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) a.dispatchEvent(e) } })(console) obniz.onclose = async function(){ $("#slider").off('input'); }; window.addEventListener("deviceorientation", event => { const beta = event.beta; const gamma = event.gamma; const alpha = event.alpha; console.log(beta); console.log(gamma); console.log(alpha); }); window.addEventListener( "devicemotion", function (event1) { let x = event1.accelerationIncludingGravity.x; let y = event1.accelerationIncludingGravity.y; document.write("<strong>Samurai</strong>"); }, true ); </script> </body> </html>
ログインしてコメントを投稿する