mDot project for Multitech and Explora worhshop
Dependencies: mDot_X_NUCLEO_IKS01A1 libmDot-dev-mbed5-deprecated
Fork of mDot-IKS01A1 by
main.cpp
- Committer:
- MDR
- Date:
- 2017-06-26
- Revision:
- 12:3466445b1ac6
- Parent:
- 10:1e3e3ab9c29c
File content as of revision 12:3466445b1ac6:
#include "mbed.h"
#include "mDot.h"
#include "x_nucleo_iks01a1.h"
#include "dot_util.h"
#include "RadioEvent.h"
#include <cmath>
// Add support to connect to Explora server
DigitalOut MyLed(D7,1);
// mDot UDK board demo with X-NUCLEO-IKS01A1 sensor card
// For more examples see the Dot-Examples project:
// https://developer.mbed.org/teams/MultiTech/code/Dot-Examples/
// This triggers an I2C issue in mbed-os 5.1.5
// Use any other revision to compile. (Tested with libmDot-dev/mbed-os 5.2.2
//#define SENET
#ifdef ACTILITY
// Network Id for Senet public network
static uint8_t network_id[] = {0xF0, 0x3D, 0x29,0xAC,0x71,0x00,0x00, 0x00};
// Register at or Sign in to http://portal.senetco.com/ and register your NodeId to receive your AppId
// {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B}
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};
static uint8_t frequency_sub_band = 0;
static bool public_network = true;
#elif defined(SENET)
// Network Id for Senet public network
static uint8_t network_id[] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
// Register at or Sign in to http://portal.senetco.com/ and register your NodeId to receive your AppId
// {0xD3,0x5A,0x30,0x60,0xA6,0x0D,0x9E,0xEA,0xD9,0xA1,0x19,0x61,0x4F,0x29,0x9E,0x5B}
static uint8_t network_key[] = {0x5F,0x7B,0x08,0x15,0x55,0x69,0x9A,0x2E,0x3C,0x91,0xE3,0xFE,0xF0,0x2A,0x77,0x79};
// 1 For Senet, configurable on your Conduit
static uint8_t frequency_sub_band = 1;
// True for Senet, false for your Conduit.
static bool public_network = true;
#else
//Replace with settings on your Conduit
static std::string network_name = "EcoLabTest";
static std::string network_passphrase = "EcoLabTest";
// 1 For Senet, configurable on your Conduit
static uint8_t frequency_sub_band = 1;
// True for Senet, false for your Conduit.
static bool public_network = true; // false;
#endif
static uint8_t ack = 0;
static uint8_t tx_datarate = mDot::SF_7;
// deepsleep consumes slightly less current than sleep
// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
// if deep_sleep == true, device will enter deepsleep mode
static bool deep_sleep = false;
mDot *dot = NULL;
int main()
{
Serial pc(USBTX, USBRX);
/* Instantiate the expansion board */
X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL, PC_1);
/* Retrieve the composing elements of the expansion board */
GyroSensor *gyroscope = mems_expansion_board->GetGyroscope();
MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer();
MagneticSensor *magnetometer = mems_expansion_board->magnetometer;
HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor;
PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor;
TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor;
TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor;
// Custom event handler for automatically displaying RX data
RadioEvent events;
pc.baud(115200);
#if defined(SENET) || defined(ACTILITY)
#if defined(SENET)
printf("Connect to SENET network\r\n");
#else
printf("Connect to ACTILITY network\r\n");
#endif
#else
printf("Connect to MultiConnect, network_name:%s, network_passphrase:%s\r\n", network_name,network_passphrase);
#endif
// LedD7 = 0;
// printf("Led ON\r\n");
// osDelay(2000);
// LedD7 = 1;
// printf("Led OFF\r\n");
// osDelay(2000);
// LedD7 = 0;
// printf("Led ON\r\n");
// osDelay(2000);
// LedD7 = 1;
// printf("Led OFF\r\n");
// osDelay(2000);
// LedD7 = 0;
// printf("Led ON\r\n");
/* Initialize mDot */
dot = mDot::getInstance();
//dot->setAdr(true);
mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL);
dot->setEvents(&events);
if (!dot->getStandbyFlag()) {
logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
// start from a well-known state
logInfo("defaulting Dot configuration");
dot->resetConfig();
dot->resetNetworkSession();
// update configuration if necessary
// in AUTO_OTA mode the session is automatically saved, so saveNetworkSession and restoreNetworkSession are not needed
if (dot->getJoinMode() != mDot::AUTO_OTA) {
logInfo("changing network join mode to AUTO_OTA");
if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) {
logError("failed to set network join mode to AUTO_OTA");
}
}
uint32_t current_tx_datarate = dot->getTxDataRate();
if (current_tx_datarate != tx_datarate) {
logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
logError("failed to set TX datarate to %u", tx_datarate);
}
}
// 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
// only one method or the other should be used!
// network ID = crc64(network name)
#if defined(SENET) || defined(ACTILITY)
// network KEY = cmac(network passphrase)
update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
#else
update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
#endif
// configure network link checks
// 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
// check the link every count packets
// declare the Dot disconnected after threshold failed link checks
// for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
update_network_link_check_config(3, 5);
// save changes to configuration
logInfo("saving configuration");
if (!dot->saveConfig()) {
logError("failed to save configuration");
}
// display configuration
display_config();
} else {
// restore the saved session if the dot woke from deepsleep mode
// useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
logInfo("restoring network session from NVM");
dot->restoreNetworkSession();
}
while (true) {
std::vector<uint8_t> tx_data;
// join network if not joined
if (!dot->getNetworkJoinStatus()) {
join_network();
}
// Payload structure for mydevices cayenne:
// 1 byte Data1 ID
// 1 Byte Data1 Type
// N Bytes Data1
// 1 byte data 2 ID
// 1 byte data 2 type
// n Bytes data 2
// ...
// formats:
// Temperature sensor:
/*
* IPSO: 3303
* LPP 103
* HEX: 67
* Data size: 2
* Resolution: 0.1 degres C
* Humidity sensor
* IPSO: 3304
* LPP: 104
* Hex: 68
* Datasize: 1
* Resolution: 0.5% unsigned
* Barometer/pressure sensor
* IPSO: 3315
* LPP: 115
* Hex: 73
* Datasize: 2
* Resolution 0.1hPa unsigned MSB
* Accelerometer
* IPSO: 3313
* LPP: 113
* Hex: 71
* Data size: 6
* Resolution: 0.001G signed MSB per axis
* Gyrometer
* IPSO: 3334
* LPP: 134
* Hex: 86
* Data size: 6
* Resolution: 0.01 degrees/s signed msb per axis
*/
//temp floats
float value1, value2;
// HTS221 Humidity sensor
temp_sensor1->GetTemperature(&value1);
humidity_sensor->GetHumidity(&value2);
//serialize data and append to packet
// Cayenne data: temperature; tag is 0x67, 2 bytes signed, 0.1 C/bit
tx_data.push_back(uint8_t(1)); // data id
tx_data.push_back(uint8_t(0x67)); // data type - temp
int16_t temp = floor(value1*10 + 0.5f);
//logInfo("Temp payload: %d", temp);
tx_data.push_back(uint8_t( 0xFF & (temp >> 8)));
tx_data.push_back(uint8_t(0xFF & temp));
tx_data.push_back(uint8_t(2)); // data id
tx_data.push_back(uint8_t(0x68)); // data type - humidity
temp = floor(value2 * 2.0f + 0.5f);
tx_data.push_back(uint8_t(0xFF & temp ));
logInfo("\r\n\r\nTemperature data %f", value1);
logInfo("Humidity data: %f", value2);
pressure_sensor->GetPressure(&value1);
logInfo("PRessure data: %f", value1);
// pressure is reported in mbar, cayenne wants it in 0.1 hPa
// 1mbar = 1 hPa
//temp = floor(value1 * 100.0f + 0.5f);
tx_data.push_back(uint8_t(3)); // data id
tx_data.push_back(uint8_t(0x73)); // data type - pressure
temp = floor(value1 / 0.1f + 0.5f);
tx_data.push_back(uint8_t(0xFF & (temp >> 8)));
tx_data.push_back(uint8_t(0xFF & temp));
// Get accelerometer data
int32_t accel_vector[3];
// returns in mG
accelerometer->Get_X_Axes(accel_vector);
logInfo("Acclerometer: %d,%d,%d", accel_vector[0], accel_vector[1], accel_vector[2]);
tx_data.push_back(uint8_t(4)); // data id
tx_data.push_back(uint8_t(0x71)); // data type - accelerometer
for(int i=0; i<3; i++){
tx_data.push_back(uint8_t(0xFF & (accel_vector[i] >> 8)));
tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
//logInfo("Acc: %d,%d,0x%02X, 0x%02X", i, accel_vector[i], accel_vector[2]);
}
// Get gyro data
gyroscope->Get_G_Axes(accel_vector);
logInfo("Gyroscope: %d,%d,%d", accel_vector[0], accel_vector[1], accel_vector[2]);
// gyro reports in milidegrees/sec, cayenne wants centidegrees/sec
tx_data.push_back(uint8_t(5)); //data id
tx_data.push_back(uint8_t(0x86)); // data type - gyrometer
for(int i=0; i<3; i++){
accel_vector[i] /= 10;
tx_data.push_back(uint8_t(0xFF & (accel_vector[i] >> 8)));
tx_data.push_back(uint8_t(0xFF & accel_vector[i]));
}
// print Raw Data
//logInfo("Temp raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[0], tx_data[1], tx_data[2], tx_data[3]);
//logInfo("Hum raw: 0x%02X, 0x%02X, 0x%02X",tx_data[4], tx_data[5], tx_data[6]);
//logInfo("Pres raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[7], tx_data[8], tx_data[9], tx_data[10]);
//logInfo("Acc raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[11], tx_data[12], tx_data[13], tx_data[14], tx_data[15], tx_data[16], tx_data[17], tx_data[18]);
//logInfo("Gir raw: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X",tx_data[19], tx_data[20], tx_data[21], tx_data[22], tx_data[23], tx_data[24], tx_data[25], tx_data[26]);
send_data(tx_data);
if(deep_sleep){
// if going into deepsleep mode, save the session so we don't need to join again after waking up
// not necessary if going into sleep mode since RAM is retained
logInfo("saving network session to NVM");
dot->saveNetworkSession();
}
// ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
// mdr sleep_wake_rtc_only(deep_sleep);
//sleep_wake_interrupt_only(deep_sleep);
//sleep_wake_rtc_or_interrupt(deep_sleep);
uint32_t delay_s = dot->getNextTxMs() / 1000;
if (delay_s < 5) {
delay_s = 5;
}
logInfo("waiting %d", delay_s);
osDelay(delay_s*1000);
logInfo("application resume", deepsleep ? "execute from beginning" : "resume");
}
return 0;
}
