Example of using the mDot UDK with the X-NUCLEO-IKS01A2 board

Dependencies:   MTS_X_NUCLEO_IKS01A2 libmDot-mbed5

Fork of mDot-IKS01A1 by Peter Ferland

Committer:
pferland
Date:
Tue Jan 17 22:53:01 2017 +0000
Revision:
9:e642e8f9ea37
Parent:
8:bfbc3dd47166
Child:
10:1e3e3ab9c29c
Updated all sensors to use the Cayenne low power payload

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pferland 0:9e88a9018fc0 1 #include "mbed.h"
pferland 0:9e88a9018fc0 2 #include "mDot.h"
pferland 0:9e88a9018fc0 3 #include "x_nucleo_iks01a1.h"
pferland 0:9e88a9018fc0 4 #include "dot_util.h"
pferland 0:9e88a9018fc0 5 #include "RadioEvent.h"
pferland 9:e642e8f9ea37 6 #include <cmath>
pferland 0:9e88a9018fc0 7
pferland 4:142c85980a6f 8 // mDot UDK board demo with X-NUCLEO-IKS01A1 sensor card
pferland 4:142c85980a6f 9 // For more examples see the Dot-Examples project:
pferland 4:142c85980a6f 10 // https://developer.mbed.org/teams/MultiTech/code/Dot-Examples/
pferland 4:142c85980a6f 11
pferland 4:142c85980a6f 12 // This triggers an I2C issue in mbed-os 5.1.5
pferland 4:142c85980a6f 13 // Use any other revision to compile. (Tested with libmDot-dev/mbed-os 5.2.2
pferland 9:e642e8f9ea37 14 #define SENET
pferland 9:e642e8f9ea37 15 #ifdef SENET
pferland 4:142c85980a6f 16 // Network Id for Senet public network
pferland 4:142c85980a6f 17 static uint8_t network_id[] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
pferland 4:142c85980a6f 18 // Register at or Sign in to http://portal.senetco.com/ and register your NodeId to receive your AppId
pferland 9:e642e8f9ea37 19 // {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B}
pferland 9:e642e8f9ea37 20 static uint8_t network_key[] = {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B};
pferland 4:142c85980a6f 21 // 1 For Senet, configurable on your Conduit
pferland 0:9e88a9018fc0 22 static uint8_t frequency_sub_band = 1;
pferland 4:142c85980a6f 23 // True for Senet, false for your Conduit.
pferland 4:142c85980a6f 24 static bool public_network = true;
pferland 9:e642e8f9ea37 25 #else
pferland 9:e642e8f9ea37 26 //Replace with settings on your Conduit
pferland 9:e642e8f9ea37 27 static std::string network_name = "TestTest";
pferland 9:e642e8f9ea37 28 static std::string network_passphrase = "TestTest";
pferland 9:e642e8f9ea37 29 // 1 For Senet, configurable on your Conduit
pferland 9:e642e8f9ea37 30 static uint8_t frequency_sub_band = 1;
pferland 9:e642e8f9ea37 31 // True for Senet, false for your Conduit.
pferland 9:e642e8f9ea37 32 static bool public_network = false;
pferland 9:e642e8f9ea37 33 #endif
pferland 9:e642e8f9ea37 34 static uint8_t ack = 1;
pferland 9:e642e8f9ea37 35 static uint8_t tx_datarate = mDot::DR4;
pferland 0:9e88a9018fc0 36
pferland 4:142c85980a6f 37 // deepsleep consumes slightly less current than sleep
pferland 4:142c85980a6f 38 // in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
pferland 4:142c85980a6f 39 // in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
pferland 4:142c85980a6f 40 // if deep_sleep == true, device will enter deepsleep mode
pferland 4:142c85980a6f 41 static bool deep_sleep = false;
pferland 4:142c85980a6f 42
pferland 0:9e88a9018fc0 43 mDot *dot = NULL;
pferland 0:9e88a9018fc0 44
pferland 0:9e88a9018fc0 45 int main()
pferland 0:9e88a9018fc0 46 {
pferland 4:142c85980a6f 47 Serial pc(USBTX, USBRX);
pferland 4:142c85980a6f 48
pferland 4:142c85980a6f 49 /* Instantiate the expansion board */
pferland 4:142c85980a6f 50 X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL, PC_1);
pferland 4:142c85980a6f 51
pferland 4:142c85980a6f 52 /* Retrieve the composing elements of the expansion board */
pferland 4:142c85980a6f 53 GyroSensor *gyroscope = mems_expansion_board->GetGyroscope();
pferland 4:142c85980a6f 54 MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer();
pferland 4:142c85980a6f 55 MagneticSensor *magnetometer = mems_expansion_board->magnetometer;
pferland 4:142c85980a6f 56 HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor;
pferland 4:142c85980a6f 57 PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor;
pferland 4:142c85980a6f 58 TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor;
pferland 4:142c85980a6f 59 TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor;
pferland 0:9e88a9018fc0 60 // Custom event handler for automatically displaying RX data
pferland 0:9e88a9018fc0 61 RadioEvent events;
pferland 0:9e88a9018fc0 62 pc.baud(115200);
pferland 0:9e88a9018fc0 63
pferland 0:9e88a9018fc0 64 /* Initialize mDot */
pferland 0:9e88a9018fc0 65 dot = mDot::getInstance();
pferland 8:bfbc3dd47166 66
pferland 8:bfbc3dd47166 67 //dot->setAdr(true);
pferland 4:142c85980a6f 68 mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL);
pferland 0:9e88a9018fc0 69 dot->setEvents(&events);
pferland 0:9e88a9018fc0 70
pferland 0:9e88a9018fc0 71
pferland 0:9e88a9018fc0 72 if (!dot->getStandbyFlag()) {
pferland 0:9e88a9018fc0 73 logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
pferland 0:9e88a9018fc0 74 // start from a well-known state
pferland 0:9e88a9018fc0 75 logInfo("defaulting Dot configuration");
pferland 0:9e88a9018fc0 76 dot->resetConfig();
pferland 0:9e88a9018fc0 77 dot->resetNetworkSession();
pferland 0:9e88a9018fc0 78
pferland 0:9e88a9018fc0 79 // update configuration if necessary
pferland 0:9e88a9018fc0 80 // in AUTO_OTA mode the session is automatically saved, so saveNetworkSession and restoreNetworkSession are not needed
pferland 0:9e88a9018fc0 81 if (dot->getJoinMode() != mDot::AUTO_OTA) {
pferland 0:9e88a9018fc0 82 logInfo("changing network join mode to AUTO_OTA");
pferland 0:9e88a9018fc0 83 if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) {
pferland 0:9e88a9018fc0 84 logError("failed to set network join mode to AUTO_OTA");
pferland 0:9e88a9018fc0 85 }
pferland 0:9e88a9018fc0 86 }
pferland 8:bfbc3dd47166 87
pferland 8:bfbc3dd47166 88 uint32_t current_tx_datarate = dot->getTxDataRate();
pferland 8:bfbc3dd47166 89 if (current_tx_datarate != tx_datarate) {
pferland 8:bfbc3dd47166 90 logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
pferland 8:bfbc3dd47166 91 if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
pferland 8:bfbc3dd47166 92 logError("failed to set TX datarate to %u", tx_datarate);
pferland 8:bfbc3dd47166 93 }
pferland 8:bfbc3dd47166 94 }
pferland 0:9e88a9018fc0 95 // 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
pferland 0:9e88a9018fc0 96 // only one method or the other should be used!
pferland 0:9e88a9018fc0 97 // network ID = crc64(network name)
pferland 9:e642e8f9ea37 98 #ifdef SENET
pferland 0:9e88a9018fc0 99 // network KEY = cmac(network passphrase)
pferland 4:142c85980a6f 100 update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
pferland 9:e642e8f9ea37 101 #else
pferland 9:e642e8f9ea37 102 update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
pferland 9:e642e8f9ea37 103 #endif
pferland 0:9e88a9018fc0 104
pferland 0:9e88a9018fc0 105 // configure network link checks
pferland 0:9e88a9018fc0 106 // 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
pferland 0:9e88a9018fc0 107 // check the link every count packets
pferland 0:9e88a9018fc0 108 // declare the Dot disconnected after threshold failed link checks
pferland 0:9e88a9018fc0 109 // for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
pferland 0:9e88a9018fc0 110 update_network_link_check_config(3, 5);
pferland 0:9e88a9018fc0 111
pferland 0:9e88a9018fc0 112 // save changes to configuration
pferland 0:9e88a9018fc0 113 logInfo("saving configuration");
pferland 0:9e88a9018fc0 114 if (!dot->saveConfig()) {
pferland 0:9e88a9018fc0 115 logError("failed to save configuration");
pferland 0:9e88a9018fc0 116 }
pferland 0:9e88a9018fc0 117
pferland 0:9e88a9018fc0 118 // display configuration
pferland 0:9e88a9018fc0 119 display_config();
pferland 0:9e88a9018fc0 120 } else {
pferland 0:9e88a9018fc0 121 // restore the saved session if the dot woke from deepsleep mode
pferland 0:9e88a9018fc0 122 // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
pferland 0:9e88a9018fc0 123 logInfo("restoring network session from NVM");
pferland 0:9e88a9018fc0 124 dot->restoreNetworkSession();
pferland 0:9e88a9018fc0 125 }
pferland 3:d34798ffcaf8 126
pferland 3:d34798ffcaf8 127
pferland 0:9e88a9018fc0 128
pferland 0:9e88a9018fc0 129 while (true) {
pferland 0:9e88a9018fc0 130 std::vector<uint8_t> tx_data;
pferland 0:9e88a9018fc0 131
pferland 0:9e88a9018fc0 132 // join network if not joined
pferland 0:9e88a9018fc0 133 if (!dot->getNetworkJoinStatus()) {
pferland 0:9e88a9018fc0 134 join_network();
pferland 0:9e88a9018fc0 135 }
pferland 7:d2052933ebcb 136
pferland 9:e642e8f9ea37 137 // Payload structure for mydevices cayenne:
pferland 9:e642e8f9ea37 138 // 1 byte Data1 ID
pferland 9:e642e8f9ea37 139 // 1 Byte Data1 Type
pferland 9:e642e8f9ea37 140 // N Bytes Data1
pferland 9:e642e8f9ea37 141 // 1 byte data 2 ID
pferland 9:e642e8f9ea37 142 // 1 byte data 2 type
pferland 9:e642e8f9ea37 143 // n Bytes data 2
pferland 9:e642e8f9ea37 144 // ...
pferland 9:e642e8f9ea37 145
pferland 9:e642e8f9ea37 146 // formats:
pferland 9:e642e8f9ea37 147 // Temperature sensor:
pferland 9:e642e8f9ea37 148 /*
pferland 9:e642e8f9ea37 149 * IPSO: 3303
pferland 9:e642e8f9ea37 150 * LPP 103
pferland 9:e642e8f9ea37 151 * HEX: 67
pferland 9:e642e8f9ea37 152 * Data size: 2
pferland 9:e642e8f9ea37 153 * Resolution: 0.1 degres C
pferland 9:e642e8f9ea37 154
pferland 9:e642e8f9ea37 155 * Humidity sensor
pferland 9:e642e8f9ea37 156 * IPSO: 3304
pferland 9:e642e8f9ea37 157 * LPP: 104
pferland 9:e642e8f9ea37 158 * Hex: 68
pferland 9:e642e8f9ea37 159 * Datasize: 1
pferland 9:e642e8f9ea37 160 * Resolution: 0.5% unsigned
pferland 9:e642e8f9ea37 161
pferland 9:e642e8f9ea37 162 * Barometer/pressure sensor
pferland 9:e642e8f9ea37 163 * IPSO: 3315
pferland 9:e642e8f9ea37 164 * LPP: 115
pferland 9:e642e8f9ea37 165 * Hex: 73
pferland 9:e642e8f9ea37 166 * Datasize: 2
pferland 9:e642e8f9ea37 167 * Resolution 0.1hPa unsigned MSB
pferland 9:e642e8f9ea37 168
pferland 9:e642e8f9ea37 169 * Accelerometer
pferland 9:e642e8f9ea37 170 * IPSO: 3313
pferland 9:e642e8f9ea37 171 * LPP: 113
pferland 9:e642e8f9ea37 172 * Hex: 71
pferland 9:e642e8f9ea37 173 * Data size: 6
pferland 9:e642e8f9ea37 174 * Resolution: 0.001G signed MSB per axis
pferland 9:e642e8f9ea37 175
pferland 9:e642e8f9ea37 176 * Gyrometer
pferland 9:e642e8f9ea37 177 * IPSO: 3334
pferland 9:e642e8f9ea37 178 * LPP: 134
pferland 9:e642e8f9ea37 179 * Hex: 86
pferland 9:e642e8f9ea37 180 * Data size: 6
pferland 9:e642e8f9ea37 181 * Resolution: 0.01 degrees/s signed msb per axis
pferland 9:e642e8f9ea37 182 */
pferland 9:e642e8f9ea37 183
pferland 0:9e88a9018fc0 184 //temp floats
pferland 0:9e88a9018fc0 185 float value1, value2;
pferland 4:142c85980a6f 186
pferland 0:9e88a9018fc0 187 // HTS221 Humidity sensor
pferland 0:9e88a9018fc0 188 temp_sensor1->GetTemperature(&value1);
pferland 0:9e88a9018fc0 189 humidity_sensor->GetHumidity(&value2);
pferland 4:142c85980a6f 190
pferland 0:9e88a9018fc0 191 //serialize data and append to packet
pferland 9:e642e8f9ea37 192 // Cayenne data: temperature; tag is 0x67, 2 bytes signed, 0.1 C/bit
pferland 9:e642e8f9ea37 193 tx_data.push_back(uint8_t(1)); // data id
pferland 9:e642e8f9ea37 194 tx_data.push_back(uint8_t(0x67)); // data type - temp
pferland 9:e642e8f9ea37 195 int16_t temp = floor(value1*10 + 0.5f);
pferland 9:e642e8f9ea37 196 logInfo("Temp payload: %d", temp);
pferland 9:e642e8f9ea37 197 tx_data.push_back(uint8_t( 0xFF & (temp >> 8)));
pferland 9:e642e8f9ea37 198 tx_data.push_back(uint8_t(0xFF & temp));
pferland 9:e642e8f9ea37 199
pferland 9:e642e8f9ea37 200
pferland 9:e642e8f9ea37 201 tx_data.push_back(uint8_t(2)); // data id
pferland 9:e642e8f9ea37 202 tx_data.push_back(uint8_t(0x68)); // data type - humidity
pferland 9:e642e8f9ea37 203 temp = floor(value2 * 2.0f + 0.5f);
pferland 9:e642e8f9ea37 204 tx_data.push_back(uint8_t(0xFF & temp ));
pferland 9:e642e8f9ea37 205
pferland 4:142c85980a6f 206 logInfo("Temperature data %f", value1);
pferland 9:e642e8f9ea37 207 logInfo("Humidity data: %f", value2);
pferland 4:142c85980a6f 208
pferland 9:e642e8f9ea37 209 pressure_sensor->GetPressure(&value1);
pferland 9:e642e8f9ea37 210 logInfo("PRessure data: %f", value1);
pferland 9:e642e8f9ea37 211 // pressure is reported in mbar, cayenne wants it in 0.1 hPa
pferland 9:e642e8f9ea37 212 // 1mbar = 1 hPa
pferland 9:e642e8f9ea37 213 temp = floor(value1 * 100.0f + 0.5f);
pferland 9:e642e8f9ea37 214 tx_data.push_back(uint8_t(3)); // data id
pferland 9:e642e8f9ea37 215 tx_data.push_back(uint8_t(0x73)); // data type - pressure
pferland 9:e642e8f9ea37 216 temp = floor(value1 / 0.1f + 0.5f);
pferland 9:e642e8f9ea37 217 tx_data.push_back(uint8_t(0xFF & (temp >> 8)));
pferland 9:e642e8f9ea37 218 tx_data.push_back(uint8_t(0xFF & temp));
pferland 9:e642e8f9ea37 219
pferland 9:e642e8f9ea37 220
pferland 9:e642e8f9ea37 221 // Get accelerometer data
pferland 4:142c85980a6f 222 int32_t accel_vector[3];
pferland 9:e642e8f9ea37 223 // returns in mG
pferland 4:142c85980a6f 224 accelerometer->Get_X_Axes(accel_vector);
pferland 4:142c85980a6f 225 logInfo("Acclerometer Z axis: %d", accel_vector[2]);
pferland 4:142c85980a6f 226
pferland 9:e642e8f9ea37 227 tx_data.push_back(uint8_t(4)); // data id
pferland 9:e642e8f9ea37 228 tx_data.push_back(uint8_t(0x71)); // data type - accelerometer
pferland 9:e642e8f9ea37 229 for(int i=0; i<3; i++){
pferland 9:e642e8f9ea37 230 tx_data.push_back(uint8_t(0xFF & accel_vector[i]) >> 8);
pferland 9:e642e8f9ea37 231 tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
pferland 9:e642e8f9ea37 232 }
pferland 9:e642e8f9ea37 233
pferland 9:e642e8f9ea37 234 // Get gyro data
pferland 9:e642e8f9ea37 235 gyroscope->Get_G_Axes(accel_vector);
pferland 9:e642e8f9ea37 236 // gyro reports in milidegrees/sec, cayenne wants centidegrees/sec
pferland 9:e642e8f9ea37 237 tx_data.push_back(uint8_t(5)); //data id
pferland 9:e642e8f9ea37 238 tx_data.push_back(uint8_t(0x86)); // data type - gyrometer
pferland 9:e642e8f9ea37 239 for(int i=0; i<3; i++){
pferland 9:e642e8f9ea37 240 accel_vector[i] /= 10;
pferland 9:e642e8f9ea37 241 tx_data.push_back(uint8_t(0xFF & (accel_vector[i] >> 8)));
pferland 9:e642e8f9ea37 242 tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
pferland 9:e642e8f9ea37 243 }
pferland 9:e642e8f9ea37 244
pferland 9:e642e8f9ea37 245
pferland 0:9e88a9018fc0 246 send_data(tx_data);
pferland 0:9e88a9018fc0 247
pferland 0:9e88a9018fc0 248 // if going into deepsleep mode, save the session so we don't need to join again after waking up
pferland 0:9e88a9018fc0 249 // not necessary if going into sleep mode since RAM is retained
pferland 0:9e88a9018fc0 250 logInfo("saving network session to NVM");
pferland 0:9e88a9018fc0 251 dot->saveNetworkSession();
pferland 0:9e88a9018fc0 252
pferland 0:9e88a9018fc0 253
pferland 0:9e88a9018fc0 254 // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
pferland 6:9e6ac13de3e9 255 sleep_wake_rtc_only(deep_sleep);
pferland 0:9e88a9018fc0 256 //sleep_wake_interrupt_only(deep_sleep);
pferland 6:9e6ac13de3e9 257 //sleep_wake_rtc_or_interrupt(deep_sleep);
pferland 0:9e88a9018fc0 258
pferland 0:9e88a9018fc0 259 }
pferland 0:9e88a9018fc0 260
pferland 0:9e88a9018fc0 261 return 0;
pferland 0:9e88a9018fc0 262 }