Example of using the mDot UDK with the X-NUCLEO-IKS01A1 shield

Dependencies:   mDot_X_NUCLEO_IKS01A1 libmDot-dev-mbed5-deprecated

Hardware

Hardware List

Setup

  • Install the mDot on the developer board.
  • Install the IKS01A1 on the developer board.
  • If using a MTUDK-ST-CELL (white board) plug in the AC power adapter
  • Connect the microusb power to your development PC
    • if using a MTUDK-ST-CELL there are 2 microusb ports. Use the one closest to the serial port.

Your developer board should look like the following:

/media/uploads/pferland/udk_iks01a1.jpg

Software

This example program uses LoRa utility functions from Dot-Examples and the IKS01A1 library from ST Micro.

LoRa Configuration

Senet

By default this program is configured to connect to the Senet network. To connect to Senet you will need to register your mDot's Node ID with the Senet developer portal and change the network_key array in main.cpp.

Others

To connect to a different LoRa gateway change the arrays network_id and network_key. If you are using passphrases, edit the strings network_name and network_key, uncomment the function "update_ota_config_name_phrase" and comment out the function "update_ota_config_id_key".

Committer:
pferland
Date:
Tue Feb 14 20:36:21 2017 +0000
Revision:
11:1425f2e65663
Parent:
10:1e3e3ab9c29c
Updated libmDot-dev to latest

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