ある日のこと...
こんにちは、宇宙エンジニアのたくろーどんです。
前回,enebularを使って遠隔で操作できるXY軸ステージをつくってみました.
※【enebularは神ですか?】enebular×Node-REDで研究室IoTに挑戦!
動きは悪くなかったのですが,約5000円の予算でつくったこともあり研究用途でつかうとなると,少し不満がありました.
ということである日,先生に相談してみると
あっさり,OKがでたので...
Amazonで見つけた格安のステージ(モーター付き)とステッピングモータのドライバを購入しました.
そして,これをいつも通りNefry BTで制御し快適な研究ライフをもくろみます.
全体の概要
回路図
今回使用したステッピングモーター(NEMA 17)は,高い電圧・電流が必要なので,直流安定化電源を使用しています.詳細は仕様を見てみることをおすすめします.
ステッピングモータのドライバ詳細
①にドライバの設定について(どれくらいのパルス・電流値で制御するか)書いてあります.
説明通り,②のスイッチをON・OFFすることで,ドライバ側の設定を変更でき,ステッピングモーターの動きを変更できます.こちらも詳細は仕様を見てみることをおすすめします.
実験系の概要図
こちらは,前回の自作XY軸ステージと同じ仕組みです.
プログラム
Nefry BT側
#include <Nefry.h>
#include <NefryFireBase.h>
#define short_range 550
#define medium_range 1050
#define long_range 10500
//インスタンス生成
NefryFireBase firebase;
const int ena = D2; //????
const int dir = D1; //モーターの回転方向を制御
const int pul = D0; //パルスの入出力を制御
const int interval = 1000; //パルスを送る時間間隔
void setup() {
pinMode(ena, OUTPUT);
pinMode(dir, OUTPUT);
pinMode(pul, OUTPUT);
Serial.begin(115200);
firebase.begin("自分のfirebaseのURL");
}
void loop() {、
int motor = firebase.read("motor").toInt();
DataElement elem = DataElement();
if(motor == 1) {
Serial.println("Back");
for (int i=0; i<short_range; i++){
digitalWrite(dir,LOW);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}else if(motor == 2){
Serial.println("Foward");
for (int i=0; i<short_range; i++){
digitalWrite(dir,HIGH);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}else if(motor == 3){
Serial.println("Foward_long");
for (int i=0; i<medium_range; i++){
digitalWrite(dir,LOW);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}else if(motor == 4){
Serial.println("Foward_long");
for (int i=0; i<medium_range; i++){
digitalWrite(dir,HIGH);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}else if(motor == 5){
Serial.println("long_long");
for (int i=0; i<long_range; i++){
digitalWrite(dir,LOW);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}else if(motor == 6){
Serial.println("Foward_long");
for (int i=0; i<long_range; i++){
digitalWrite(dir,HIGH);
digitalWrite(ena,LOW);
digitalWrite(pul,HIGH);
delayMicroseconds(interval);
digitalWrite(pul,LOW);
delayMicroseconds(interval);
}
elem.setValue("motor", 0);
firebase.write("motor", &elem);//FireBaseのデータを書き込むFireBaseのデータを書き込む
}
stopMotor();
delay(200);
}
void stopMotor() {
digitalWrite(dir, HIGH); // low CW(時計回り) / high CCW(反時計回り)
digitalWrite(ena, LOW);
digitalWrite(pul, LOW);
}
マイコン側
[
{
"id": "be0d6811.0c5098",
"type": "inject",
"z": "b1df9a03.d68bf8",
"name": "",
"topic": "",
"payload": "{\"motor\":1}",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 120,
"y": 480,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "bcb4c067.326a5",
"type": "inject",
"z": "b1df9a03.d68bf8",
"name": "",
"topic": "",
"payload": "{\"motor\":2}",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 119.99999618530273,
"y": 551.9999961853027,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "3e380a81.fa6686",
"type": "inject",
"z": "b1df9a03.d68bf8",
"name": "",
"topic": "",
"payload": "{\"motor\":3}",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 119.99999618530273,
"y": 611.9999961853027,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "82bf19f7.816248",
"type": "inject",
"z": "b1df9a03.d68bf8",
"name": "",
"topic": "",
"payload": "{\"motor\":4}",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 119.99999618530273,
"y": 671.9999961853027,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "41ef2e0b.1028f",
"type": "firebase modify",
"z": "b1df9a03.d68bf8",
"name": "",
"firebaseconfig": "",
"childpath": "",
"method": "set",
"value": "msg.payload",
"priority": "msg.priority",
"x": 819.1001091003418,
"y": 736.800051689148,
"wires": [
[]
]
},
{
"id": "a9fd5c2b.656f5",
"type": "template",
"z": "b1df9a03.d68bf8",
"name": "HTML",
"field": "payload",
"fieldType": "msg",
"format": "html",
"syntax": "mustache",
"template": "<!DOCTYPE html>\n<html lang=\"ja\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>加速度検出</title>\n</head>\n \n<body>\n<div id=\"datatxt\">データの表示</div> \n <btn class = 'btn'>\n <a href=\"\">右</a> \n </btn>\n<script>\n \n\n</script>\n</body>\n</html>",
"x": 370.10003662109375,
"y": 103.19999694824219,
"wires": [
[
"6199aa01.d1ee44"
]
]
},
{
"id": "6199aa01.d1ee44",
"type": "template",
"z": "b1df9a03.d68bf8",
"name": "CSS",
"field": "payload",
"fieldType": "msg",
"format": "css",
"syntax": "mustache",
"template": ".btn{\n width:90px;\n height:90px;\n line-height:90px;\n}\n.btn a{\n display:block;\n width:100%;\n height:100%;\n text-decoration: none;\n background:#FF8181;\n text-align:center;\n color:#FFFFFF;\n font-size:20px;\n font-weight:bold;\n border-radius:50px;\n -webkit-border-radius:50px;\n -moz-border-radius:50px;\n box-shadow:0px 5px 8px 0px #BBBBBB ;\n text-shadow:0px 1px 1px #444444 ;\n}\n.btn a:hover{\n background:#FF0303;\n color:#FFFFFF;\n margin-top:5px;\n box-shadow:none;\n}",
"x": 493.00000762939453,
"y": 104.00000095367432,
"wires": [
[
"4a88979.d9e9e68"
]
]
},
{
"id": "b4b28800.b0f228",
"type": "http in",
"z": "b1df9a03.d68bf8",
"name": "",
"url": "stage",
"method": "get",
"swaggerDoc": "",
"x": 184,
"y": 99,
"wires": [
[
"a9fd5c2b.656f5"
]
]
},
{
"id": "4a88979.d9e9e68",
"type": "http response",
"z": "b1df9a03.d68bf8",
"name": "",
"x": 784,
"y": 113,
"wires": []
},
{
"id": "d7d1d295.5d8bf",
"type": "inject",
"z": "b1df9a03.d68bf8",
"name": "",
"topic": "",
"payload": "{\"motor\":0}",
"payloadType": "json",
"repeat": "",
"crontab": "",
"once": false,
"x": 124.99999618530273,
"y": 410.99999618530273,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "8b6bfa6d.367128",
"type": "comment",
"z": "b1df9a03.d68bf8",
"name": "左",
"info": "",
"x": 83.10000419616699,
"y": 511.8000240325928,
"wires": []
},
{
"id": "55d9a346.66ce3c",
"type": "comment",
"z": "b1df9a03.d68bf8",
"name": "右",
"info": "",
"x": 81.99999618530273,
"y": 444.9999990463257,
"wires": []
},
{
"id": "da155616.411bb8",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Back(5mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":1}",
"payloadType": "json",
"topic": "",
"x": 610,
"y": 200,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "fce48abb.06cc78",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Foward(5mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":2}",
"payloadType": "json",
"topic": "",
"x": 620,
"y": 240,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "e9c8c2c.cb14e4",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Back(10mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":3}",
"payloadType": "json",
"topic": "",
"x": 610,
"y": 280,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "44413259.eb1bec",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Foward(10mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":4}",
"payloadType": "json",
"topic": "",
"x": 620,
"y": 320,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "e5da3f9f.b4543",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "offset",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"distance_x\":0, \"distance_y\":0}",
"payloadType": "json",
"topic": "",
"x": 590,
"y": 160,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "8d1b8b68.150858",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Back(100mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":5}",
"payloadType": "json",
"topic": "",
"x": 880,
"y": 200,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "a7b7733a.5de8c",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Foward(100mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":6}",
"payloadType": "json",
"topic": "",
"x": 880,
"y": 240,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "ecc8e229.7d44b",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Back(10mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":7}",
"payloadType": "json",
"topic": "",
"x": 870,
"y": 280,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "13b94a18.4c5bd6",
"type": "ui_button",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "f7557849.9ddfe8",
"order": 0,
"width": 0,
"height": 0,
"passthru": false,
"label": "Foward(10mm)",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "{\"motor\":8}",
"payloadType": "json",
"topic": "",
"x": 880,
"y": 320,
"wires": [
[
"41ef2e0b.1028f"
]
]
},
{
"id": "839fb64e.6538f8",
"type": "ui_gauge",
"z": "b1df9a03.d68bf8",
"name": "",
"group": "373ca1aa.76bade",
"order": 0,
"width": 0,
"height": 0,
"gtype": "gage",
"title": "gauge",
"label": "units",
"format": "{{value}}",
"min": "-10",
"max": 10,
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"x": 990,
"y": 100,
"wires": []
},
{
"id": "6535557a.547ddc",
"type": "ui_text",
"z": "b1df9a03.d68bf8",
"group": "373ca1aa.76bade",
"order": 0,
"width": 0,
"height": 0,
"name": "",
"label": "distance_x",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 920.1000137329102,
"y": 46.4000129699707,
"wires": []
},
{
"id": "3117451a.3e75fa",
"type": "firebase.on",
"z": "b1df9a03.d68bf8",
"name": "",
"firebaseconfig": "",
"childpath": "distance_x",
"atStart": true,
"eventType": "value",
"queries": [
{
"name": "orderByChild",
"value": "distance_x"
}
],
"x": 478.1000061035156,
"y": 42.60000038146973,
"wires": [
[
"839fb64e.6538f8",
"6535557a.547ddc"
]
]
},
{
"id": "f7557849.9ddfe8",
"type": "ui_group",
"z": "",
"name": "Group",
"tab": "f58979ef.30ad38",
"order": null,
"disp": true,
"width": "6",
"collapse": false
},
{
"id": "373ca1aa.76bade",
"type": "ui_group",
"z": 0,
"name": "Group",
"tab": "5d8bed2f.3397a4",
"order": null,
"disp": true,
"width": 6
},
{
"id": "f58979ef.30ad38",
"type": "ui_tab",
"z": 0,
"name": "Tab",
"icon": "dashboard",
"order": 0
},
{
"id": "5d8bed2f.3397a4",
"type": "ui_tab",
"z": 0,
"name": "Tab",
"icon": "dashboard",
"order": 0
}
]
動かしてみる
操作画面はこのような感じです.
実測で,移動量をボタンで割り当てています.
そして,以下のように動きます!
遠隔操作できるステージが、ちゃんと真空チャンバー内で動いてくれるので、研究費節約しつつ実験効率が半端なく上がった(できるだけ実験条件変えなくてよいのも◎)というのが週末のハイライト...お手軽IoT pic.twitter.com/tYjeNX3fGD
— たくろーどん@宇宙エンジニア (@takudooon) 2018年12月9日
終わりに
enebularは便利!