スマホからBluetooth経由でサーボモータを無線制御してみます。
Androidアプリは自作、BluetoothLE(以下BLE)経由で情報を送信し、Arduinoで受けてサーボモータをコントロールしてます。今回はArduino側スケッチ(ソース)作成の内容をメインに紹介したいと思います。スマホ側のアプリ作成方法はこちらで紹介しています。
スマホ側をセントラル、Arduino(サーボモータ)側をペリフェラルとしています。
▼動画▼
使い廻しの動画ですみません。準備するものはArduino101、サーボモータ、スマホとPC(開発環境)です。スマホはBLEに対応している必要があります。Arduinoとサーボモータは直付け。スマホからサーボモータ位置情報を送信して制御、Arduino側のループ処理時間を受信してスマホに表示しています。
以下からArduino側スケッチの中身を紹介します。この記事の最後にスケッチ全体を掲載しています。
BLEPeripheral blePeripheral; BLEService CurieBLEService("19B10010-E8F2-537E-4F6C-D104768A1214"); BLEIntCharacteristic servoCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLEWrite); BLECharacteristic deviceInfoCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead, 20); Servo servo;
▲BLE通信クラスとサーボモータクラスのインスタンス化をします。オブジェクト名は上記のようにしています。今回、「characteristic」はサーボモータの角度情報(受信用)とループ処理時間(送信用)の2つ準備しました。
servoCharacteristic.setEventHandler(BLEWritten, servoCharacteristicWritten);
▲今回、スマホからの受信はイベントハンドラを使って処理します。引数に呼び出される関数名を入れておきます。
servo.attach(9);
▲サーボモータの制御信号は9番pinを使用します。
void loop() { dt = (micros() - preTime) / 1000000; //s preTime = micros(); sendBLE(); }
▲メインループ処理では、ループの処理時間を計測してBLE送信用の関数を呼び出しているだけです。
inline void sendBLE() { char s[8]; char buf[20]; float freq = 1 / dt; dtostrf(freq, 1, 1, s); sprintf(buf, "%s", s); int bufSize = strlen(buf); deviceInfoCharacteristic.setValue((unsigned char*)buf, bufSize); }
▲BLE送信部分です。計測したループ処理時間を周波数にして、文字列に変換してます。BLE送信部は最後の一行のみです。floatやint型でもよかったのですが、文字列送信(char型)を試してみたかったのでこのような少し面倒な形になってます。ここで送信した情報をスマホ画面で表示しています。
void servoCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { servo.writeMicroseconds((1600 + (1020 / 90) * servoCharacteristic.value())); digitalWrite(13, LED); LED = LED - 1; }
▲BLE受信部分です。イベントハンドラを使用。スマホから受信したデータでサーボモータを制御しています。今回サーボモータの制御はライブラリを使用しています。あとデータの受信に合わせてオンボードのLEDをOn/Offしています。計算式の部分は使用するサーボモータに合わせて調整が必要かと思います。(大体こんなものだと思いますが・・。)
ライブラリを使用せずサーボモータを制御する方法はこちらで紹介してます。サーボモータについても少し触れています。
Arduino側のスケッチ概要はこんなところです。ライブラリを使用すれば割と簡単にBLE通信を試すことができると思います。スマホを使用した制御やロガーなどができ、工作の幅が広がると思います
▼スケッチ全体▼
#include "CurieBLE.h" #include <Servo.h> bool LED; float preTime, dt; BLEPeripheral blePeripheral; BLEService CurieBLEService("19B10010-E8F2-537E-4F6C-D104768A1214"); BLEIntCharacteristic servoCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLEWrite); BLECharacteristic deviceInfoCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead, 20); Servo servo; void setup() { pinMode(13, OUTPUT); blePeripheral.setLocalName("CurieBLE"); blePeripheral.setAdvertisedServiceUuid(CurieBLEService.uuid()); blePeripheral.addAttribute(CurieBLEService); blePeripheral.addAttribute(servoCharacteristic); blePeripheral.addAttribute(deviceInfoCharacteristic); servoCharacteristic.setEventHandler(BLEWritten, servoCharacteristicWritten); blePeripheral.begin(); servo.attach(9); } void loop() { dt = (micros() - preTime) / 1000000; //s preTime = micros(); sendBLE(); } inline void sendBLE() { char s[8]; char buf[20]; float freq = 1 / dt; dtostrf(freq, 1, 1, s); sprintf(buf, "%s", s); int bufSize = strlen(buf); deviceInfoCharacteristic.setValue((unsigned char*)buf, bufSize); } void servoCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { servo.writeMicroseconds((1600 + (1020 / 90) * servoCharacteristic.value())); digitalWrite(13, LED); LED = LED - 1; }
コメント
こんなにわかりやすく説明してくれてありがとうございます。
これからも頑張ってください。
Arduino UNOでも同じプログラム、スマホ側の開発環境はMIT App lnventor 2でも開発は可能でしょうか?
匿名希望さん、こんにちは。
残念ながら「UNO」のみではBluetooth通信はできません。本稿で紹介した「101」ではBluetooth内蔵してるためその前提でのソースとなります。
話が変わりますが少し前(2017/9)にintelがcurieの生産終了を発表したようで、もうすでに「101」を入手するのは困難かもしれません。
「UNO」+「Bluetoothモジュール」等であれば開発が可能なので今から検討するのであればそちらをおすすめします。
返信ありがとうございます! BLE端末を使用して実験してみようと思います。
ご教授ありがとうございました。