#はじめに
この記事では,TOPPERS/R2CAにより,NCES IoT Base Shield に接続したセンサ(Ultrasonic Ranger)の値をMilkcocoaにsendしたり,Milkcocoa経由で受け取ったデータによりサーボを駆動する方法について説明します.
NCES IoT Base Shiledについては以下の記事を参照して下さい.
- Arduino M0 Pro でマルチタスクプログラミング : NCES IoT Base Shield : Wifi/SD機能
- Arduino M0 Pro でマルチタスクプログラミング : NCES IoT Base Shield : GROVE機能
必要なハードウェア
- Arduino M0 Pro
- NCES IoT Base Shield
- Grove Servo
- Grove - Ultrasonic Ranger
- Windows PC
- Windows7とWindows10で動作を確認しています.
- USB(microB)ケーブル
- ボードには付属していないので用意して下さい.
#サーバー側の設定
Arduino M0 Pro でマルチタスクプログラミング : Milkcocoaへの接続を参考にサーバー側の設定をして下さい.
##ハードウェアセットアップ
M0にNCES IoT Base Shield を取り付けて,さらにGrove ServoをD2に,とGrove - Ultrasonic RangerをD3に接続します.
##ソフトウェアセットアップ
プログラムは以下にあります.
- examples\Milkcocoa_NCESIoT
コードは次のようになっています.STA_SSID/STA_PASSWORDは使用する環境に合わせて定義して下さい.MILKCOCOA_APP_ID/MILKCOCOA_DATASTOREも同様にサーバーの設定に合わせて定義します.
タスク数は2個で,片方のタスク(loop()を実行するメインタスク)で,Ultora Sonicの値を取得してRangeInCentimetersのキーに設定してpush()で送信します.
もう片方のタスク(loop1()を実行するtask1)は,milkcocoa.loop(1)でデータが来ているかチェックして,データが来ていれば,onpush()が実行されます.onpush()は,SERVOのキーが送信された場合は整数値に変換して,0から180の範囲ならサーボを指定された角度で駆動します.
#define R2CA_NUM_TASK 1
#include "r2ca.h"
#include "ESP8266.h"
#include "Milkcocoa.h"
#include "Client_ESP8266.h"
#include "../examples_gdef.h"
#define MILKCOCOA_SERVERPORT 1883
ESP8266Client wifi_client;
const char MQTT_SERVER[] PROGMEM = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] PROGMEM = __TIME__ MILKCOCOA_APP_ID;
Milkcocoa milkcocoa = Milkcocoa(&wifi_client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID);
#include <Servo.h>
Servo myservo;
#include "Ultrasonic.h"
Ultrasonic ultrasonic(3);
extern void onpush(DataElement *elem);
bool setup_done = false;
void setup()
{
int ret;
Serial.begin(115200);
Serial.print("Milkcocoa NCES IoT demo");
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(STA_SSID);
ret = WiFi.begin(Serial5, 115200);
if(ret == 1) {
Serial.print("Cannot communicate with ESP8266.");
while(1);
} else if(ret == 2) {
Serial.println("FW Version mismatch.");
Serial.print("FW Version:");
Serial.println(WiFi.getVersion().c_str());
Serial.print("Supported FW Version:");
Serial.println(ESP8266_SUPPORT_VERSION);
while(1);
} else {
Serial.print("begin ok\r\n");
}
Serial.print("FW Version:");
Serial.println(WiFi.getVersion().c_str());
if (WiFi.setOprToStation()) {
Serial.print("to station ok\r\n");
} else {
Serial.print("to station err\r\n");
}
if (WiFi.joinAP(STA_SSID, STA_PASSWORD)) {
Serial.print("Join AP success\r\n");
Serial.print("IP: ");
Serial.println(WiFi.getLocalIP().c_str());
} else {
Serial.print("Join AP failure\r\n");
}
if (WiFi.stopServer()) {
Serial.print("Stop server ok\r\n");
} else {
Serial.print("Stop server err\r\n");
}
if (WiFi.disableMUX()) {
Serial.print("single ok\r\n");
} else {
Serial.print("single err\r\n");
}
if (milkcocoa.on(MILKCOCOA_DATASTORE, "push", onpush)){
Serial.println("milkcocoa on sucesss");
}
else {
Serial.println("milkcocoa on failure");
}
myservo.attach(2);
setup_done = true;
Serial.println("setup end\r\n");
}
void loop() {
int8_t ret;
int8_t push_ret;
long RangeInCentimeters;
RangeInCentimeters = ultrasonic.MeasureInCentimeters();
Serial.print(RangeInCentimeters);//0~400cm
Serial.println(" cm");
DataElement elem = DataElement();
elem.setValue("RangeInCentimeters", (int)RangeInCentimeters);
do {
push_ret = milkcocoa.push(MILKCOCOA_DATASTORE, &elem);
if (push_ret != 0) {
Serial.println("Milkcocoa.push() error.");
Serial.println(milkcocoa.pushErrorString(push_ret));
Serial.println(push_ret);
Serial.println("Retrying MQTT push in 5 seconds...");
delay(5000);
}
}while(push_ret != 0);
Serial.println("Push success.");
delay(2000);
if (Serial.available() > 0) {
Serial.read();
Serial.print("Pause : Input any char to continue.\n\r");
while(!(Serial.available() > 0));
Serial.print("Resume.\n\r");
Serial.read();
}
}
void onpush(DataElement *pelem) {
char *data;
int pos;
if(!pelem->getString("SERVO", &data)) {
return;
};
pos = atoi(data);
if ((pos >= 0) && (pos <= 180)) {
myservo.write(pos);
Serial.print("Ser Servo : ");
Serial.println(pos);
}
}
void loop1() {
int8_t ret;
while((ret = milkcocoa.loop(1)) != 0) {
Serial.println("Milkcocoa.loop() connection error.");
Serial.println(milkcocoa.connectErrorString(ret));
Serial.println(ret);
Serial.println("Retrying MQTT connection in 5 seconds...");
delay(5000);
}
delay(100);
}
実行後,データストアにUltrasonic Rangerの値がストアされていることが確認できます.また,Milkcocoa Testerにより,SERVOのキーに値を指定して送信することにより,サーボが動作することを確認できます.
#おわりに
この記事では,TOPPERS/R2CAによる NCES IoT Base Shield とMilkcocoaの連携方法について説明しました.マルチタスクが使えるので,Milkcocoaへの送信と受信を独立して実施できるので,タイミングが異なる場合も容易にプログラミング可能です.