はじめての電子工作超入門

第58回 Arduinoでモーター再入門(その2)サーボモーターを遠隔で制御する!

2017-04-24 06.29.02

サーボモーターを改めて理解する企画、第2回です!

Arduinoで電子工作をするならやはりモーターは外せない部品です。これまで、連載の中でもいくつかモーターを扱ってデバイスなどを作成してきましたが、今回はおさらいの意味を込めて、特に利用頻度が高いと思われるサーボモーターの基本から詳しい使い方までじっくりと腰を据えて取り組んでみたいと思います。

前回の その1サーボモーターの基本 では、そもそもサーボモーターとは何か、どう動かすのか、という基本をおさらいしました。今回の記事では、さらに一歩踏み込んで、少し実用的なものを作ってみます。

目次

  1. サーボモーターでできること
  2. 組み合わせると可能性が広がる
  3. 遠隔でサーボモーターを操作する
  4. まとめ

1.サーボモーターでできること

サーボモーターでできることをおさらいしてみます。

まず、1つのサーボモーターでできることはどんなことがあるか見てみましょう。代表的な動作は、下記の二つでしょうか。

ボタンを押す

サーボモーターはその動作の角度を制御できます。というわけで、なんといってもボタンを押す機構を作るにはサーボモーターが最適です。下記の動画のような面白いデバイスを作ることもできますし、部屋のスイッチを押したり、カギをあけたり、ボタンを押すという動作ができるだけでいろいろなことができますね。

 

ものを動かす

第13回ではLEGOを使ったラジコンカーを製作しましたね。そこではステアリングの部分をサーボモーターを使って実装しました。

1つのサーボモーターだけだと操作の応用があまりないかもしれませんが、いろいろなパーツと組み合わせると世界が広がります!

 

2.サーボモーター実践編 組み合わせると可能性が広がる

実践編として、照明のスイッチを押す機械を作ってみたいと思います! Arduino+サーボ+3Dプリンター+Wi-Fiモジュールを組み合わせて実用的なものにしてみます。

まずは、せっかくなので、シンプルなスイッチを押すパーツを3Dプリンターで作ってみました。

今回使うサーボモーターは、これまで連載で使っていたものよりもトルクの強いMG996Rというサーボモーターを使います。このサーボモーターはトルクが9.4Kg、動作電圧は4.8~6.6Vとなっています。ほかの技術との組み合わせ、ということで今回は第3236回で利用したESP-WROOM-02のwifiと組み合わせて、PCやスマホからサーボモーターを動かしてスイッチを操作できるようにしてみます。

スイッチを押すためのパーツ

スイッチを押すためのパーツ

 

3Dプリンターで出力中

3Dプリンターで出力中

これで部屋のスイッチを押してみます。

部屋のスイッチ

部屋のスイッチ

 

サーボモーターにパーツの取り付け

サーボモーターにパーツの取り付け

部屋のスイッチに取り付け

部屋のスイッチに取り付け

部屋のスイッチへの取り付けは、壁紙が傷まないようにはってはがせるテープを利用。

はってはがせるテープ

はってはがせるテープ

準備ができたところで、さっそくスイッチオンの確認!

おぉ、スイッチが無事押されました。……んがしかし、このタイプのスイッチだとオン・オフができません。スイッチのオンオフができるように、両方を押せるようにします(早く気付け!)。

スイッチのサイズを計測

スイッチのサイズを計測

スイッチの幅を計測します。約4cmということで、4cm内の両脇にボタンがおさまるようなパーツを作成すればよいということがわかりました。ということで、下記のような両端に突起がついているパーツを作成しました。

両端を押せるパーツ

両端を押せるパーツ

 

サーボに取り付け

サーボモーターに取り付け

サーボモーターの取り付けが完了したら、次は離れた場所でも通信できるようにESP-WROOM-02にプログラムを書き込んでいきます。

2017-04-24 07.32.26

3.遠隔でサーボモーターを操作する

次に、このメカを部屋に設置されている無線ルーターにつないで、取得したIPアドレスをもとに、サーボモーターを操作できる機能を提供できるようにします。

今回、ESP-WROOM-02に電源が入ったとき、無線ルーターからIPアドレスを取得したあと、取得したIPアドレスをメールで伝えるための、外部APIをたたくための、報告用サーバー設定をできるようにしました。このIP報告用サーバー設定に、それぞれ作成した通知用のアドレスを利用することができます。(通知にIFTTTを使ってみるのもいいかもしれません)

#include <ESP8266WiFi.h>
#include <Servo.h> 

const char *ssid = "[wifi_ssid]";
const char *password = "[wifi_password]";

