1. 概要
簡単に動きを制御できるプラットフォームを作りたくて、まずは簡単にラジコンを作ってみることにしました。
スマホを傾けることで操作できるようになりますが、操作しにくいです。
まだとりあえず動いただけなので今後改良していくつもりですが、何かの役に立てばと思いまとめました。
2. 用意するもの
3. 作業環境
- MacBook Air (13-inch, Mid 2012) & Mac OS 10.11.4
- Arduino IDE 1.6.5
4. 参考サイト
- 建築発明工作ゼミ2008: Arduino サーボ制御
- ESP8266 (ESP-WROOM-02) でサーボを制御する - Qiita
- スマホの向きをPCのブラウザで表示 Tutorial | Milkcocoa
5. ローテーショナルサーボとは
- 通常のサーボが-180~180度といった角度制限があるのに比べて、連続で回転が可能なサーボ
- ステッピングモータと違いドライバが不要なため簡単に車輪を制御できる(はず?)
6. ローテーショナルサーボの使い方(Arduino UNOでテスト)
- まずはArduino Unoで動かしてみる
6.1 接続図
GWS S35 STD | Arduino Uno |
---|---|
白 | Pin 3 |
赤 | 5V |
黒 | GND |
6.2 プログラム
Rotational_Servo_UNO.ino
// Arduino UNOでローテーショナルサーボGWS S35 STDを制御
#include<Servo.h>
Servo servo; // サーボのインスタンス
void setup() {
// サーボの信号線を3番ピンに接続
servo.attach(3);
}
void loop() {
// サーボ出力 1.5ms(停止)を中心に、1.0ms~2.0msのパルス幅で動く。パルス幅によって速度が変わる
servo.writeMicroseconds(1600);
delay(500);
servo.writeMicroseconds(1500);
delay(500);
servo.writeMicroseconds(1400);
delay(500);
servo.writeMicroseconds(1500);
delay(500);
servo.writeMicroseconds(2000);
delay(500);
servo.writeMicroseconds(1500);
delay(500);
servo.writeMicroseconds(1000);
delay(500);
servo.writeMicroseconds(1500);
delay(500);
}
6.3 実行結果
- 実行画面(20160621 Rotational Servo Test - YouTubeに飛びます)
7. ラジコン化
- サーボを2つにしてmilkcocoaとESP8266を使ってスマホから動かしてみる
- スマホの本体の傾きによって前進、後退、右、左、その場で右回転、その場で左回転
- 速度は傾きに関係なく一定
7.1 接続図
- サーボの定格は5Vですが、とりあえず3.3Vで動かしています。
- タイヤはタミヤの工作キットで適当に作ってみました。
- 使ったのはこの辺りだと思います。サーボは穴をつなげた溝に挟んでるだけです。
- 楽しい工作シリーズ-No-157-ユニバーサルプレート-2枚セット-70157
- 楽しい工作シリーズ-No-140-プーリー-Sセット-70140
- 楽しい工作シリーズ-No-141-プーリー-Lセット-70141
GWS S35 STD | ESP8266 |
---|---|
白 | IO12 / IO13 |
赤 | 3.3V |
黒 | GND |
7.2 プログラム(ESP8266)
- wifiのSSIDとPASS、Milkcocoaのapp idは各自のものをご使用ください
Rotational_Servo_ESP8266.ino
// ESP8266でローテーショナルサーボGWS S35 STDを制御
#include <ESP8266WiFi.h>
#include <Milkcocoa.h>
#include<Servo.h>
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "*****" // 各自の環境に応じて変更してください
#define WLAN_PASS "*****" // 各自の環境に応じて変更してください
/************************* Your Milkcocoa Setup *********************************/
#define MILKCOCOA_APP_ID "*****" // 各自の環境に応じて変更してください
#define MILKCOCOA_DATASTORE "gravity"
/************************* Harware Setup *********************************/
#define MotorPinR 12 // PWM用ピンアサイン GPIO 12 -> GWS S35 STD Signal
#define MotorPinL 13 // PWM用ピンアサイン GPIO 13 -> GWS S35 STD Signal
Servo servoR; // サーボのインスタンス
Servo servoL; // サーボのインスタンス
/************* Milkcocoa Setup (you don't need to change this!) ******************/
#define MILKCOCOA_SERVERPORT 1883
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
const char MQTT_SERVER[] PROGMEM = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] PROGMEM = __TIME__ MILKCOCOA_APP_ID;
Milkcocoa milkcocoa = Milkcocoa(&client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID);
void setup() {
Serial.begin(115200);
delay(10);
Serial.println(F("Milkcocoa SDK demo"));
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println( milkcocoa.on(MILKCOCOA_DATASTORE, "push", onpush) );
// サーボの信号線を12番ピンに接続
servoR.attach(MotorPinR);
servoL.attach(MotorPinL);
}
void loop() {
milkcocoa.loop();
}
void onpush(DataElement *elem) {
int gravityX = elem->getInt("x"); //
int gravityY = elem->getInt("y"); //
Serial.print("x:");
Serial.print(gravityX);
Serial.print(" y:");
Serial.println(gravityY);
if(gravityY > 1){
if(gravityX > 1){
servoR.writeMicroseconds(1000);
servoL.writeMicroseconds(1500); // stop
}
else if(gravityX < -1){
servoR.writeMicroseconds(1500); // stop
servoL.writeMicroseconds(2000);
}
else if(gravityX >= -1 && gravityX <= 1){ // 直進
servoR.writeMicroseconds(1000);
servoL.writeMicroseconds(2000);
}
}
else if(gravityY < -1){
if(gravityX > 1){
servoR.writeMicroseconds(1500); // stop
servoL.writeMicroseconds(2000);
}
else if(gravityX < -1){
servoR.writeMicroseconds(1000);
servoL.writeMicroseconds(1500); // stop
}
else if(gravityX >= -1 && gravityX <= 1){ // 後退
servoR.writeMicroseconds(2000);
servoL.writeMicroseconds(1000);
}
}
else if(gravityY >= -1 && gravityY <= 1){ // Break
if(gravityX > 1){
servoR.writeMicroseconds(1000);
servoL.writeMicroseconds(1000);
}
else if(gravityX < -1){
servoR.writeMicroseconds(2000);
servoL.writeMicroseconds(2000);
}
else if(gravityX >= -1 && gravityX <= 1){ // 停止
servoR.writeMicroseconds(1500);
servoL.writeMicroseconds(1500);
}
}
delay(10);
};
7.3 プログラム(スマホ側)
- スマホ側のプログラムはjsdo.itを利用
- QRコードを使ってスマホで実行することで、スマホの傾きのデータがMilkcocoaに送信される
- スマートフォン側のコードを書く Tutorial | Milkcocoaをベースにしました。
- 一旦ロック画面などになって反応しない時はページを再読み込みするとうまくいくことも
- app_idは自分のものを使用してください
javascript
window.onload = function(){
window.setInterval(sendToMilkcocoa, 100);
//var currentMode = 'portrait';
var output = document.getElementById('output');
var prevRoundX = 0;
var prevRoundY = 0;
// app_idは自分のものに書き換えてください
var milkcocoa = new MilkCocoa("*****.mlkcca.com");
var ds = milkcocoa.dataStore('gravity');
window.addEventListener('devicemotion', function(e){
gravity = e.accelerationIncludingGravity;
output.innerHTML = 'x方向: '+Math.round(gravity.x) + '<br>y方向: '+Math.round(gravity.y);
sendModeFromGravityValue(gravity);
},true);
function sendToMilkcocoa(){
var roundX = Math.round( gravity.x ) ;
var roundY = Math.round( gravity.y ) ;
if (roundX != prevRoundX){
//ds.push({x: roundX});
if (roundY != prevRoundY){
ds.push({x: roundX, y: roundY});
}
else{
ds.push({x: roundX, y: PrevRoundY});
}
}
else if (roundY != prevRoundY){
ds.push({x: PrevRoundX, y: roundY});
}
PrevRoundX = roundX;
PrevRoundY = roundY;
}
};
html
<body>
<div id="output"></div>
<script src='https://cdn.mlkcca.com/v2.0.0/milkcocoa.js'></script>
<script src="main-sp.js"></script>
</body>
css
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: #dff;
font: 30px sans-serif;
}
7.4 実行結果
- 実行画面(20160621 Rotational Servo Test - YouTubeに飛びます)
- 動かし方に戸惑っている様子がお分かりいただけると思います。