レンタルサーバーと連携したsakura.ioの運用例

Dependencies:   mbed SakuraIO MPU9250_SPI BME280 gps AQM0802A

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include <mbed.h>
00002 #include <AQM0802A.h>
00003 #include <BME280.h>
00004 #include <MPU9250.h>
00005 #include <SakuraIO.h>
00006 #include "SakuraPinNames.h"
00007 #include "sensors.h"
00008 #include "gps.h"
00009 
00010 //LED制御メッセージのタイプ種別の定数
00011 #define MESG_NORMAL 0
00012 #define MESG_INIT 1
00013 
00014 
00015 // Serial over CMSIS_DAP
00016 Serial pc(DAP_UART_TX, DAP_UART_RX, 9600);
00017 
00018 // GPS
00019 Serial gps(GPS_TX, GPS_RX, 9600);
00020 DigitalOut gps_en(GPS_EN);
00021 
00022 // LED
00023 DigitalOut led_1(LED1);
00024 DigitalOut led_2(LED2);
00025 DigitalOut led_3(LED3);
00026 DigitalOut led_4(LED4);
00027 
00028 // LCD backlight
00029 DigitalOut lcd_led(LED_LCD);
00030 
00031 // Switch
00032 DigitalIn sw_1(SW1);
00033 DigitalIn sw_2(SW2);
00034 DigitalIn sw_3(SW3);
00035 DigitalIn sw_4(SW4);
00036 DigitalIn sw_5(SW5);
00037 DigitalIn sw_6(SW6);
00038 
00039 // Internal I2C
00040 I2C internal_i2c(I2C_INTERNAL_SDA, I2C_INTERNAL_SCL);
00041 AQM0802A lcd(internal_i2c);
00042 BME280 bme280(internal_i2c);
00043 
00044 // SPI
00045 SPI internal_mpu9250_spi(SPI_MPU_MOSI, SPI_MPU_MISO, SPI_MPU_SCK);
00046 mpu9250_spi mpu9250(internal_mpu9250_spi, SPI_MPU_CS);
00047 
00048 // sakura.io
00049 //SakuraIO_I2C sakuraio(I2C_SDA, I2C_SCL);
00050 #define SPI_FREQ (350000)
00051 SPI sakuraio_spi(PB_15, PB_14, PB_13);
00052 DigitalOut sakuraio_cs(PB_12);
00053 SakuraIO_SPI sakuraio(sakuraio_spi, sakuraio_cs);
00054 
00055 SensorData sensor_data;
00056 
00057 // GPS UART buffer
00058 char uart_buffer[128] = {0};
00059 int uart_buffer_index = 0;
00060 
00061 //LED応対s申告の為のLTE接続した直後を検出するためのフラグ
00062 // 0:切断、1:接続直後でLED情報送信中、2:LED状態到達確認済み
00063 int connected_now = 0;
00064 
00065 // NMEA Decoder
00066 GPSDecoder gps_decoder;
00067 
00068 void gps_uart_buffering_handler();
00069 
00070 const int SEND_INTERVAL_TICKS_PAR_COUNT = 1500;
00071 
00072 const int RETRY_INTERVAL_TICKS_PAR_COUNT = 50;
00073 
00074 void setup()
00075 {
00076     lcd_led = 1;
00077     pc.printf("Hello World !\r\n");
00078     lcd.cls();
00079     lcd.printf("Hello");
00080     connected_now = 0;
00081 
00082     // Initialize sensors
00083     bme280.initialize();
00084     pc.printf("BME280 ok.\r\n");
00085     mpu9250.init(1, BITS_DLPF_CFG_188HZ);
00086     pc.printf("MPU9250 ok. WHOAMI=%02x\r\n", mpu9250.whoami());
00087     if (mpu9250.whoami() != 0x71) {
00088         pc.printf("[ERROR] MPU9250 init fail.\r\n");
00089     }
00090 
00091     mpu9250.set_gyro_scale(BITS_FS_2000DPS);    //Set full scale range for gyros
00092     mpu9250.set_acc_scale(BITS_FS_16G);          //Set full scale range for accs
00093     mpu9250.calib_acc();
00094     mpu9250.AK8963_calib_Magnetometer();
00095 
00096     // active high
00097     gps_en = 1;
00098     gps.attach(&gps_uart_buffering_handler, Serial::RxIrq);
00099 
00100     led_1 = 1;
00101     led_2 = 0;
00102     
00103     pc.printf("Send par %d seconds.\r\n", (SEND_INTERVAL_TICKS_PAR_COUNT * 200) / 1000);
00104 }
00105 
00106 void read_sensor_data()
00107 {
00108     sensor_data.bme280.temperature = bme280.getTemperature();
00109     sensor_data.bme280.pressure = bme280.getPressure();
00110     sensor_data.bme280.humidity = bme280.getHumidity();
00111 
00112     mpu9250.read_all();
00113     sensor_data.mpu9250.temperature = mpu9250.Temperature;
00114     for (int cnt_send = 0; cnt_send < 3; cnt_send++) {
00115         sensor_data.mpu9250.accelerometer[cnt_send] = mpu9250.accelerometer_data[cnt_send];
00116         sensor_data.mpu9250.gyroscope[cnt_send] = mpu9250.gyroscope_data[cnt_send];
00117         sensor_data.mpu9250.magnetometer[cnt_send] =  mpu9250.Magnetometer[cnt_send];
00118     }
00119 }
00120 
00121 void enqueue_sensor_data(int counter)
00122 {
00123     sakuraio.enqueueTx(0, (int32_t)counter);
00124     sakuraio.enqueueTx(1, sensor_data.bme280.temperature);
00125     sakuraio.enqueueTx(2, sensor_data.bme280.pressure);
00126     sakuraio.enqueueTx(3, sensor_data.bme280.humidity);
00127     sakuraio.enqueueTx(4, sensor_data.mpu9250.accelerometer[0]);
00128     sakuraio.enqueueTx(5, sensor_data.mpu9250.accelerometer[1]);
00129     sakuraio.enqueueTx(6, sensor_data.mpu9250.accelerometer[2]);
00130     sakuraio.enqueueTx(7, sensor_data.mpu9250.gyroscope[0]);
00131     sakuraio.enqueueTx(8, sensor_data.mpu9250.gyroscope[1]);
00132     sakuraio.enqueueTx(9, sensor_data.mpu9250.gyroscope[2]);
00133     sakuraio.enqueueTx(10, sensor_data.mpu9250.magnetometer[0]);
00134     sakuraio.enqueueTx(11, sensor_data.mpu9250.magnetometer[1]);
00135     sakuraio.enqueueTx(12, sensor_data.mpu9250.magnetometer[2]);
00136     sakuraio.enqueueTx(13, gps_decoder.get_longitude());
00137     sakuraio.enqueueTx(14, gps_decoder.get_latitude());
00138     sakuraio.enqueueTx(15, gps_decoder.get_unixtime());
00139 }
00140 
00141 void gps_uart_buffering_handler()
00142 {
00143     while (gps.readable() == 1) {
00144         char c = gps.getc();
00145         if (c == '\r') {
00146             continue;
00147         }
00148         uart_buffer[uart_buffer_index] = c;
00149         uart_buffer_index++;
00150         if (c == '\n') {
00151             uart_buffer[uart_buffer_index - 1] = '\0';
00152             gps_decoder.set_nmea_message(uart_buffer);
00153             gps_decoder.decode();
00154             uart_buffer_index = 0;
00155         }
00156     }
00157 }
00158 
00159 
00160 void loop()
00161 {
00162     static int cnt_send = 1;
00163     static int tick_by_200ms = 0;
00164     static int stat_sw5 = -1;
00165     uint8_t rx_available = 0;
00166     uint8_t rx_queued = 0;
00167     uint8_t rx_ch=0;
00168     uint8_t rx_type=0;
00169     uint8_t rx_value[8];
00170     int64_t rx_offset=0;
00171     int64_t rx_val;
00172     uint32_t tx_tmp;
00173     uint8_t ch20_ctrl;
00174     uint32_t ch20_id;
00175     uint8_t ch20_mesg;
00176 
00177     if((sakuraio.getConnectionStatus() & 0x80) == 0x00) {
00178         //Offline
00179         lcd.cls();
00180         lcd.printf("Offline");
00181         pc.printf("Network is offline.\r\n(After 1 sec to running retry.)\r\n");
00182         wait(1);
00183         connected_now = 0;
00184         return;    
00185     }
00186     else {
00187         //ON_LINEだったとき
00188         if(0 == connected_now){
00189             //接続直後(直前までオフラインだった)時
00190             
00191             //現在のLED状態を申告する送信
00192             tx_tmp = (MESG_INIT << 8) | (lcd_led & 0xFF);
00193             sakuraio.enqueueTx(20, tx_tmp);
00194             sakuraio.send();
00195             
00196             //接続直後でLED情報送信中
00197             connected_now = 1;
00198             
00199             //過去の送信カウント数クリアと、Offlineになってしまった液晶のsend再表示の為
00200             stat_sw5 = -1;
00201         }
00202         if(1 == connected_now){
00203             //現在のLED状態を申告に対する応答がプラットフォームから帰ってきてない時
00204             if((tick_by_200ms % RETRY_INTERVAL_TICKS_PAR_COUNT) == 0){
00205                 //一定時間経過していたら再度LED状態を申告
00206                 tx_tmp = (MESG_INIT<<8) | (lcd_led & 0xFF);
00207                 sakuraio.enqueueTx(20, tx_tmp);
00208                 sakuraio.send();
00209             }
00210         }   
00211     }
00212 
00213             
00214             
00215     //スイッチ状態が切り替わった時、もしくは、LTE接続が一旦切れて復帰した時
00216     if (stat_sw5 != sw_5) {
00217         stat_sw5 = sw_5;
00218         led_3 = stat_sw5;   //State: `Send Enable'
00219         if (stat_sw5 == 0) {
00220             lcd.cls();
00221             lcd.printf("Send:OFF");
00222         } else {
00223             cnt_send = 1;
00224             tick_by_200ms = 0;
00225             lcd.cls();
00226             lcd.printf("Send:ON");
00227         }
00228     }
00229     
00230     if (stat_sw5 == 1) {
00231         //送信スイッチONの時。送信処理開始
00232         if ((tick_by_200ms % SEND_INTERVAL_TICKS_PAR_COUNT) == 0) {  //Send data intarval is 5 minutes.
00233             pc.printf("\r\n\r\n--------------------\r\n");
00234             read_sensor_data();
00235             pc.printf("BME280\r\n");
00236             pc.printf("\tTemp: %.2fC\r\n", sensor_data.bme280.temperature);
00237             pc.printf("\tPres: %.2fhPa\r\n", sensor_data.bme280.pressure);
00238             pc.printf("\tHum: %.2f%%\r\n", sensor_data.bme280.humidity);
00239             pc.printf("MPU9250\r\n");
00240             pc.printf("\tTemp: %.2fC\r\n", sensor_data.mpu9250.temperature);
00241             for (int j = 0; j < 3; j++) {
00242                 pc.printf("\tacc[%d]: %.2f\r\n", j, sensor_data.mpu9250.accelerometer[j]);
00243                 pc.printf("\tgyro[%d]: %.2f\r\n", j, sensor_data.mpu9250.gyroscope[j]);
00244                 pc.printf("\tmag[%d]: %.2f\r\n", j, sensor_data.mpu9250.magnetometer[j]);
00245             }
00246             pc.printf("GPS\r\n");
00247             pc.printf("\tlat: %f%c\r\n", 
00248                     gps_decoder.get_latitude(), 
00249                     gps_decoder.get_latitude() >= 0 ? 'N' : 'S');
00250             pc.printf("\tlon: %f%c\r\n", 
00251                     gps_decoder.get_longitude(),
00252                     gps_decoder.get_longitude() >= 0 ? 'E' : 'W');
00253             pc.printf("\tspeed: %fkm/h\r\n", gps_decoder.get_speed());
00254             pc.printf("\tmove_direction: %f\r\n", gps_decoder.get_move_direction());
00255             pc.printf("\tdate: %d/%02d/%02d %02d:%02d:%02d (UTC)\r\n",
00256                     gps_decoder.get_year(), gps_decoder.get_month(), gps_decoder.get_day(),
00257                     gps_decoder.get_hour(), gps_decoder.get_min(), gps_decoder.get_sec());
00258             pc.printf("\tUNIX time: %d\r\n", gps_decoder.get_unixtime());
00259             led_2 = 1;
00260             pc.printf("Send:%d\r\n", cnt_send);
00261             lcd.setCursor(0, 1);
00262             lcd.printf("%d", cnt_send);
00263             enqueue_sensor_data(cnt_send);
00264             sakuraio.send();
00265             cnt_send++;
00266             led_2 = 0;
00267             pc.printf("After %d sec to send.\r\n", (int)(SEND_INTERVAL_TICKS_PAR_COUNT * 0.2));
00268         }
00269     }
00270     
00271     //受信確認処理
00272     do {
00273         rx_available = 0;
00274         if ( CMD_ERROR_NONE == sakuraio.getRxQueueLength(&rx_available, &rx_queued)) {
00275             //getRxQueueLengthが成功したとき
00276             if (0 < rx_queued) {
00277                  //sakura.ioモジュールの受信キューにデータが入っているとき
00278                  //キューからひとつデータを取り出す
00279                 if ( CMD_ERROR_NONE == sakuraio.dequeueRx(&rx_ch, &rx_type, rx_value, &rx_offset)) {
00280                     //正常に受信キューからデータを取り出せたとき
00281                     if ( (20 == rx_ch) && (0x49 == rx_type) ) {
00282                         //LED状態の要求、もしくは、LED状態申告の回答のとき
00283                         
00284                         //受信した32bit整数値が、8bit値が4つの配列になって届くので、ひとつの整数値に整形
00285                         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);
00286                         
00287                         //受信した32bit値からbitmapに従ってそれぞれの情報の切り出し
00288                         ch20_ctrl = rx_val & 0xFF;
00289                         ch20_mesg = (rx_val>>8) & 0xFF;
00290                         ch20_id = (rx_val>>16) & 0xFFFF;
00291                         
00292                         
00293                         if ( (1 == ch20_ctrl) && (MESG_NORMAL == ch20_mesg)) {
00294                             //LED状態の要求だったとき
00295                             tx_tmp = (ch20_id<<16) | (MESG_NORMAL<<8) | (lcd_led & 0xFF);
00296                             sakuraio.enqueueTx(20, tx_tmp);
00297                             sakuraio.send();
00298                         }
00299                         if ( (1 == ch20_ctrl) && (MESG_INIT == ch20_mesg)) {
00300                             //LED状態申告の回答だったとき
00301                             //フラグを進めて、LED状態到達確認済みとし、再送処理を止める
00302                             connected_now = 2;
00303                         }
00304                     }
00305                     if ( (21 == rx_ch) && (0x49 == rx_type) ) {
00306                         //LED設定のとき
00307                         
00308                         //受信した32bit整数値が、8bit値が4つの配列になって届くので、ひとつの整数値に整形
00309                         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);
00310                         
00311                         //受信した32bit値からbitmapに従ってそれぞれの情報の切り出し
00312                         ch20_ctrl = rx_val & 0xFF;
00313                         ch20_mesg = (rx_val>>8) & 0xFF;
00314                         ch20_id = (rx_val>>16) & 0xFFFF;
00315                         
00316                         
00317                         if ( 1 == ch20_ctrl || 0 == ch20_ctrl ) {
00318                             //LED制御値が、0(OFF) or 1(ON)だったとき
00319                             
00320                             //LEDに制御値を設定
00321                             lcd_led = ch20_ctrl;
00322                             
00323                             //設定後の値をプラットフォームへ返送
00324                             tx_tmp = (ch20_id<<16) | (MESG_NORMAL<<8) | (lcd_led & 0xFF);
00325                             sakuraio.enqueueTx(20, tx_tmp);
00326                             sakuraio.send();
00327                         }
00328                     }
00329                 }
00330             }
00331         }
00332     }while(0 < rx_queued); //受信キューが空になるまで回す
00333                             
00334                 
00335     
00336     led_1 = !led_1;
00337     led_4 = !sw_4;
00338     tick_by_200ms++;
00339     wait(0.2);
00340 }
00341 
00342 
00343 int main()
00344 {
00345     setup();
00346     while(1) {
00347         loop();
00348     }
00349 }