LoginSignup
15
17

More than 5 years have passed since last update.

ESP8266(ESPr Developer)とMilkcocoaとローテーショナルサーボで簡易ラジコン

Last updated at Posted at 2016-06-21

1. 概要

簡単に動きを制御できるプラットフォームを作りたくて、まずは簡単にラジコンを作ってみることにしました。
スマホを傾けることで操作できるようになりますが、操作しにくいです。
まだとりあえず動いただけなので今後改良していくつもりですが、何かの役に立てばと思いまとめました。

2. 用意するもの

3. 作業環境

  • MacBook Air (13-inch, Mid 2012) & Mac OS 10.11.4
  • Arduino IDE 1.6.5

4. 参考サイト

5. ローテーショナルサーボとは

  • 通常のサーボが-180~180度といった角度制限があるのに比べて、連続で回転が可能なサーボ
  • ステッピングモータと違いドライバが不要なため簡単に車輪を制御できる(はず?)

6. ローテーショナルサーボの使い方(Arduino UNOでテスト)

  • まずはArduino Unoで動かしてみる

6.1 接続図

GWS S35 STD Arduino Uno
Pin 3
5V
GND

IMG_3359.JPG

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に飛びます)

20160621 Rotational Servo Test - YouTube

7. ラジコン化

  •  サーボを2つにしてmilkcocoaとESP8266を使ってスマホから動かしてみる
  •  スマホの本体の傾きによって前進、後退、右、左、その場で右回転、その場で左回転
  •  速度は傾きに関係なく一定

7.1 接続図

GWS S35 STD ESP8266
IO12 / IO13
3.3V
GND

20160621_Rotational_Servox2_Test.JPG

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に飛びます)
    • 動かし方に戸惑っている様子がお分かりいただけると思います。

20160621 Rotational Servo Test - YouTube

15
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
17