LoginSignup
2
1

More than 5 years have passed since last update.

Arduino M0 Pro でマルチタスクプログラミング : NCES IoT Base Shield : Milkcocoa

Last updated at Posted at 2016-05-03

はじめに

この記事では,TOPPERS/R2CAにより,NCES IoT Base Shield に接続したセンサ(Ultrasonic Ranger)の値をMilkcocoaにsendしたり,Milkcocoa経由で受け取ったデータによりサーボを駆動する方法について説明します.

NCES IoT Base Shiledについては以下の記事を参照して下さい.

必要なハードウェア

サーバー側の設定

Arduino M0 Pro でマルチタスクプログラミング : Milkcocoaへの接続を参考にサーバー側の設定をして下さい.

ハードウェアセットアップ

M0にNCES IoT Base Shield を取り付けて,さらにGrove ServoをD2に,とGrove - Ultrasonic RangerをD3に接続します.

aFullSizeRender.jpg.jpg

ソフトウェアセットアップ

プログラムは以下にあります.

  • 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の範囲ならサーボを指定された角度で駆動します.

examples\Milkcocoa_NCESIoT\r2ca_app.h
#define R2CA_NUM_TASK 1

examples\Milkcocoa_NCESIoT\r2ca_app.cpp
#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への送信と受信を独立して実施できるので,タイミングが異なる場合も容易にプログラミング可能です.

2
1
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
2
1