//IP報告用サーバー設定
const char* host = "xxxx.xx.xxx";
String url = "/xxxx/";
 
Servo myservo;
Servo myservo2;

WiFiServer server(80);

String IpAddress2String(const IPAddress& ipAddress)
{
 return String(ipAddress[0]) + String(".") +\
 String(ipAddress[1]) + String(".") +\
 String(ipAddress[2]) + String(".") +\
 String(ipAddress[3]) ; 
}
 
void setup() {
 Serial.begin(115200);
 delay(10);
 
 Serial.println("Start!");
 Serial.println();
 Serial.print("Connecting to ");
 Serial.println(ssid);
 
 WiFi.begin(ssid, password);
 
 while (WiFi.status() != WL_CONNECTED) {
 delay(1500);
 Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected");
 
 server.begin();
 Serial.println("Server started");
 Serial.println(WiFi.localIP());

//*********************************************************
// IPアドレスの通知
//*********************************************************
 WiFiClient client;
 const int httpPort = 80;
 if (!client.connect(host, httpPort)) {
 Serial.println("connection failed");
 return;
 }
 
 url += IpAddress2String(WiFi.localIP());
 client.print(String("GET ") + url + " HTTP/1.1\r\n" +
 "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
 delay(1000);
 Serial.print("Connecting url to ");
 Serial.println(url);

//*********************************************************************

}
 
void loop() {
 WiFiClient client = server.available();
 if (!client) {
 return;
 }
 
 Serial.println("new client");
 while(!client.available()){
 delay(1);
 }
 
 String req = client.readStringUntil('\r');
 Serial.println(req);
 client.flush();

 // Match the request
 int selectServo = 0;

int posSlash0 = req.indexOf("/");
String tmp = req.substring(0,posSlash0);
int posSlash1st = req.indexOf("/",1+posSlash0);
String action = req.substring(1+posSlash0,posSlash1st);
int posSlash2nd = req.indexOf("/",1+posSlash1st);
String sel = req.substring(1+posSlash1st,posSlash2nd);
int posSlash3rd = req.indexOf("/",1+posSlash2nd);
String valueTmp = req.substring(1+posSlash2nd,posSlash3rd);
int posSpace = valueTmp.indexOf(" ");
String value = valueTmp.substring(0,posSpace);

if(action == "favicon.ico HTTP"){
 return;
}
//GET /servo/1/60 HTTP/1.1

Serial.print("POS:");
Serial.print(posSlash1st);
Serial.print(":");
Serial.print(posSlash2nd);
Serial.print(":");
Serial.println(posSlash3rd);

Serial.print("ACTION:");
Serial.println(action);
Serial.print("SELECT SERVO:");
Serial.println(sel);
Serial.print("VALUE:");
Serial.println(value);

if(sel == "0"){
myservo.write(value.toInt());
}

 
 client.flush();
 
 String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>";
 s += "<head><meta name='viewport' content='width=device-width, initial-scale=1'>";
 s += "<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' media='screen'>"; 
 s += "<script type='text/javascript' src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>";
 s += "</head><body>";
 s += "\r\nSERVO ";
 s += sel;
 s += " is ";
 s += String(value);
 s += "<div class='container'><div class='row'>";
 s += "<div class='col-md-12'><h3>Servo0</h3></div>";
 s += "<div class='col-md-12'><a class='btn btn-primary' href='/servo/0/0'>ON</a></div>\n";
 s += "<div class='col-md-12'><a class='btn btn-info' href='/servo/0/50'>OFF</a></div>\n";
s += "<div class='col-md-12'><a class='btn btn-info' href='/servo/0/30'>STAY</a></div>\n";
s += "</div></div>";
 s += "</body>";
 s += "</html>\n";
 
 client.print(s);
 delay(1);
 Serial.println("Client disonnected");
}

 

ということで、プログラムも書き込めたので、いざ起動!

PCからON/OFFを切り替えるとESP-WROOM-02を通じてサーボモーターを制御することができました!

 

まとめ

今回、サーボモーターを無線で動作させて部屋のスイッチを制御することができました。これを応用すれば、いろいろなことができそうですね!
(※ただしストーブなどの火気があるものの制御などは危険ですのでやめましょう)

次回は、サーボモーターを複数組み合わせて、例のブツの製作に再チャレンジ……です。ついにというかいよいよというか、筆者赤川、雪辱を晴らしたいと思います!

2017-04-24 08.52.18

 

■関連記事

電子工作マニュアル Vol.4
赤川シホロ

電子工作や新しいデバイスをこよなく愛するエンジニア。日常生活のちょっとしたことを電子工作で作って試して、おもしろく過ごしたいと日々考えています。