はじめに
本コンテンツは、Wio LTE M1/NB1(BG96) (以下Wio LTE)を用いた、
新潟 IoTハッカソン2020で使用する技術ハンズオンの資料です。
参考として御活用下さい。
WioLTEでやること
センサから取得した温度値をWio LTE経由でenebularへ転送します。
※enebularの環境作成やMotionBoardでの可視化は以降のハンズオンでのご案内となります。
#LPWAの特徴とCat.M1の位置づけ
✅ 数kbps~数100kbps程の低速通信
✅ (そのかわり)デバイスの電池が数年から数十年の運用ができる省電力性
✅ 数kmから数10kmの通信が出来る広域性
✅Cat.M1の最大の特徴がモビリティ(デバイスの移動)に対応している事
✅LTEと同様に基地局に接続して通信、LTEと同等のエリアをカバー(NB-IoTも同様)
✅NB-IoTよりも通信速度が速いためプロトタイプの幅が広がる(ハッカソン向き)
※電池の持ちを最優先にする場合はNB-IoTの方が優れます。
✅WiFiやBLE、EnOceanは中継するGW装置が必要になるのが一般的だが、Cat.M1ではデバイスから直接データ送信が出来る
※ビジネスモデル検討時の参考として活用下さい
※※本リストについてはハッカソンで検討しやすいように参考として書き起こしたものと御理解下さい。記載の金額についてお約束するものではありません。
✅LTEに比べLPWAは低速となりますが要件が合えば運用にかかわるコストを抑えることができます。
✅Cat.M1とNB-IoTの料金は同一となります。モビリティが無く通信頻度も少ない場合はNB-IoTの方がビジネスモデルに適する場合があります。
※※今回WioLTEではCat.M1への接続方式のみの提供としております、NB-IoTが適するビジネスモデルの場合はプレゼンテーション内で表現頂くようお願い致します。設定変更でNB-IoTへの接続は出来ません。
#前提確認
本ハンズオンは事前準備が完了していないと、プログラムを動作させる事が出来ません。
以下3点、完了している事を御確認下さい。
✅【1】ボードの選択
✅【2】書き込み方式の選択
✅【3】ライブラリのインストール
※事前準備を完了されていない方はこちらご対応下さい
<Windows>
http://bit.ly/38zbToN
<macOS>
http://bit.ly/2HvzjiQ
####【1】ボードの選択
<Windows>
メニューバーの[ツール]➡**ボード:"Seeed Wio LTE M1/NB1(BG96)"**が選択されていること
<macOS>
メニューバーの[ツール]➡**ボード:"Seeed Wio LTE M1/NB1(BG96)"**が選択されていること
####【2】書き込み方式の選択
<Windows>
メニューバーの[ツール]➡マイコンボードに書き込む:**"OpenOCD"**が選択されていること
<macOS>
メニューバーの[ツール]➡マイコンボードに書き込む:**"OpenOCD"**が選択されていること
####【3】ライブラリのインストール
<Windows>
メニューバーの[スケッチ]➡[ライブラリをインクルード]➡[ライブラリを管理]を押下
ライブラリマネージャのウインドウが開く ➡ 検索バーに**"WioCellLibforArduino"を入力
➡ Wio cell lib for Arduino by Seeed k.k バージョン1.7.0 が "INSTALLED" **であること
検索バーに**"rBase64"を入力
➡rBase64 バージョン1.1.1が "INSTALLED" **であること
<macOS>
メニューバーの[スケッチ]➡[ライブラリをインクルード]➡[ライブラリを管理]を押下
ライブラリマネージャのウインドウが開く ➡ 検索バーに**"WioCellLibforArduino"を入力
➡ Wio cell lib for Arduino by Seeed k.k バージョン1.7.0 が "INSTALLED" **であること
検索バーに**"rBase64"を入力
➡rBase64 バージョン1.1.1が "INSTALLED" **であること
上記の3点が確認出来ればWio LTEを動かすための前提条件は整っています。
#Wio LTE について
WioLTEはSeeed社が開発しているマイコンモジュールになります。
Groveコネクタ,STM32F4マイコン,SB認証済通信モジュールを搭載、ArduinoIDEを用いて素早くプロトタイプの作成が出来ます。
【Interface】
デジタル入力:2ポート D38 D20
アナログ入力:2ポート A6 A4
シリアル通信:I2Cポート
信号変換:UARTポート
【価格】
SoftBank Editionの試作機のため非売品ですが、
本ハッカソンでは¥8,000~10,000程度になると考えて下さい。
同時に生産する数量が増えればボリュームディスカウントで価格は下がる可能性はあります。
#注意点
アンテナは最初から接続された状態です。
接続部分のコネクタ(赤枠)は外さないで下さい。
工作などで外す場合はアンテナの下部(赤枠)を回せば外れます、こちらで外して下さい。
※WioLTE並びにセンサ類につきましては、ハッカソン終了後にはご返却をお願い致します。
#センサの取り付け
温湿度センサをD38ポートに接続します。
#PCとの接続
IDEを一度閉じて下さい。
USBケーブルとPCを接続して下さい。
#シリアルポートの接続確認
PCとWioLTEが接続された状態でUSBシリアルポートの設定をします。
<Windows>
Aruduino IDEを起動し[ツール]➡[シリアルポート]➡[COM数字]を選択する。
<macOS>
Aruduino IDEを起動し[ツール]➡[シリアルポート]➡[/dev/cu.usbmodem 数字]を選択する。
#サンプルスケッチ(プログラム)の準備
IDEに以下のコードを転記して下さい
/****************************************************
00 Sample code For Nigata IoT Hack 2020
BG96,humi
to enebular HTTP POST
Mode M1 2019.2.13 by SoftBank
Update---------------->2019.2.13 by SoftBank
*****************************************************/
/***** include *****/
#include <WioCellLibforArduino.h>
#include <stdio.h>
#include <rBase64.h>
/***** define *****/
#define ARDUINO_WIO_LTE_M1NB1_BG96
#define BAUDRATE 115200
#define CONSOLE SerialUSB
#define BG96 SerialModule
#define INTERVAL (30000) /*** Push interval(mSec) ***/
/***** enebular info *****/
#define ENEBULAR_NODE_PATH "https://ev2-prod-node-red-9efa8d82-c82.herokuapp.com" // URL末尾に"/"をつけない
//NODE_PATHは後からご自身のURLに書き換えとなります。
//
#define ENABULAR_POST_URL "/debug"
#define ENEBULAR_ENDPOINT ENEBULAR_NODE_PATH""ENABULAR_POST_URL
/***** LTEプロバイダ 制御コマンド *****/
#define SET_QCFG "at+qcfg=\"nwscanseq\",020103"
#define SET_QCFG2 "at+qcfg=\"iotopmode\",0"
#define GET_QNWINFO "at+qnwinfo"
/****** Sensor PIN *****/
#define SENSOR_PIN (WIO_D38)
#define SENSOR_PIN2 (WIO_D20)
#define SENSOR_PIN2_1 (WIO_D19) // D20と同一ポート LED Button 使用時など
#define SENSOR_PIN3 (WIO_I2C_D24) // I2C use D-PORT24
#define SENSOR_PIN4 (WIO_A6) //Analog Port
#define SENSOR_PIN5 (WIO_A4) //Analog Port
/*** Wio LTE 制御クラス ****/
WioCellular Wio;
/***** NW接続用関数 *****/
void getKey(char a_key[8],char u_key[4],char p_key[4]){
char org_char[] = "TjEyR3Q1ZGVyY0phcy5tem5PZmdwMjQ=";
rbase64.decode(org_char);
int slen1 = strlen(rbase64.result());
char str1[slen1];
strcpy(str1, rbase64.result());
char org_int[] = "MTQsNCw5LDEzLDE5LDcsMTY=";
rbase64.decode(org_int);
int slen2 = strlen(rbase64.result());
char str2[slen2];
strcpy(str2, rbase64.result());
char *sint;
for (int i=0;i<8;i++){
if (i==0){
sint = strtok(str2,",");
a_key[i] = str1[atoi(sint)];
} else {
sint = strtok(NULL,",");
a_key[i] = str1[atoi(sint)];
if (i==2){
strcpy(u_key,a_key);
strcpy(p_key,a_key);
u_key[i+1] = '\0';
p_key[i+1] = '\0';
} else if (i==7){
a_key[i] = '\0';
}
}
}
}
/************************* Set Up ****************************************/
void setup() {
delay(1000);
CONSOLE.begin(BAUDRATE);
CONSOLE.println("");
CONSOLE.println("");
CONSOLE.println("############ SETUP ############");
CONSOLE.println("");
/***** Wio LTE 全体を初期化 *****/
Wio.Init();
CONSOLE.println("### Start Wio LTE initialization ###");
/***** LTE通信モジュールの電源供給を開始 *****/
Wio.PowerSupplyCellular(true);
CONSOLE.println("### Power supply ON ###");
delay(500); // モジュール安定までWAIT
/***** LTE通信モジュールを起動(起動済みの場合はリセット) *****/
if (!Wio.TurnOnOrReset()) {
CONSOLE.println("### Turn on or reset ERROR! ###");
return;
}else{
CONSOLE.println("### Turn on or reset Succeeded ###");
}
delay(500); // モジュール安定までWAIT
/***** Mobile Network接続(SB) *****/
Wio.SetSelectNetwork(WioCellular::SELECT_NETWORK_MODE_MANUAL, "44020");
CONSOLE.println("### SELECT_NETWORK_MODE_MANUAL 44020 ###");
/***** プロバイダ(SB) APN set *****/
char a_key[8]={};
char u_key[4]={};
char p_key[4]={};
getKey(a_key,u_key,p_key);
if (!Wio.Activate(a_key, u_key, p_key)) {
CONSOLE.println("### NW Connect ERROR! ###");
return;
}else{
CONSOLE.println("### Connecting to NW. Succeeded ###");
}
/***** LTE M1を明示的に指定 *****/
Wio.SetAccessTechnology(WioCellular::ACCESS_TECHNOLOGY_LTE_M1);
CONSOLE.println("### ACCESS_TECHNOLOGY_CAT-M1 ###");
BG96.println(SET_QCFG);
CONSOLE.println(SET_QCFG);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
BG96.println(SET_QCFG2);
CONSOLE.println(SET_QCFG2);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
BG96.println(GET_QNWINFO);
CONSOLE.println(GET_QNWINFO);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
/***** D38以外のGroveポートにも給電開始 *****/
Wio.PowerSupplyGrove(true);
CONSOLE.println("### ALL GROVE PORT POWER SUPPLY ON ###");
/***** setup Sensor PIN *****/
/*温度センサー(青色)を接続しています*/
TemperatureAndHumidityBegin(SENSOR_PIN);
CONSOLE.println("### SETUP TEMPERATURE ###");
CONSOLE.print("Setup Temperature -> ");
CONSOLE.print(SENSOR_PIN);
CONSOLE.println("");
CONSOLE.println("");
/***** Wio LTE セットアップ完了 *****/
CONSOLE.println("");
CONSOLE.println("##### Wio LTE initialize completed. #####");
CONSOLE.println("");
CONSOLE.println("");
CONSOLE.println("");
CONSOLE.println("############ SETUP FIN ############");
CONSOLE.println("");
CONSOLE.println("");
CONSOLE.println("");
CONSOLE.println("############ GOTO LOOP ############");
}
/******************************* Loop ***********************************/
void loop() {
/***** 変数定義 ループ毎に変数を初期化 *****/
float temp;
float humi;
/***** シリアルモニタに温度湿度出力 *****/
if (!TemperatureAndHumidityRead(&temp, &humi)) {
CONSOLE.println("ERROR!");
goto err;
}
CONSOLE.print("Current humidity = ");
CONSOLE.print(humi);
CONSOLE.print("% ");
CONSOLE.print("temperature = ");
CONSOLE.print(temp);
CONSOLE.println("C");
err:
delay(2000);
/***** 変数定義 ループ毎に変数を初期化 *****/
char imei[20];
char imsi[20];
char iccid[20];
int rss;
/***** IMEI値を取得 *****
IMEI:International Mobile Equipment Identity (国際移動体装置識別番号)
IMEIはモジュールの表面に印字されています
IMEI以外も取得可能,コンソール出力が不要であればコメントアウト(//)
*/
Wio.GetIMEI(imei, sizeof(imei));
CONSOLE.print("IMEI:");
CONSOLE.println(imei);
//Wio.GetIMSI(imsi, sizeof(imsi));
//CONSOLE.print("IMSI:");
//CONSOLE.println(imsi);
//Wio.GetICCID(iccid, sizeof(iccid));
//CONSOLE.print("ICCID:");
//CONSOLE.println(iccid);
//rss = Wio.GetReceivedSignalStrength();
//CONSOLE.print("Get RSSI:");
//CONSOLE.println(rss);
//CONSOLE.println("");
/***** 変数定義 ループ毎に変数を初期化 *****/
int status;
char body[200];
/***** WioLTEやセンサから取得した値をJSON形式に変換 *****/
sprintf(body,"{\"d\" : { \"ambientTemp\" : %g, \"humidity\": %g } }" ,temp,humi);
//sprintf(body,"{\"UPTIME\":%lu, \"IMEI\": %s, \"TEMP\":%g, \"RSSI\": %d}",millis()/1000, imei,temp,rss);
/* センサ数値をJSON形式フォーマットに従って文字列に変換 */
/***** データ送信先確認 コンソールへ出力 *****/
CONSOLE.println("### Post to \""ENEBULAR_ENDPOINT"\".###");
CONSOLE.print("--> ");
CONSOLE.print(body);
CONSOLE.println("");
/***** Header情報の付与 *****/
WioCellularHttpHeader header;
header["Content-Type"] = "application/json";
/* enebularにJSON形式のbodyを送信する場合は、Content-Typeヘッダを"application/json"にする必要あり
「いま自分が送ったデータはjson形式」を示す付加情報*/
/***** データ送信 POST *****/
if (Wio.HttpPost(ENEBULAR_ENDPOINT, body, &status, header)) {
/*POST成功の場合Responseコードが返ってくる(ようにEnebular側を準備する)*/
CONSOLE.print("<-- ");
CONSOLE.print("enebular ResponseCode:");
CONSOLE.println(status);
}
else {
/*POST失敗 サーバーからのレスポンスがタイムアウトした場合や、到達できなかったとき*/
CONSOLE.print("### Failed to Post. (");
CONSOLE.print(status);
CONSOLE.println(")###");
}
/***** 次回実行までのwait *****/
CONSOLE.print("### Wait for ");
CONSOLE.print(INTERVAL);
CONSOLE.println(" msecs.###");
CONSOLE.println("");
delay(INTERVAL);
/*INTERVALに定義した時間経過後Loop処理を再実行*/
}
/**********************************************************
以下、サンプルスケッチ参照
WioCellLibForArduino
-> Grove
-> grove-temperature-and-humidity-sensor からの引用
************************************************************/
int TemperatureAndHumidityPin;
void TemperatureAndHumidityBegin(int pin){
TemperatureAndHumidityPin = pin;
DHT11Init(TemperatureAndHumidityPin);
}
bool TemperatureAndHumidityRead(float* temperature, float* humidity){
byte data[5];
DHT11Start(TemperatureAndHumidityPin);
for (int i = 0; i < 5; i++) data[i] =
DHT11ReadByte(TemperatureAndHumidityPin);
DHT11Finish(TemperatureAndHumidityPin);
if(!DHT11Check(data, sizeof (data))) return false;
if (data[1] >= 10) return false;
if (data[3] >= 10) return false;
*humidity = (float)data[0] + (float)data[1] / 10.0f;
*temperature = (float)data[2] + (float)data[3] / 10.0f;
return true;
}
void DHT11Init(int pin){
digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
}
void DHT11Start(int pin){
// Host the start of signal
digitalWrite(pin, LOW);
delay(18);
// Pulled up to wait for
pinMode(pin, INPUT);
while (!digitalRead(pin)) ;
// Response signal
while (digitalRead(pin)) ;
// Pulled ready to output
while (!digitalRead(pin)) ;
}
byte DHT11ReadByte(int pin){
byte data = 0;
for (int i = 0; i < 8; i++) {
while (digitalRead(pin)) ;
while (!digitalRead(pin)) ;
unsigned long start = micros();
while (digitalRead(pin)) ;
unsigned long finish = micros();
if ((unsigned long)(finish - start) > 50) data |= 1 << (7 - i);
}
return data;
}
void DHT11Finish(int pin){
// Releases the bus
while (!digitalRead(pin)) ;
digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
}
bool DHT11Check(const byte* data, int dataSize){
if (dataSize != 5) return false;
byte sum = 0;
for (int i = 0; i < dataSize - 1; i++) {
sum += data[i];
}
return data[dataSize - 1] == sum;
}
#スケッチの書き込み(コンパイル)
<Windows>
転記が完了しましたらシリアルモニタを起動して下さい。
IDE右上の赤枠虫眼鏡🔎アイコンです。
シリアルモニタが見える状態にして書き込みボタンを押しWioLTEにスケッチを書き込んで下さい。
書き込みが完了すると同時にシリアルモニタに出力されます。
センサから取得されたデータがシリアルモニタに出力されている事を確認して下さい。
<macOS>
転記が完了しましたらシリアルモニタを起動して下さい。
IDE右上の赤枠虫眼鏡🔎アイコンです
シリアルモニタが見える状態にして書き込みボタンを押しWioLTEにスケッチを書き込んで下さい。
書き込みが完了すると同時にシリアルモニタに出力されます。
センサから取得されたデータがシリアルモニタに出力されている事を確認して下さい。
#スケッチ解説・補足
//あいうえ
/* あいうえ */
コメント
//で始まる行や/* ~ */の中の文はコメントとなります。
プログラムの動作としては、無視されます。
#include <WioCellLibforArduino.h>
#include <~>
C言語の標準ライブラリやArduino用ライブラリを利用するための構文です。
・WioCellLibforArduino.h"
・stdio.h
・rBase64.h
上記3つは必須となりますので変更せずそのまま転記して下さい。
#define SENSOR_PIN (WIO_D38)
#define CONSOLE SerialUSB
#define 定数名 値<~>
指定した値に対して、名前(定数名)をつけるための構文です。
#define ARDUINO_WIO_LTE_M1NB1_BG96
#define ボード名
使用するボードを宣言しています。
変更せずそのまま転記して下さい。
#define BAUDRATE 115200
#define BAUDRATE 値
ボーレートを定義します。1秒間にアナログ・デジタルの復調・変調を何回できるかを示す値のこと。
変更せずそのまま転記して下さい。
#define CONSOLE SerialUSB
#define 定数名 SerialUSB
コンソールの定義です。
変更せずそのまま転記して下さい。
#define BG96 SerialModule
#define <通信モジュール> SerialModule
通信モジュール制御用の定義です。
変更せずそのまま転記して下さい。
#define INTERVAL (30000) /*** Push interval(mSec) ***/
#define INTERVAL (ミリ秒)
データの送信間隔の定義です。単位はミリ秒、30000だと30秒間隔になります。
()内の数値を変更し使用して下さい。
#define ENEBULAR_NODE_PATH "https://ev2-prod-node-red-9efa8d82-c82.herokuapp.com" // URL末尾に"/"をつけない
#define ENEBULAR_NODE_PATH "ご自身のURLを記載"
※※ENEBULAR_NODE_PATHは後からご自身のURLに書き換えとなります。
※※10時からのenebularハンズオンを受講しURLを書き換えて下さい。
このハンズオンではそのまま張り付けて頂いて構いません、プロトタイプを作成される際にご自身の環境のURLに書き換えて下さい。
#define ENABULAR_POST_URL "/debug"
#define ENEBULAR_ENDPOINT ENEBULAR_NODE_PATH""ENABULAR_POST_URL
#define ENABULAR_POST_URL "/debug"
#define ENEBULAR_ENDPOINT ENEBULAR_NODE_PATH""ENABULAR_POST_URL
enebularにデータを送信する為の定義となります。
変更せずそのまま転記して下さい。
#define SET_QCFG "at+qcfg=\"nwscanseq\",020103"
#define SET_QCFG2 "at+qcfg=\"iotopmode\",0"
#define GET_QNWINFO "at+qnwinfo"
#define SET_command
SoftBankのネットワークに接続する為の定義となります。
変更せずそのまま転記して下さい。
#define SENSOR_PIN (WIO_D38)
#define SENSOR_PIN2 (WIO_D20)
#define SENSOR_PIN2_1 (WIO_D19) // D20と同一ポート LED Button 使用時など
#define SENSOR_PIN3 (WIO_I2C_D24) // I2C use D-PORT24
#define SENSOR_PIN4 (WIO_A6) //Analog Port
#define SENSOR_PIN5 (WIO_A4) //Analog Port
#define SENSOR_PINx (WIO_yyy)
センサー接続用のポートの定義になります。
※D38以外を使用する際は給電の記述が必要となります(後述:Wio.PowerSupplyGrove(true);)
定義するのは使用するセンサーのみでも構いません
WioCellular Wio;
クラス名 オブジェクト名
ここではWioLTEの制御をWioという名前(オブジェクト)を使って行うことを定義しています。
変更せずそのまま転記して下さい。
/***** NW接続用関数 *****/
void getKey(){}
NW接続用関数 getkey
SoftBankのネットワークに接続するための記述部分になります。
変更せずそのまま転記し使用して下さい。
void setup() {
setup(){~}
電源を入れたときやリセットした時に1度だけ実行されます。
WioLTE本体の初期化やセンサーを接続するPinの初期化を行っています。
{}内の構文行の最後は「;」を記載するルールとなっています。
delay(1000);
delay(~);
カッコ内の数字(ミリ秒)の間、何もせず待つための構文です。
電源投入直後などに挿入し安定を待ちます
CONSOLE.println("############ SETUP ############");
CONSOLE.println("");
CONSOLE.println(“~”);
CONSOLE.println("コンソールに表示する文字")
コンソール画面内にカッコ内の文字を表示するための構文です。
コンソール画面に処理の経過を表示することで、エラーになった場合等に対処しやすくなります。
Wio.Init();
Wio.Init()
WioLTEを初期化します。
変更せずそのまま転記して下さい。
Wio.PowerSupplyCellular(true);
Wio.PowerSupplyCellular()
通信モジュールに電源供給を行います。
変更せずそのまま転記して下さい。
if (!Wio.TurnOnOrReset()) {
Wio.TurnOnOrReset()
通信モジュールを起動します。
変更せずそのまま転記して下さい。
if (!Wio.TurnOnOrReset()) {
CONSOLE.println("### Turn on or reset ERROR! ###");
return;
}else{
CONSOLE.println("### Turn on or reset Succeeded ###");
if (~){~}
()内の状態が真ならば{}を実行します。
偽ならばelse{~}内を実行します。
※「!」は、真⇒偽、偽⇒真とする記号です。
通信モジュールの起動に異常が発生した場合を真として、
Turn on or reset ERROR!を出力しています。
通信モジュール起動部はこのまま転記して下さい
センサの動作を制御する場合などに書き換えて使用して下さい。
/***** Mobile Network接続(SB) *****/
Wio.SetSelectNetwork(WioCellular::SELECT_NETWORK_MODE_MANUAL, "44020");
CONSOLE.println("### SELECT_NETWORK_MODE_MANUAL 44020 ###");
/***** プロバイダ(SB) APN set *****/
char a_key[8]={};
char u_key[4]={};
char p_key[4]={};
getKey(a_key,u_key,p_key);
if (!Wio.Activate(a_key, u_key, p_key)) {
CONSOLE.println("### NW Connect ERROR! ###");
return;
}else{
CONSOLE.println("### Connecting to NW. Succeeded ###");
}
/***** LTE M1を明示的に指定 *****/
Wio.SetAccessTechnology(WioCellular::ACCESS_TECHNOLOGY_LTE_M1);
CONSOLE.println("### ACCESS_TECHNOLOGY_CAT-M1 ###");
BG96.println(SET_QCFG);
CONSOLE.println(SET_QCFG);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
BG96.println(SET_QCFG2);
CONSOLE.println(SET_QCFG2);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
BG96.println(GET_QNWINFO);
CONSOLE.println(GET_QNWINFO);
delay(300);
while(BG96.available()>0){
CONSOLE.write(BG96.read());
}
delay(1000);
Mobile Network接続(SB)
SoftBankのネットワークに接続する処理を行っています。
変更せずそのまま転記して下さい。
Wio.PowerSupplyGrove(true);
Wio.PowerSupplyGrove()
D38以外のポートにも給電を開始します。
※D38以外のポートにセンサを接続する場合必須となります。
※プロトタイプの方針変更で接続するセンサを増やす可能性もあるかと思いますので、その時に忘れてハマらないように最初から転記して使用頂くのを推奨します。
TemperatureAndHumidityBegin(SENSOR_PIN);
CONSOLE.println("### SETUP TEMPERATURE ###");
CONSOLE.print("Setup Temperature -> ");
CONSOLE.print(SENSOR_PIN);
TemperatureAndHumidityBegin(SENSOR_PIN);
温湿度センサーの接続ピンをD38で初期化しています。
Set up時のセンサの値をコンソールに出力します。
void loop() {
loop(){~}
繰り返し実行する処理を記述する場所です。
センサーの値を取得しコンソール画面に表示する等のプログラムを書きます。
float temp;
float humi;
float ~
温度データと湿度データを格納する変数を準備します
if (!TemperatureAndHumidityRead(&temp, &humi)) {
TemperatureAndHumidityRead(&temp, &humi)
温湿度センサから温度と湿度のデータを取得
if (!TemperatureAndHumidityRead(&temp, &humi)) {
CONSOLE.println("ERROR!");
goto err;
}
CONSOLE.print("temperature = ");
CONSOLE.print(temp);
CONSOLE.println("℃ ");
CONSOLE.print("Current humidity = ");
CONSOLE.print(humi);
CONSOLE.println("% ");
CONSOLE.println("");
err:
if (!~){~}
「!」は、真⇒偽、偽⇒真とする記号です。
左記では、温湿度データが正常に読み取れなかった「偽」を「真」に置き換えて、コンソールにERROR!を表示します。
温湿度データが正常に読み取れた場合は、温度、湿度をコンソールに表示します。
goto err;
「err:」の記載位置まで処理をジャンプする構文です
char imei[20];
char imsi[20];
char iccid[20];
int rss;
char imei[20];
IMEIを格納する変数を定義します。
IMEIはモジュールの表面に印字されています。
Wio.GetIMEI(imei, sizeof(imei));
CONSOLE.print("IMEI:");
CONSOLE.println(imei);
Wio.GetIMEI(変数名, sizeof(変数名))
WioLTEからIMEI情報を取得します。
int status;
char body[200];
enebularへデータを送信する用の変数を定義します。
sprintf(body,"{\"d\" : { \"ambientTemp\" : %g, \"humidity\": %g } }" ,temp,humi);
sprintf(body,"{"d" : { "ambientTemp" : %g, "humidity": %g } }" ,temp,humi)
センサから取得した数値をJSON形式のフォーマットに従って文字列に変換します。
enebularにデータを送信する際は上記の書式を使用して下さい。
CONSOLE.println("### Post to \""ENEBULAR_ENDPOINT"\".###");
CONSOLE.print("--> ");
CONSOLE.print(body);
CONSOLE.println("");
データの送信先となるURL(enebular)をコンソールに出力しています。
WioCellularHttpHeader header;
header["Content-Type"] = "application/json";
WioCellularHttpHeader header;
header["Content-Type"] = "application/json";
Header情報を付与しています。
enebularにJSON形式のbodyを送信する場合は、Content-Typeヘッダを"application/json"にする必要があります。
そのまま転記して下さい。
if (Wio.HttpPost(ENEBULAR_ENDPOINT, body, &status, header)) {
/*POST成功の場合Responseコードが返ってくる(ようにEnebular側を準備する)*/
CONSOLE.print("<-- ");
CONSOLE.print("enebular ResponseCode:");
CONSOLE.println(status);
}
else {
/*POST失敗 サーバーからのレスポンスがタイムアウトした場合や、到達できなかったとき*/
CONSOLE.print("### Failed to Post. (");
CONSOLE.print(status);
CONSOLE.println(")###");
}
Wio.HttpPost()
enebularに対してデータを送ります。
データ送信が成功した場合はレスポンスコードが返ります。
※10時からのenebularハンズオンでレスポンスコードが返るように環境を作成頂きます。
※このハンズオン時点では成功時のレスポンスコードは返りませんのでenebular環境作成後にもう一度試してみて下さい。
CONSOLE.print("### Wait for ");
CONSOLE.print(INTERVAL);
CONSOLE.println(" msecs.###");
CONSOLE.println("");
delay(INTERVAL);
delay(INTERVAL)
次のループ処理に入るまでの間隔を設定しています。
このサンプルでは30秒(30000ミリ秒)としていますが、プロトタイプの要件に合わせて変更して下さい。
※INTERVALを0にしてしまうとWioLTEの負荷が高くなるため0は設定しないようお願い致します。
/**********************************************************
以下、サンプルスケッチ参照
WioCellLibForArduino
-> Grove
-> grove-temperature-and-humidity-sensor からの引用
************************************************************/
int TemperatureAndHumidityPin;
void TemperatureAndHumidityBegin(int pin){
TemperatureAndHumidityPin = pin;
DHT11Init(TemperatureAndHumidityPin);
}
bool TemperatureAndHumidityRead(float* temperature, float* humidity){
byte data[5];
DHT11Start(TemperatureAndHumidityPin);
for (int i = 0; i < 5; i++) data[i] =
DHT11ReadByte(TemperatureAndHumidityPin);
DHT11Finish(TemperatureAndHumidityPin);
if(!DHT11Check(data, sizeof (data))) return false;
if (data[1] >= 10) return false;
if (data[3] >= 10) return false;
*humidity = (float)data[0] + (float)data[1] / 10.0f;
*temperature = (float)data[2] + (float)data[3] / 10.0f;
return true;
}
void DHT11Init(int pin){
digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
}
void DHT11Start(int pin){
// Host the start of signal
digitalWrite(pin, LOW);
delay(18);
// Pulled up to wait for
pinMode(pin, INPUT);
while (!digitalRead(pin)) ;
// Response signal
while (digitalRead(pin)) ;
// Pulled ready to output
while (!digitalRead(pin)) ;
}
byte DHT11ReadByte(int pin){
byte data = 0;
for (int i = 0; i < 8; i++) {
while (digitalRead(pin)) ;
while (!digitalRead(pin)) ;
unsigned long start = micros();
while (digitalRead(pin)) ;
unsigned long finish = micros();
if ((unsigned long)(finish - start) > 50) data |= 1 << (7 - i);
}
return data;
}
void DHT11Finish(int pin){
// Releases the bus
while (!digitalRead(pin)) ;
digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
}
bool DHT11Check(const byte* data, int dataSize){
if (dataSize != 5) return false;
byte sum = 0;
for (int i = 0; i < dataSize - 1; i++) {
sum += data[i];
}
return data[dataSize - 1] == sum;
}
上記はライブラリに含まれる温湿度センサを動作させるためのスケッチとなります。
温湿度センサ以外にもスケッチがありますので参照してみて下さい。
###【スケッチサンプル】
[ファイル]➡[スケッチ例]➡[Wio cell lib for Arduino]➡[grove]➡参照したいセンサ
スケッチ例にない場合は運営側で検証したスケッチも掲載しますので参考にして下さい。
【ウフル貸出:1-45】https://qiita.com/uhuru-hackathon/items/8559e94843203f04e086
【SB貸出:46-62】https://qiita.com/ichikawak_sb/private/ac12dca68f237795d491