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 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 }