Mbed Connect Cloudの再利用 (各種センサー、WiFi 評価ボード かな?)
ODIN-W2(技適付きWiFiモジュール)の載ったこのIoTボードを昔、入手してました。それをPlatformIOで動作させてみました。いやーいろいろなセンサーが載ってました。
ボード自体は、2018年の下記のイベントでいただきました。楽しかったなぁ~。
この時のイベントの様子は下記で詳しく語っていただいてます。
今回は下記のコンテンツを活用させていただいています。
内容は、【1】LCDに表示、 【2】LED点滅、 【3】温湿度センサーの測定値をLCDに表示、【4】 空気センサーの測定値をLCDに表示、 【5】光度センサーの測定値をLCDに表示、 【6】加速度センサーの測定値をLCDに表示、 【7】距離センサーの測定値をLCDに表示
1. Mbed Connect Cloudとは?
Mbed Connect Cloudとは、センサなどの載ったプログラム可能WiFIボードです。載っているデバイスは下記です。
・ODIN-W2:WiFiモジュール(技適付き)
・LPC11U35:DAP Link = デバッガーインターフェース。
・C12832:LCDディスプレイ
・SHT31:温湿度センサー
・CSS811:空気センサー
・TSL2561:光度センサー
・MMA7660:加速度センサー
・vl53l0x:距離センサー
設計資料は下記で公開されています。
2.開発環境の準備
基本的な環境構築は下記と同様です。
Boardは [u-blox ODIN-W2] を選択して初期環境を立ち上げます。
platformio.iniを下記のように書き換えます。mbed_connect_odin が用意されているので楽でした。デバッガーも,cmsis-dapが接続できました。
[env:mbed_connect_odin]
platform = ststm32
board = mbed_connect_odin
framework = mbed
debug_tool = cmsis-dap
upload_protocol = cmsis-dap
build_flags = -D PIO_FRAMEWORK_MBED_RTOS_PRESENT
3. ライブラリーの入手先
zipで添付するので、そちらを使うほうが最初は楽かもしれません。
C12832のライブラリは、下記から入手します。
SHT31のライブラリを下記から入手します。
CSS811のライブラリを下記から入手します。
TSL2561のライブラリを下記から入手します。
MMA7660のライブラリを下記から入手します。
4. C21832ライブラリの修正
ライブラリが古いmbedのバージョン対応なので、最新の環境に適応させると、エラーが発生します。下記の修正が必要です。
C21832.cpp の修正(misoの設定のNCのままにするとエラーが出る。)
修正箇所[修正前]
C12832::C12832(PinName mosi, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name)
: _spi(mosi,NC,sck),_reset(reset),_A0(a0),_CS(ncs),GraphicsDisplay(name)
修正箇所[修正後]
C12832::C12832(PinName mosi, PinName miso, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name)
: _spi(mosi,miso,sck),_reset(reset),_A0(a0),_CS(ncs),GraphicsDisplay(name)
C21832.h の修正
修正箇所[修正前]
C12832(PinName mosi, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name = "LCD");
修正箇所[修正後]
C12832(PinName mosi, PinName miso, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name = "LCD");
こんなエラー、実行に出るので、修正が必要でした。あせった。
++ MbedOS Error Info ++
Error Status: 0x80FF0144 Code: 324 Module: 255
Error Message: Assertion failed: pin != (PinName)NC
Location: 0x80020E9
File: C:\Users\hiroa\.platformio\packages\framework-mbed@6.51506.201227\targets\TARGET_STM\pinmap.c+62
Error Value: 0x0
Current Thread: main Id: 0x20005290 Entry: 0x8003047 StackSize: 0x1000 StackMem: 0x20006038 SP: 0x20006EE4
For more info, visit: https://mbed.com/s/error?error=0x80FF0144&tgt=MBED_CONNECT_ODIN
-- MbedOS Error Info --
5. 実際のコードと実行結果
5.0.ベースのコード
下記のベースのコードに、各機能のコードを追加していきます。
#include "mbed.h"
#include "C12832.h"
#include "CCS811.h"
#include "Sht31.h"
#include "TSL2561.h"
#include "MMA7660.h"
// GLOBAL VARIABLES HERE
// FUNCTION DEFINTIONS HERE
int main() {
// MAIN CODE HERE
}
5.1. LCD実行コード
ベースコードにC12832の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
// GLOBAL VARIABLES HERE
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 );
// FUNCTION DEFINTIONS HERE
void lcd_print(const char* message) {
lcd.cls();
lcd.locate(0, 3);
lcd.printf(message);
}
int main() {
// MAIN CODE HERE
lcd_print("Hello World!");
}
実行結果はLCDに [ Helllo World ] が表示されます。
5.2. LEDトグル実行コード
ベースコードにLEDトグル実行コードに必要なコードを下記のように追記して実行します。
#include "mbed.h"
// GLOBAL VARIABLES HERE
DigitalOut led(PB_8, 1);
InterruptIn button(PF_2);
// FUNCTION DEFINTIONS HERE
void toggle_led() {
led = !led;
}
int main() {
// MAIN CODE HERE
button.rise(&toggle_led);
}
SW2を押すごとにLEDが点滅します。
5.3. 温湿度センサーの測定値をLCDに表示
ベースコードC12832の表示のコードに、温湿度センサー(SHT31)の測定値の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
#include "Sht31.h"
// GLOBAL VARIABLES HERE
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 );
Sht31 temp_sensor(PF_0, PF_1);
// FUNCTION DEFINTIONS HERE
void lcd_print(const char* message) {
lcd.cls();
lcd.locate(0, 3);
lcd.printf(message);
}
void read_temp() {
float t = temp_sensor.readTemperature();
float h = temp_sensor.readHumidity();
char val[32];
sprintf(val, "TEMP: %3.2fC, HUM: %3.2f%%", t, h);
lcd_print(val);
}
int main() {
// MAIN CODE HERE
while(1) {
read_temp();
thread_sleep_for(2000);
}
}
実行結果はLCDに [ TEMP: 30.41C, HUM: 55.57 ] のように表示されます。
5.4. 空気センサーの測定値をLCDに表示
ベースコードC12832の表示のコードに、空気センサー(CCS811)の測定値の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
#include "CCS811.h"
// GLOBAL VARIABLES HERE
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 );
CCS811 air_sensor(PF_0, PF_1);
// FUNCTION DEFINTIONS HERE
void lcd_print(const char* message) {
lcd.cls();
lcd.locate(0, 3);
lcd.printf(message);
}
void read_air() {
air_sensor.init();
uint16_t eco2, tvoc;
air_sensor.readData(&eco2, &tvoc);
char val[32];
sprintf(val, "eCO2: %dppm, TVOC: %dppb", eco2, tvoc);
lcd_print(val);
}
int main() {
// MAIN CODE HERE
while(1) {
read_air();
thread_sleep_for(2000);
}
}
実行結果はLCDに [ eCOS: 574ppm, TVOC: 26ppb ] のように表示されます。
5.5. 光度センサーの測定値をLCDに表示
ベースコードC12832の表示のコードに、光度センサー(TSL2561)の測定値の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
#include "TSL2561.h"
// GLOBAL VARIABLES HERE
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 );
TSL2561 light_sensor(PF_0, PF_1, TSL2561_ADDR_HIGH);
// FUNCTION DEFINTIONS HERE
void lcd_print(const char* message) {
lcd.cls();
lcd.locate(0, 3);
lcd.printf(message);
}
void read_light() {
int vis = light_sensor.getLuminosity(TSL2561_VISIBLE);
int infr = light_sensor.getLuminosity(TSL2561_INFRARED);
char val[32];
sprintf(val, "VIS: %d, INFR: %d ", vis, infr);
lcd_print(val);
}
int main() {
// MAIN CODE HERE
light_sensor.begin();
light_sensor.setGain(TSL2561_GAIN_0X);
light_sensor.setTiming(TSL2561_INTEGRATIONTIME_402MS);
while(1) {
// WHILE LOOP CODE HERE
read_light();
thread_sleep_for(2000);
}
}
実行結果はLCDに [ VIS: 170, INFR: 30 ] のように表示されます。
5.6. 加速度センサーの測定値をLCDに表示
ベースコードC12832の表示のコードに、加速度センサー(MMA7660)の測定値の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
#include "MMA7660.h"
// GLOBAL VARIABLES HERE
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 );
MMA7660 accel(PF_0, PF_1);
// FUNCTION DEFINTIONS HERE
void lcd_print(const char* message) {
lcd.cls();
lcd.locate(0, 3);
lcd.printf(message);
}
void read_accel() {
float x = accel.x();
float y = accel.y();
float z = accel.z();
char val[32];
sprintf(val, "x=%.2f y=%.2f z=%.2f", x, y, z);
lcd_print(val);
}
int main() {
printf("Mbed OS version %d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
while(1) {
// MAIN CODE HERE
read_accel();
thread_sleep_for(2000);
}
}
実行結果はLCDに [ x=-0.23 y=-0.09 z=0.98 ] のように表示されます。
5.7. 距離センサーの測定値をLCDに表示
ベースコードC12832の表示のコードに、距離センサー(vl53l0x)の測定値の表示に必要なコードを下記のように追記して実行します。
#include "mbed.h"
#include "C12832.h"
#include "vl53l0x_api.h"
#include "vl53l0x_platform.h"
#include "vl53l0x_i2c_platform.h"
#define USE_I2C_2V8
// GLOBAL VARIABLES HERE
/* Sets up LCD and prints sensor data value of Indoor Air Quality sensor to LCD */
C12832 lcd( PE_14 , PE_13 , PE_12 , PD_12 , PD_11 , PE_9 ); //LCD: MISO, MOSI, SCK, RESET, A0, nCS
// FUNCTION DEFINTIONS HERE
VL53L0X_Error WaitMeasurementDataReady(VL53L0X_DEV Dev) {
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
uint8_t NewDatReady=0;
uint32_t LoopNb;
if (Status == VL53L0X_ERROR_NONE) {
LoopNb = 0;
do {
Status = VL53L0X_GetMeasurementDataReady(Dev, &NewDatReady);
if ((NewDatReady == 0x01) || Status != VL53L0X_ERROR_NONE) {
break;
}
LoopNb = LoopNb + 1;
VL53L0X_PollingDelay(Dev);
} while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP);
if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) {
Status = VL53L0X_ERROR_TIME_OUT;
}
}
return Status;
}
VL53L0X_Error WaitStopCompleted(VL53L0X_DEV Dev) {
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
uint32_t StopCompleted=0;
uint32_t LoopNb;
if (Status == VL53L0X_ERROR_NONE) {
LoopNb = 0;
do {
Status = VL53L0X_GetStopCompletedStatus(Dev, &StopCompleted);
if ((StopCompleted == 0x00) || Status != VL53L0X_ERROR_NONE) {
break;
}
LoopNb = LoopNb + 1;
VL53L0X_PollingDelay(Dev);
} while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP);
if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) {
Status = VL53L0X_ERROR_TIME_OUT;
}
}
return Status;
}
int main()
{
lcd.cls();
printf("Mbed OS version %d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
//Setup laser
int var=1, measure=0;
int ave=0, sum=0;
VL53L0X_Dev_t MyDevice;
VL53L0X_Dev_t *pMyDevice = &MyDevice;
VL53L0X_RangingMeasurementData_t RangingMeasurementData;
VL53L0X_RangingMeasurementData_t *pRangingMeasurementData = &RangingMeasurementData;
// Initialize Comms laster
pMyDevice->I2cDevAddr = 0x52;
pMyDevice->comms_type = 1;
pMyDevice->comms_speed_khz = 400;
VL53L0X_RdWord(&MyDevice, VL53L0X_REG_OSC_CALIBRATE_VAL,0);
VL53L0X_DataInit(&MyDevice);
uint32_t refSpadCount;
uint8_t isApertureSpads;
uint8_t VhvSettings;
uint8_t PhaseCal;
VL53L0X_StaticInit(pMyDevice);
VL53L0X_PerformRefSpadManagement(pMyDevice, &refSpadCount, &isApertureSpads); // Device Initialization
VL53L0X_PerformRefCalibration(pMyDevice, &VhvSettings, &PhaseCal); // Device Initialization
VL53L0X_SetDeviceMode(pMyDevice, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING); // Setup in single ranging mode
VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, (FixPoint1616_t)(0.25*65536)); //High Accuracy mode, see API PDF
VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, (FixPoint1616_t)(18*65536)); //High Accuracy mode, see API PDF
VL53L0X_SetMeasurementTimingBudgetMicroSeconds(pMyDevice, 200000); //High Accuracy mode, see API PDF
VL53L0X_StartMeasurement(pMyDevice);
// MAIN CODE HERE
while(1) {
lcd.cls();
lcd.locate(0,3);
lcd.printf("(DISTANCE)");
while(var<=10){
WaitMeasurementDataReady(pMyDevice);
VL53L0X_GetRangingMeasurementData(pMyDevice, pRangingMeasurementData);
measure=pRangingMeasurementData->RangeMilliMeter;
sum=sum+measure;
VL53L0X_ClearInterruptMask(pMyDevice, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY);
VL53L0X_PollingDelay(pMyDevice);
var++;
}
ave=sum/var;
var=1;
sum=0;
lcd.locate(0,15);
lcd.printf("%dmm", ave); // Print to LCD values
wait(1);
}
}
実行結果はLCDに [ (DISTANCE) 160mm ] のように表示されます。
6. ダウンロード
src と lib を下記に用意しましたが、解凍して適宜コピーしてください。
こんな感じに配置します。