Marc Drouin / Mbed OS mDot-IKS01A1-Explora

Dependencies:   mDot_X_NUCLEO_IKS01A1 libmDot-dev-mbed5-deprecated

Fork of mDot-IKS01A1 by Peter Ferland

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "mDot.h"
00003 #include "x_nucleo_iks01a1.h"
00004 #include "dot_util.h"
00005 #include "RadioEvent.h"
00006 #include <cmath>
00007 
00008 // Add support to connect to Explora server
00009 
00010 DigitalOut MyLed(D7,1);
00011 
00012 // mDot UDK board demo with X-NUCLEO-IKS01A1 sensor card
00013 // For more examples see the Dot-Examples project:
00014 // https://developer.mbed.org/teams/MultiTech/code/Dot-Examples/
00015 
00016 // This triggers an I2C issue in mbed-os 5.1.5
00017 // Use any other revision to compile. (Tested with libmDot-dev/mbed-os 5.2.2
00018 //#define SENET
00019 #ifdef ACTILITY
00020 // Network Id for Senet public network
00021 static uint8_t network_id[] = {0xF0, 0x3D, 0x29,0xAC,0x71,0x00,0x00, 0x00};
00022 // Register at or Sign in to http://portal.senetco.com/ and register your NodeId to receive your AppId
00023 // {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B}
00024 static uint8_t network_key[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //{0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B};
00025 static uint8_t frequency_sub_band = 0;
00026 static bool public_network = true;
00027 #elif defined(SENET)
00028 // Network Id for Senet public network
00029 static uint8_t network_id[] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
00030 // Register at or Sign in to http://portal.senetco.com/ and register your NodeId to receive your AppId
00031 // {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B}
00032 static uint8_t network_key[] =  {0x5F,0x7B,0x08,0x15,0x55,0x69,0x9A,0x2E,0x3C,0x91,0xE3,0xFE,0xF0,0x2A,0x77,0x79};
00033 // 1 For Senet, configurable on your Conduit
00034 static uint8_t frequency_sub_band = 1;
00035 // True for Senet, false for your Conduit.
00036 static bool public_network = true;
00037 #else
00038 //Replace with settings on your Conduit
00039 static std::string network_name = "EcoLabTest";
00040 static std::string network_passphrase = "EcoLabTest"; 
00041 // 1 For Senet, configurable on your Conduit
00042 static uint8_t frequency_sub_band = 1;
00043 // True for Senet, false for your Conduit.
00044 static bool public_network = true; // false;
00045 #endif
00046 static uint8_t ack = 0;
00047 static uint8_t tx_datarate = mDot::SF_7;
00048 
00049 // deepsleep consumes slightly less current than sleep
00050 // in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
00051 // in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
00052 // if deep_sleep == true, device will enter deepsleep mode
00053 static bool deep_sleep = false;
00054 
00055 mDot *dot = NULL;
00056 
00057 int main()
00058 {
00059     Serial pc(USBTX, USBRX);
00060     
00061     /* Instantiate the expansion board */
00062     X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL, PC_1);
00063     
00064     /* Retrieve the composing elements of the expansion board */
00065     GyroSensor *gyroscope = mems_expansion_board->GetGyroscope();
00066     MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer();
00067     MagneticSensor *magnetometer = mems_expansion_board->magnetometer;
00068     HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor;
00069     PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor;
00070     TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor;
00071     TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor;
00072     // Custom event handler for automatically displaying RX data
00073     RadioEvent events;
00074     pc.baud(115200);
00075 
00076 
00077 #if defined(SENET) || defined(ACTILITY)
00078 #if defined(SENET)
00079     printf("Connect to SENET network\r\n");
00080 #else
00081     printf("Connect to ACTILITY network\r\n");
00082 #endif
00083 #else
00084     printf("Connect to MultiConnect, network_name:%s, network_passphrase:%s\r\n", network_name,network_passphrase);
00085 #endif
00086 
00087 //    LedD7 = 0;
00088 //    printf("Led ON\r\n");
00089 //    osDelay(2000);
00090 //    LedD7 = 1;
00091 //    printf("Led OFF\r\n");
00092 //    osDelay(2000);
00093 //    LedD7 = 0;
00094 //    printf("Led ON\r\n");
00095 //    osDelay(2000);
00096 //    LedD7 = 1;
00097 //    printf("Led OFF\r\n");
00098 //    osDelay(2000);
00099 //    LedD7 = 0;
00100 //    printf("Led ON\r\n");
00101     
00102     /* Initialize mDot */
00103     dot = mDot::getInstance();
00104 
00105     //dot->setAdr(true);
00106     mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL);
00107     dot->setEvents(&events);
00108     
00109 
00110     if (!dot->getStandbyFlag()) {
00111         logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
00112         // start from a well-known state
00113         logInfo("defaulting Dot configuration");
00114         dot->resetConfig();
00115         dot->resetNetworkSession();
00116         
00117         // update configuration if necessary
00118         // in AUTO_OTA mode the session is automatically saved, so saveNetworkSession and restoreNetworkSession are not needed
00119         if (dot->getJoinMode() != mDot::AUTO_OTA) {
00120             logInfo("changing network join mode to AUTO_OTA");
00121             if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) {
00122                 logError("failed to set network join mode to AUTO_OTA");
00123             }
00124         }
00125         
00126         uint32_t current_tx_datarate = dot->getTxDataRate();
00127         if (current_tx_datarate != tx_datarate) {
00128             logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
00129             if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
00130                 logError("failed to set TX datarate to %u", tx_datarate);
00131             }
00132         }
00133         // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
00134         // only one method or the other should be used!
00135         // network ID = crc64(network name)
00136 #if defined(SENET) || defined(ACTILITY)
00137         // network KEY = cmac(network passphrase)
00138         update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
00139 #else
00140         update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
00141 #endif
00142         
00143         // configure network link checks
00144         // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
00145         // check the link every count packets
00146         // declare the Dot disconnected after threshold failed link checks
00147         // for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
00148         update_network_link_check_config(3, 5);
00149         
00150         // save changes to configuration
00151         logInfo("saving configuration");
00152         if (!dot->saveConfig()) {
00153             logError("failed to save configuration");
00154         }
00155     
00156         // display configuration
00157         display_config();
00158     }  else {
00159         // restore the saved session if the dot woke from deepsleep mode
00160         // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
00161         logInfo("restoring network session from NVM");
00162         dot->restoreNetworkSession();
00163     }
00164 
00165 
00166     
00167     while (true) {
00168         std::vector<uint8_t> tx_data;
00169 
00170         // join network if not joined
00171         if (!dot->getNetworkJoinStatus()) {
00172             join_network();
00173         }
00174 
00175         // Payload structure for mydevices cayenne:
00176         // 1 byte Data1 ID
00177         // 1 Byte Data1 Type
00178         // N Bytes Data1 
00179         // 1 byte data 2 ID
00180         // 1 byte data 2 type
00181         // n Bytes data 2
00182         // ... 
00183         
00184         // formats:
00185         // Temperature sensor:
00186         /*
00187          * IPSO: 3303
00188          * LPP 103
00189          * HEX: 67
00190          * Data size: 2
00191          * Resolution: 0.1 degres C
00192          
00193          * Humidity sensor
00194          * IPSO: 3304
00195          * LPP: 104
00196          * Hex: 68
00197          * Datasize: 1
00198          * Resolution: 0.5% unsigned
00199          
00200          * Barometer/pressure sensor
00201          * IPSO: 3315
00202          * LPP: 115
00203          * Hex: 73
00204          * Datasize: 2
00205          * Resolution 0.1hPa unsigned MSB
00206          
00207          * Accelerometer
00208          * IPSO: 3313
00209          * LPP: 113
00210          * Hex: 71
00211          * Data size: 6
00212          * Resolution: 0.001G signed MSB per axis
00213          
00214          * Gyrometer
00215          * IPSO: 3334
00216          * LPP: 134
00217          * Hex: 86
00218          * Data size: 6
00219          * Resolution: 0.01 degrees/s signed msb per axis
00220         */
00221         
00222         //temp floats
00223         float value1, value2;
00224         
00225         // HTS221 Humidity sensor
00226         temp_sensor1->GetTemperature(&value1);
00227         humidity_sensor->GetHumidity(&value2);
00228         
00229         //serialize data and append to packet
00230         // Cayenne data: temperature; tag is 0x67, 2 bytes signed, 0.1 C/bit
00231         tx_data.push_back(uint8_t(1)); // data id
00232         tx_data.push_back(uint8_t(0x67)); // data type - temp
00233         int16_t temp = floor(value1*10 + 0.5f);
00234         //logInfo("Temp payload: %d", temp);
00235         tx_data.push_back(uint8_t( 0xFF & (temp >> 8)));
00236         tx_data.push_back(uint8_t(0xFF & temp));
00237         
00238         
00239         tx_data.push_back(uint8_t(2)); // data id
00240         tx_data.push_back(uint8_t(0x68)); // data type - humidity
00241         temp = floor(value2 * 2.0f + 0.5f);
00242         tx_data.push_back(uint8_t(0xFF & temp ));
00243 
00244         logInfo("\r\n\r\nTemperature data %f", value1);
00245         logInfo("Humidity data: %f", value2);
00246         
00247         pressure_sensor->GetPressure(&value1);
00248         logInfo("PRessure data: %f", value1);
00249         // pressure is reported in mbar, cayenne wants it in 0.1 hPa
00250         // 1mbar = 1 hPa
00251         //temp = floor(value1 * 100.0f + 0.5f);
00252         tx_data.push_back(uint8_t(3)); // data id
00253         tx_data.push_back(uint8_t(0x73)); // data type - pressure
00254         temp = floor(value1 / 0.1f + 0.5f);
00255         tx_data.push_back(uint8_t(0xFF & (temp >> 8)));
00256         tx_data.push_back(uint8_t(0xFF & temp));
00257         
00258         
00259         // Get accelerometer data
00260         int32_t accel_vector[3];
00261         // returns in mG
00262         accelerometer->Get_X_Axes(accel_vector);
00263         logInfo("Acclerometer: %d,%d,%d", accel_vector[0], accel_vector[1], accel_vector[2]);
00264         
00265         tx_data.push_back(uint8_t(4)); // data id
00266         tx_data.push_back(uint8_t(0x71)); // data type - accelerometer
00267         for(int i=0; i<3; i++){
00268             tx_data.push_back(uint8_t(0xFF & (accel_vector[i] >> 8)));
00269             tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
00270             //logInfo("Acc: %d,%d,0x%02X, 0x%02X", i, accel_vector[i], accel_vector[2]);
00271         }
00272         
00273         // Get gyro data
00274         gyroscope->Get_G_Axes(accel_vector);
00275         logInfo("Gyroscope: %d,%d,%d", accel_vector[0], accel_vector[1], accel_vector[2]);
00276         // gyro reports in milidegrees/sec, cayenne wants centidegrees/sec
00277         tx_data.push_back(uint8_t(5)); //data id
00278         tx_data.push_back(uint8_t(0x86)); // data type - gyrometer
00279         for(int i=0; i<3; i++){
00280             accel_vector[i] /= 10;
00281             tx_data.push_back(uint8_t(0xFF & (accel_vector[i] >> 8)));
00282             tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
00283         }
00284         
00285         // print Raw Data
00286         //logInfo("Temp raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[0], tx_data[1], tx_data[2], tx_data[3]);
00287         //logInfo("Hum raw: 0x%02X, 0x%02X, 0x%02X",tx_data[4], tx_data[5], tx_data[6]);
00288         //logInfo("Pres raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[7], tx_data[8], tx_data[9], tx_data[10]);
00289         //logInfo("Acc raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[11], tx_data[12], tx_data[13], tx_data[14], tx_data[15], tx_data[16], tx_data[17], tx_data[18]);
00290         //logInfo("Gir raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[19], tx_data[20], tx_data[21], tx_data[22], tx_data[23], tx_data[24], tx_data[25], tx_data[26]);
00291         send_data(tx_data);
00292         
00293         if(deep_sleep){
00294         // if going into deepsleep mode, save the session so we don't need to join again after waking up
00295         // not necessary if going into sleep mode since RAM is retained
00296             logInfo("saving network session to NVM");
00297             dot->saveNetworkSession();
00298         }
00299         
00300 
00301         // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
00302         // mdr sleep_wake_rtc_only(deep_sleep);
00303         //sleep_wake_interrupt_only(deep_sleep);
00304         //sleep_wake_rtc_or_interrupt(deep_sleep);
00305         
00306         uint32_t delay_s = dot->getNextTxMs() / 1000;
00307         if (delay_s < 5) {
00308             delay_s = 5;
00309         }
00310         
00311         logInfo("waiting %d", delay_s);
00312         osDelay(delay_s*1000);
00313         logInfo("application resume", deepsleep ? "execute from beginning" : "resume");
00314 
00315     }
00316 
00317     return 0;    
00318 }