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:
Fri Jan 26 17:39:50 2018 +0000
Revision:
12:63e90d375afd
Parent:
10:1e3e3ab9c29c
Child:
13:e165a137c3af
Updated to IKS01A2 and TTN support

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