レンタルサーバーと連携したsakura.ioの運用例
Dependencies: mbed SakuraIO MPU9250_SPI BME280 gps AQM0802A
main.cpp
- Committer:
- punix
- Date:
- 2018-11-27
- Revision:
- 2:48e7e85cb169
- Parent:
- 1:11957db1faa5
File content as of revision 2:48e7e85cb169:
#include <mbed.h> #include <AQM0802A.h> #include <BME280.h> #include <MPU9250.h> #include <SakuraIO.h> #include "SakuraPinNames.h" #include "sensors.h" #include "gps.h" //LED制御メッセージのタイプ種別の定数 #define MESG_NORMAL 0 #define MESG_INIT 1 // Serial over CMSIS_DAP Serial pc(DAP_UART_TX, DAP_UART_RX, 9600); // GPS Serial gps(GPS_TX, GPS_RX, 9600); DigitalOut gps_en(GPS_EN); // LED DigitalOut led_1(LED1); DigitalOut led_2(LED2); DigitalOut led_3(LED3); DigitalOut led_4(LED4); // LCD backlight DigitalOut lcd_led(LED_LCD); // Switch DigitalIn sw_1(SW1); DigitalIn sw_2(SW2); DigitalIn sw_3(SW3); DigitalIn sw_4(SW4); DigitalIn sw_5(SW5); DigitalIn sw_6(SW6); // Internal I2C I2C internal_i2c(I2C_INTERNAL_SDA, I2C_INTERNAL_SCL); AQM0802A lcd(internal_i2c); BME280 bme280(internal_i2c); // SPI SPI internal_mpu9250_spi(SPI_MPU_MOSI, SPI_MPU_MISO, SPI_MPU_SCK); mpu9250_spi mpu9250(internal_mpu9250_spi, SPI_MPU_CS); // sakura.io //SakuraIO_I2C sakuraio(I2C_SDA, I2C_SCL); #define SPI_FREQ (350000) SPI sakuraio_spi(PB_15, PB_14, PB_13); DigitalOut sakuraio_cs(PB_12); SakuraIO_SPI sakuraio(sakuraio_spi, sakuraio_cs); SensorData sensor_data; // GPS UART buffer char uart_buffer[128] = {0}; int uart_buffer_index = 0; //LED応対s申告の為のLTE接続した直後を検出するためのフラグ // 0:切断、1:接続直後でLED情報送信中、2:LED状態到達確認済み int connected_now = 0; // NMEA Decoder GPSDecoder gps_decoder; void gps_uart_buffering_handler(); const int SEND_INTERVAL_TICKS_PAR_COUNT = 1500; const int RETRY_INTERVAL_TICKS_PAR_COUNT = 50; void setup() { lcd_led = 1; pc.printf("Hello World !\r\n"); lcd.cls(); lcd.printf("Hello"); connected_now = 0; // Initialize sensors bme280.initialize(); pc.printf("BME280 ok.\r\n"); mpu9250.init(1, BITS_DLPF_CFG_188HZ); pc.printf("MPU9250 ok. WHOAMI=%02x\r\n", mpu9250.whoami()); if (mpu9250.whoami() != 0x71) { pc.printf("[ERROR] MPU9250 init fail.\r\n"); } mpu9250.set_gyro_scale(BITS_FS_2000DPS); //Set full scale range for gyros mpu9250.set_acc_scale(BITS_FS_16G); //Set full scale range for accs mpu9250.calib_acc(); mpu9250.AK8963_calib_Magnetometer(); // active high gps_en = 1; gps.attach(&gps_uart_buffering_handler, Serial::RxIrq); led_1 = 1; led_2 = 0; pc.printf("Send par %d seconds.\r\n", (SEND_INTERVAL_TICKS_PAR_COUNT * 200) / 1000); } void read_sensor_data() { sensor_data.bme280.temperature = bme280.getTemperature(); sensor_data.bme280.pressure = bme280.getPressure(); sensor_data.bme280.humidity = bme280.getHumidity(); mpu9250.read_all(); sensor_data.mpu9250.temperature = mpu9250.Temperature; for (int cnt_send = 0; cnt_send < 3; cnt_send++) { sensor_data.mpu9250.accelerometer[cnt_send] = mpu9250.accelerometer_data[cnt_send]; sensor_data.mpu9250.gyroscope[cnt_send] = mpu9250.gyroscope_data[cnt_send]; sensor_data.mpu9250.magnetometer[cnt_send] = mpu9250.Magnetometer[cnt_send]; } } void enqueue_sensor_data(int counter) { sakuraio.enqueueTx(0, (int32_t)counter); sakuraio.enqueueTx(1, sensor_data.bme280.temperature); sakuraio.enqueueTx(2, sensor_data.bme280.pressure); sakuraio.enqueueTx(3, sensor_data.bme280.humidity); sakuraio.enqueueTx(4, sensor_data.mpu9250.accelerometer[0]); sakuraio.enqueueTx(5, sensor_data.mpu9250.accelerometer[1]); sakuraio.enqueueTx(6, sensor_data.mpu9250.accelerometer[2]); sakuraio.enqueueTx(7, sensor_data.mpu9250.gyroscope[0]); sakuraio.enqueueTx(8, sensor_data.mpu9250.gyroscope[1]); sakuraio.enqueueTx(9, sensor_data.mpu9250.gyroscope[2]); sakuraio.enqueueTx(10, sensor_data.mpu9250.magnetometer[0]); sakuraio.enqueueTx(11, sensor_data.mpu9250.magnetometer[1]); sakuraio.enqueueTx(12, sensor_data.mpu9250.magnetometer[2]); sakuraio.enqueueTx(13, gps_decoder.get_longitude()); sakuraio.enqueueTx(14, gps_decoder.get_latitude()); sakuraio.enqueueTx(15, gps_decoder.get_unixtime()); } void gps_uart_buffering_handler() { while (gps.readable() == 1) { char c = gps.getc(); if (c == '\r') { continue; } uart_buffer[uart_buffer_index] = c; uart_buffer_index++; if (c == '\n') { uart_buffer[uart_buffer_index - 1] = '\0'; gps_decoder.set_nmea_message(uart_buffer); gps_decoder.decode(); uart_buffer_index = 0; } } } void loop() { static int cnt_send = 1; static int tick_by_200ms = 0; static int stat_sw5 = -1; uint8_t rx_available = 0; uint8_t rx_queued = 0; uint8_t rx_ch=0; uint8_t rx_type=0; uint8_t rx_value[8]; int64_t rx_offset=0; int64_t rx_val; uint32_t tx_tmp; uint8_t ch20_ctrl; uint32_t ch20_id; uint8_t ch20_mesg; if((sakuraio.getConnectionStatus() & 0x80) == 0x00) { //Offline lcd.cls(); lcd.printf("Offline"); pc.printf("Network is offline.\r\n(After 1 sec to running retry.)\r\n"); wait(1); connected_now = 0; return; } else { //ON_LINEだったとき if(0 == connected_now){ //接続直後(直前までオフラインだった)時 //現在のLED状態を申告する送信 tx_tmp = (MESG_INIT << 8) | (lcd_led & 0xFF); sakuraio.enqueueTx(20, tx_tmp); sakuraio.send(); //接続直後でLED情報送信中 connected_now = 1; //過去の送信カウント数クリアと、Offlineになってしまった液晶のsend再表示の為 stat_sw5 = -1; } if(1 == connected_now){ //現在のLED状態を申告に対する応答がプラットフォームから帰ってきてない時 if((tick_by_200ms % RETRY_INTERVAL_TICKS_PAR_COUNT) == 0){ //一定時間経過していたら再度LED状態を申告 tx_tmp = (MESG_INIT<<8) | (lcd_led & 0xFF); sakuraio.enqueueTx(20, tx_tmp); sakuraio.send(); } } } //スイッチ状態が切り替わった時、もしくは、LTE接続が一旦切れて復帰した時 if (stat_sw5 != sw_5) { stat_sw5 = sw_5; led_3 = stat_sw5; //State: `Send Enable' if (stat_sw5 == 0) { lcd.cls(); lcd.printf("Send:OFF"); } else { cnt_send = 1; tick_by_200ms = 0; lcd.cls(); lcd.printf("Send:ON"); } } if (stat_sw5 == 1) { //送信スイッチONの時。送信処理開始 if ((tick_by_200ms % SEND_INTERVAL_TICKS_PAR_COUNT) == 0) { //Send data intarval is 5 minutes. pc.printf("\r\n\r\n--------------------\r\n"); read_sensor_data(); pc.printf("BME280\r\n"); pc.printf("\tTemp: %.2fC\r\n", sensor_data.bme280.temperature); pc.printf("\tPres: %.2fhPa\r\n", sensor_data.bme280.pressure); pc.printf("\tHum: %.2f%%\r\n", sensor_data.bme280.humidity); pc.printf("MPU9250\r\n"); pc.printf("\tTemp: %.2fC\r\n", sensor_data.mpu9250.temperature); for (int j = 0; j < 3; j++) { pc.printf("\tacc[%d]: %.2f\r\n", j, sensor_data.mpu9250.accelerometer[j]); pc.printf("\tgyro[%d]: %.2f\r\n", j, sensor_data.mpu9250.gyroscope[j]); pc.printf("\tmag[%d]: %.2f\r\n", j, sensor_data.mpu9250.magnetometer[j]); } pc.printf("GPS\r\n"); pc.printf("\tlat: %f%c\r\n", gps_decoder.get_latitude(), gps_decoder.get_latitude() >= 0 ? 'N' : 'S'); pc.printf("\tlon: %f%c\r\n", gps_decoder.get_longitude(), gps_decoder.get_longitude() >= 0 ? 'E' : 'W'); pc.printf("\tspeed: %fkm/h\r\n", gps_decoder.get_speed()); pc.printf("\tmove_direction: %f\r\n", gps_decoder.get_move_direction()); pc.printf("\tdate: %d/%02d/%02d %02d:%02d:%02d (UTC)\r\n", gps_decoder.get_year(), gps_decoder.get_month(), gps_decoder.get_day(), gps_decoder.get_hour(), gps_decoder.get_min(), gps_decoder.get_sec()); pc.printf("\tUNIX time: %d\r\n", gps_decoder.get_unixtime()); led_2 = 1; pc.printf("Send:%d\r\n", cnt_send); lcd.setCursor(0, 1); lcd.printf("%d", cnt_send); enqueue_sensor_data(cnt_send); sakuraio.send(); cnt_send++; led_2 = 0; pc.printf("After %d sec to send.\r\n", (int)(SEND_INTERVAL_TICKS_PAR_COUNT * 0.2)); } } //受信確認処理 do { rx_available = 0; if ( CMD_ERROR_NONE == sakuraio.getRxQueueLength(&rx_available, &rx_queued)) { //getRxQueueLengthが成功したとき if (0 < rx_queued) { //sakura.ioモジュールの受信キューにデータが入っているとき //キューからひとつデータを取り出す if ( CMD_ERROR_NONE == sakuraio.dequeueRx(&rx_ch, &rx_type, rx_value, &rx_offset)) { //正常に受信キューからデータを取り出せたとき if ( (20 == rx_ch) && (0x49 == rx_type) ) { //LED状態の要求、もしくは、LED状態申告の回答のとき //受信した32bit整数値が、8bit値が4つの配列になって届くので、ひとつの整数値に整形 rx_val = ( (int64_t)rx_value[3] << 24) + ( (int64_t)rx_value[2] << 16) + ( (int64_t)rx_value[1] << 8) + ( (int64_t)rx_value[0] << 0); //受信した32bit値からbitmapに従ってそれぞれの情報の切り出し ch20_ctrl = rx_val & 0xFF; ch20_mesg = (rx_val>>8) & 0xFF; ch20_id = (rx_val>>16) & 0xFFFF; if ( (1 == ch20_ctrl) && (MESG_NORMAL == ch20_mesg)) { //LED状態の要求だったとき tx_tmp = (ch20_id<<16) | (MESG_NORMAL<<8) | (lcd_led & 0xFF); sakuraio.enqueueTx(20, tx_tmp); sakuraio.send(); } if ( (1 == ch20_ctrl) && (MESG_INIT == ch20_mesg)) { //LED状態申告の回答だったとき //フラグを進めて、LED状態到達確認済みとし、再送処理を止める connected_now = 2; } } if ( (21 == rx_ch) && (0x49 == rx_type) ) { //LED設定のとき //受信した32bit整数値が、8bit値が4つの配列になって届くので、ひとつの整数値に整形 rx_val = ( (int64_t)rx_value[3] << 24) + ( (int64_t)rx_value[2] << 16) + ( (int64_t)rx_value[1] << 8) + ( (int64_t)rx_value[0] << 0); //受信した32bit値からbitmapに従ってそれぞれの情報の切り出し ch20_ctrl = rx_val & 0xFF; ch20_mesg = (rx_val>>8) & 0xFF; ch20_id = (rx_val>>16) & 0xFFFF; if ( 1 == ch20_ctrl || 0 == ch20_ctrl ) { //LED制御値が、0(OFF) or 1(ON)だったとき //LEDに制御値を設定 lcd_led = ch20_ctrl; //設定後の値をプラットフォームへ返送 tx_tmp = (ch20_id<<16) | (MESG_NORMAL<<8) | (lcd_led & 0xFF); sakuraio.enqueueTx(20, tx_tmp); sakuraio.send(); } } } } } }while(0 < rx_queued); //受信キューが空になるまで回す led_1 = !led_1; led_4 = !sw_4; tick_by_200ms++; wait(0.2); } int main() { setup(); while(1) { loop(); } }