Peter Ferland / Mbed OS mDot-IKS01A1

Dependencies:   mDot_X_NUCLEO_IKS01A1 libmDot-dev-mbed5-deprecated

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