Provide working example for LoRa 'Sensor-to-Cloud' demonstration using MultiTech LoRa Starter Kit and Telit Data and Cloud Platform Services Offerings

Dependencies:   DOGS102 GpsParser ISL29011 MMA845x MPL3115A2 MTS-Serial NCP5623B mDot_X_NUCLEO_IKS01A1 libmDot-mbed5

Revision:
0:e516bb631931
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_mems.cpp	Thu Jul 13 19:03:50 2017 +0000
@@ -0,0 +1,1496 @@
+/*================================================================================
+ *
+ * CLASIFICATION:     **** PUBLIC RELEASE AS-IS APPLICATION EXAMPLE ****
+ *
+ * SOURCE FILE NAME:  main.cpp
+ *
+ * DESCRIPTIVE NAME:  MBED Source for MultiTech mDot, EVB, and MDOT-BOX Devices
+ *
+ * COPYRIGHT:         Copyright 2014-2017, Telit
+ *
+ *                    LICENSED MATERIAL - PROGRAM PROPERTY OF TELIT
+ *                    REFER TO TELIT COPYRIGHT INSTRUCTION
+ *
+** WEB SITE:          www.telit.com
+ *
+ * WRITTEN BY:        Eliott Fersko and John Keever
+ *
+ * DATE:              April 17, 2017
+ *
+ * VERSION:           1.04
+ *
+ * FUNCTION:          Provide working example for LoRa 'Sensor-to-Cloud'
+ *                    Demonstration using MultiTech LoRa Starter Kit and
+ *                    Telit Data and Cloud Platform Services Offerings
+ *
+ * SOURCE FILE TYPE:  MBED C++
+ *
+ * FUNCTIONS/ENTRY POINTS:  main
+ *
+ * INPUT  = None.
+ * OUTPUT = None.
+ *
+ * EXIT-NORMAL = N/A
+ * EXIT-ERROR  = N/A
+ *
+ * EXTERNAL REFERENCES = None.
+ *
+ * EXTERNAL FUNCTIONS = None.
+ *
+ * CONTROL BLOCKS = None.
+ *
+ *================================================================================*/
+/*                              LEGAL DISCLAIMER                                  */
+/*================================================================================
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Neither the name of ILS Technology nor Telit nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ *================================================================================*/
+/*                                 CHANGE LOG                                     */
+/*================================================================================*/
+/*          |Changed |          |                                                 */
+/*  Date    |   by   |Version ID| Comments                                        */
+/*----------+--------+----------+-------------------------------------------------*/
+/*04-12-2017|JEK     |V1.00     |Original Version - mDot, EVB, MDOT-BOX           */
+/*04-14-2017|JEK     |V1.01     |Added IRQ Handlers - SW1/SW2 (Threads?)          */
+/*04-17-2017|JEK     |V1.02     |Added Binary LoRa Payload Message Framing Type   */
+/*04-24-2017|EMF     |V1.03     |Updated Libraries                                */
+/*05-10-2017|EMF     |V1.04     |Added support for ST-Micro MEMS Sensor Shield    */
+/*05-30-2017|EMF     |V1.05     |Added GPS support for MDOT-BOX				      */
+/*================================================================================*/
+/*NOTE:  Please keep the change log up to date!!!                                 */
+/*================================================================================*/
+
+#include "mbed.h"
+#include "MMA845x.h"
+#include "MPL3115A2.h"
+#include "ISL29011.h"
+#include "NCP5623B.h"
+#include "DOGS102.h"
+#include "font_6x8.h"
+#include "MultiTech_Logo.h"
+#include "mDot.h"
+#include "rtos.h"
+#include "GPSPARSER.h"
+#include "MTSSerial.h"
+#include "x_nucleo_iks01a1.h"
+
+#include <cmath>
+#include <string>
+#include <vector>
+#include <ctime>
+#include <Ticker.h>
+
+#define CALL_METH(obj, meth, param, ret) ((obj == NULL) ?       \
+                      ((*(param) = (ret)), 0) : \
+                      ((obj)->meth(param))      \
+                      )
+
+//Length of time between data publishes
+const int CYCLE_TIME = 5000;
+
+enum LED1_COLOR {
+    RED = 0,
+    GREEN = 1
+};
+
+namespace {
+    const int MS_INTERVALS = 1000;
+}
+
+/*
+ * union for converting from 32-bit to 4 8-bit values
+ */
+union convert32 {
+    int32_t f_s;        // convert from signed 32 bit int
+    uint32_t f_u;       // convert from unsigned 32 bit int
+    uint8_t t_u[4];     // convert to 8 bit unsigned array
+};
+
+typedef struct {
+    int32_t AXIS_X;
+    int32_t AXIS_Y;
+    int32_t AXIS_Z;
+} AxesRaw_TypeDef;
+
+
+/*
+ * union for converting from 16- bit to 2 8-bit values
+ */
+union convert16 {
+    int16_t f_s;        // convert from signed 16 bit int
+    uint16_t f_u;       // convert from unsigned 16 bit int
+    uint8_t t_u[2];     // convert to 8 bit unsigned array
+};
+
+//DigitalIn mDot02(PA_2);                       //  GPIO/UART_TX
+//DigitalOut mDot03(PA_3);                      //  GPIO/UART_RX
+//DigitalIn mDot04(PA_6);                       //  GPIO/SPI_MISO
+//DigitalIn mDot06(PA_8);                       //  GPIO/I2C_SCL
+//DigitalIn mDot07(PC_9);                       //  GPIO/I2C_SDA
+
+InterruptIn mDot08(PA_12);                      //  GPIO/USB       PB S1 on EVB
+InterruptIn mDot09(PA_11);                      //  GPIO/USB       PB S2 on EVB
+
+//DigitalIn mDot11(PA_7);                       //  GPIO/SPI_MOSI
+
+InterruptIn mDot12(PA_0);                       //  GPIO/UART_CTS  PRESSURE_INT2 on EVB
+DigitalOut mDot13(PC_13,1);                     //  GPIO           LCD_C/D
+InterruptIn mDot15(PC_1);                       //  GPIO           LIGHT_PROX_INT on EVB
+InterruptIn mDot16(PA_1);                       //  GPIO/UART_RTS  ACCEL_INT2 on EVB
+DigitalOut mDot17(PA_4,1);                      //  GPIO/SPI_NCS   LCD_CS on EVB
+
+// DigitalIn mDot18(PA_5);                          //  GPIO/SPI_SCK
+// DigitalInOut mDot19(PB_0,PIN_INPUT,PullNone,0);  //  GPIO         PushPull LED Low=Red High=Green set MODE=INPUT to turn off
+// AnalogIn mDot20(PB_1);                           //  GPIO         Current Sense Analog in on EVB
+
+Serial debugUART(PA_9, PA_10);                  // mDot debug UART
+MTSSerial mDotUART(PA_2,PA_3);                  // mDot external UART mDot02 and mDot03
+I2C mDoti2c(PC_9,PA_8);                         // mDot External I2C mDot6 and mDot7
+SPI mDotspi(PA_7,PA_6,PA_5);                    // mDot external SPI mDot11, mDot4, and mDot18
+AnalogIn current_sensor(PB_1);                  // EVB - GPIO - Current Sensor Analog Input
+
+/* **** replace these values with the proper public or private network settings ****
+ * config_network_nameand config_network_pass are for private networks.
+ */
+
+//static std::string config_network_name = "telitlora";
+//static std::string config_network_pass = "telitpass";
+//static uint8_t config_frequency_sub_band = 7;
+
+
+
+static volatile bool timer_irq_triggered = false;
+static volatile bool ff_irq_triggered = false;
+
+
+static std::string config_network_name = "MTCDT-19020718";
+static std::string config_network_pass = "MTCDT-19020718";
+static uint8_t config_frequency_sub_band = 1;
+
+
+/*
+static std::string config_network_name = "MTCDT-19186804";
+static std::string config_network_pass = "MTCDT-19186804";
+static uint8_t config_frequency_sub_band = 1;
+*/
+
+/*  config_app_id and config_app_key are for public networks.
+static uint8_t app_id[8] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
+std::vector<uint8_t> config_app_id;
+static uint8_t app_key[16] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0C,0x0D};
+std::vector<uint8_t> config_app_key;
+*/
+
+uint8_t result;
+uint8_t data;
+uint8_t sf_val = mDot::SF_7;
+uint8_t pwr_val = 11; // dBm
+uint8_t swp_pwr;
+uint8_t swp_sf;
+
+// max size of text string for 6x8 font. Set to 12 if using 8x8 font
+char txtstr[17];
+
+int32_t mdot_ret;
+int32_t join_delay;
+
+osThreadId mainThreadID;
+
+// flags for push button debounce code
+bool pb1_low = false;
+bool pb2_low = false;
+bool toggle_text = false;
+bool sw1_state = false;
+bool sw2_state = false;
+
+uint32_t num_whole;
+uint16_t num_frac;
+
+uint32_t pressure;
+double current;
+
+bool exit_program = false;
+
+//EVB sensor variables
+MMA845x_DATA accel_data;
+MPL3115A2_DATA baro_data;
+uint16_t  lux_data;
+MMA845x* evbAccel;
+MPL3115A2* evbBaro;
+ISL29011* evbAmbLight;
+NCP5623B* evbBackLight;
+DOGS102* evbLCD;
+
+//MEMS sensor variables
+X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL, PC_1);
+static Ticker ticker;
+GyroSensor *memsGyro;
+MotionSensor *memsAccel;
+MagneticSensor *memsMag;
+HumiditySensor *memsHumidity;
+PressureSensor *memsPressure;
+TempSensor *memsTemp1;
+TempSensor *memsTemp2;
+unsigned int ret = 0;
+char buffer1[32];
+char buffer2[32];
+char buffer3[32];
+char buffer4[32];
+float temp_value, humid_value, pressure_value;
+int16_t int_temp_value, int_humid_value, int_pressure_value;
+int32_t accel_vector[3];
+int32_t mag_vector[3];
+int32_t gyro_vector[3];
+
+//MDOT-BOX sensor variables
+GPSPARSER::latitude lat_data;
+GPSPARSER::longitude lng_data;
+NCP5623B* led_cont;
+MTSSerial gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048);
+GPSPARSER* mdot_gps;
+float lat = 0;
+float lng = 0;
+bool sat_lock = 0;
+
+mDot* mdot_radio;
+Mutex mdot_mutex;
+
+
+
+
+
+
+
+
+
+
+convert32 convertl;
+convert16 converts;
+
+void pb1ISR(void);
+void pb2ISR(void);
+void pb1_debounce(void const *args);
+void pb2_debounce(void const *args);
+
+MPL3115A2* resetBaro(const MPL3115A2* oldBaro);
+void log_error(mDot* dot, const char* msg, int32_t retval);
+int32_t sendString(const std::string text);
+bool writeValueOrError();
+
+const int FAIL_MAX=15;
+int failtime=FAIL_MAX;
+int cycle_cnt = 0;
+
+char sensor_text[64];
+char lora_temp_string[16];
+char lora_alt_string[16];
+char lora_press_string[16];
+char lora_light_string[16];
+char lora_current_string[16];
+char lora_humid_string[16];
+char lora_lat_string[16];
+char lora_lng_string[16];
+
+bool bHasGPS = false;
+bool bHasACC = false;
+bool bHasLCD = false;
+
+/*** Helper Functions ------------------------------------------------------------ ***/
+/* print floats & doubles */
+static char *printDouble(char* str, double v, int decimalDigits=2)
+{
+  int i = 1;
+  int intPart, fractPart;
+  int len;
+  char *ptr;
+
+  /* prepare decimal digits multiplicator */
+  for (;decimalDigits!=0; i*=10, decimalDigits--);
+
+  /* calculate integer & fractinal parts */
+  intPart = (int)v;
+  fractPart = (int)((v-(double)(int)v)*i);
+
+  /* fill in integer part */
+  sprintf(str, "%i.", intPart);
+
+  /* prepare fill in of fractional part */
+  len = strlen(str);
+  ptr = &str[len];
+
+  /* fill in leading fractional zeros */
+  for (i/=10;i>1; i/=10, ptr++) {
+      if(fractPart >= i) break;
+      *ptr = '0';
+  }
+
+  /* fill in (rest of) fractional part */
+  sprintf(ptr, "%i", fractPart);
+
+  return str;
+}
+/*===================================================================================
+Main Program Logic - Entry
+===================================================================================*/
+int main()
+{
+    std::vector<uint8_t> mdot_data;
+    std::vector<uint8_t> mdot_EUI;
+    uint16_t i = 0;
+    uint8_t id1 = 0;
+
+    debugUART.baud(9600);
+
+    printf ("Starting Application...\r\n");
+
+    mainThreadID = osThreadGetId();
+
+    printf("Begin I2C/SPI Device Initialization...\r\n");
+
+
+    // Use Magnetometer As MEMS sensor shield Enumeration...
+
+    memsMag = mems_expansion_board->magnetometer;
+    CALL_METH(memsMag, ReadID, &id1, 0x0);
+    printf("Magnetometer ID value = %i \n\r", id1);
+
+    //chcek for default magnetomter ID 61...
+    if(id1 == 61)
+    {
+        printf("Magnetometer Found - MEMS sensor shield detected...\r\n");
+        bHasACC = true;
+
+        // Initialize Integrated Sensors...
+        printf("Instantiate Magnetometer...\r\n");
+        memsMag = mems_expansion_board->magnetometer;
+
+        printf("Instantiate Accelerometer...\r\n");
+        memsAccel = mems_expansion_board->GetAccelerometer();
+
+        printf("Instantiate Gyroscope...\r\n");
+        memsGyro = mems_expansion_board->GetGyroscope();
+
+        printf("Instantiate Barometric Pressure Sensor...\r\n");
+        memsPressure = mems_expansion_board->pt_sensor;
+
+        printf("Instantiate Temperature Pressure Sensor...\r\n");
+        memsTemp1 = mems_expansion_board->ht_sensor;
+        memsTemp2 = mems_expansion_board->pt_sensor;
+
+        printf("Instantiate Humidity Sensor...\r\n");
+        memsHumidity = mems_expansion_board->ht_sensor;
+
+    }
+
+
+    else
+    {
+        printf("No Magnetometer Found...\r\n");
+        // Use Accelerometer As MDOT-BOX/EVB Enumeration...
+        printf("Instantiate Accelerometer...\r\n");
+        evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS);
+
+        printf("Accelerometer Status = %d\r\n", evbAccel->getStatus());
+        printf("Accelerometer who_am_i value = %x \n\r", evbAccel->getWhoAmI());
+
+        if( (evbAccel->getStatus() == 1) && (evbAccel->getWhoAmI() == 0) )
+        {
+            printf("No Accelerometer Found - Basic mDot, Not MDOT-BOX or EVB...\r\n");
+        }
+
+        else
+        {
+            printf("Accelerometer Found - Either MDOT-BOX or EVB...\r\n");
+            bHasACC = true;
+
+        // Initialize Integrated Sensors...
+            printf("Instantiate Barometric Pressure Sensor...\r\n");
+            evbBaro = new MPL3115A2(mDoti2c);       // Setup Barometric Sensor
+            printf("Barometric Sensor Status = %d\r\n", evbBaro->getStatus());
+            printf("Barometer who_am_i check = %d\r\n", evbBaro->testWhoAmI());
+            printf("Barometer who_am_i check = %s\r\n", evbBaro->testWhoAmI() ? "TRUE" : "FALSE");
+
+            if( evbBaro->getStatus() == 0 ) printf("No Barometric Sensor...\r\n");
+
+            printf("Instantiate Ambient Light Sensor...\r\n");
+            evbAmbLight = new ISL29011(mDoti2c);    // Setup Ambient Light Sensor
+
+            // Setup the Accelerometer for 8g range, 14 bit resolution, Noise reduction off, sample rate 1.56 Hz
+            // Normal oversample mode, High pass filter off
+            evbAccel->setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF, MMA845x::DR_1_56,MMA845x::OS_NORMAL,MMA845x::HPF_OFF );
+
+            // Setup the Barometric sensor for post processed Ambient pressure, 4 samples per data acquisition.
+            // and a sample taken every second when in active mode
+            evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+
+            // Setup the Ambient Light Sensor for continuous Ambient Light Sensing, 16 bit resolution, and 16000 lux range
+            evbAmbLight->setMode(ISL29011::ALS_CONT);
+            evbAmbLight->setResolution(ISL29011::ADC_16BIT);
+            evbAmbLight->setRange(ISL29011::RNG_16000);
+
+            // Set the accelerometer for active mode
+            evbAccel->activeMode();
+
+            // Clear the min-max registers in the Barometric Sensor
+            evbBaro->clearMinMaxRegs();
+
+            // Support Integrated LCD Display
+            bHasLCD = true;
+
+            printf("Instantiate BackLight and LCD Display...\r\n");
+            evbBackLight = new NCP5623B(mDoti2c);               // setup backlight and LED 2 driver chip
+
+            evbLCD = new DOGS102(mDotspi, mDot17, mDot13);      // setup LCD Display
+
+            printf("Font Table Address:  %p\r\n",&font_6x8);
+            printf("Bitmap Logo Address:  %p\r\n",&MultiTech_Logo);
+
+            // Setup and display logo on LCD
+            evbLCD->startUpdate();
+            evbLCD->writeBitmap(0,0,MultiTech_Logo);
+
+            sprintf(txtstr,"MTDOT-EVB");
+            evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr));
+            sprintf(txtstr,"Sensor Demo");
+            evbLCD->writeText(18,4,font_6x8,txtstr,strlen(txtstr));
+
+            evbLCD->endUpdate();
+
+            printf("Setup PushButton Interface Handlers...\r\n");
+
+            printf("Launching Debounce Threads...\r\n");
+            Thread thread_1(pb1_debounce);
+            Thread thread_2(pb2_debounce);
+            printf("Debounce Threads Launched...\r\n");
+
+            printf("Set SW1/SW2 IRQs...\r\n");
+            // Setup SW1 as Data rate and power out select
+            mDot08.disable_irq();
+            mDot08.fall(&pb1ISR);
+
+            // need to call this function after rise or fall because rise/fall sets mode to PullNone
+            mDot08.mode(PullUp);
+            mDot08.enable_irq();
+
+            // Setup SW2 as send PING
+            mDot09.disable_irq();
+            mDot09.fall(&pb2ISR);
+
+            // need to call this function after rise or fall because rise/fall sets mode to PullNone
+            mDot09.mode(PullUp);
+            mDot09.enable_irq();
+
+            // Setting other InterruptIn pins with Pull Ups
+            mDot12.mode(PullUp);
+            mDot15.mode(PullUp);
+            mDot16.mode(PullUp);
+
+            printf("SW1/SW2 IRQs Set...\r\n");
+        }
+    }
+
+    printf("I2C/SPI Device Initialization Complete...\r\n");
+
+    printf("\r\nSetup mDot Radio Communications...\r\n");
+
+    // get a mDot handle
+    mdot_radio = mDot::getInstance();
+
+    if (mdot_radio)
+    {
+        // reset to default config so we know what state we're in
+        mdot_mutex.lock();  // lock mdot before setting configuration
+        mdot_radio->resetConfig();
+
+        // Setting up LED1 as activity LED
+        mdot_radio->setActivityLedPin(PB_0);
+        mdot_radio->setActivityLedEnable(true);
+
+        // Read node ID
+        mdot_EUI = mdot_radio->getDeviceId();
+        printf("mDot EUI = ");
+
+        for(i=0; i<mdot_EUI.size(); i++) {
+            printf("%02x ", mdot_EUI[i]);
+        }
+        printf("\r\n");
+
+        // Setting up the mDot with network information.
+
+        // This call sets up private or public mode on the MTDOT. Set the function to true if
+        // connecting to a public network
+        printf("Setting Private Network Mode...\r\n");
+        if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set Public Network Mode", mdot_ret);
+        }
+
+        // Frequency sub-band is valid for NAM only and for Private networks should be set to a value
+        // between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
+        // This function can be commented out for EU networks
+        printf("Setting Frequency Sub-Band...\r\n");
+        if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set Frequency Sub-Band", mdot_ret);
+        }
+
+        // Setting TX power for radio. Max allowed is +14dBm for EU and +20 dBm for NAM. Default is +11 dBm
+        printf("Setting TX Power Level to %2d dBm...\r\n", pwr_val);
+        if ((mdot_ret = mdot_radio->setTxPower(pwr_val)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set TX Power Level", mdot_ret);
+        }
+
+        // Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_10
+        printf("Setting TX data rate to SF_7...\r\n");
+        if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set TX Data Rate", mdot_ret);
+        }
+
+        // Configure Pushbutton Display Labels...
+        sprintf(txtstr,"SF=%2d PWR=%2d",sf_val,pwr_val);
+        if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+        printf("%s\r\n",txtstr);
+
+
+        // Setting Packet ACK to 1 try.
+
+        printf("Setting Packet Retry to 1...\r\n");
+        if ((mdot_ret = mdot_radio->setAck(1)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set Packet Retry\r\n", mdot_ret);
+        }
+
+
+        // setNetworkName is used for private networks.
+        // Use setNetworkID(AppID) for public networks
+
+        // config_app_id.assign(app_id,app_id+7);
+
+        printf("Setting Network Name...\r\n");
+        if ((mdot_ret = mdot_radio->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
+        // if ((mdot_ret = mdot_radio->setNetworkID(config_app_id)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set Network Name", mdot_ret);
+        }
+
+        // setNetworkPassphrase is used for private networks
+        // Use setNetworkKey for public networks
+
+        // config_app_key.assign(app_key,app_key+15);
+
+        printf("Setting Network Password...\r\n");
+        if ((mdot_ret = mdot_radio->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
+        // if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to set Network Password", mdot_ret);
+        }
+
+        mdot_mutex.unlock();        // unlock mdot mutex before join attempt so SW1 can work
+
+        // attempt to join the network
+        printf("Joining LoRa Network...\r\n");
+        do {
+            mdot_mutex.lock();      // lock mdot mutex before join attempt
+            mdot_ret = mdot_radio->joinNetwork();
+            mdot_mutex.unlock();        // unlock mdot mutex after join attempt so SW1 can work
+
+            if (mdot_ret != mDot::MDOT_OK)
+            {
+                log_error(mdot_radio,"ERROR: Failed to Join Network:", mdot_ret);
+
+                if (toggle_text)
+                    sprintf(txtstr," > Join Failed <");
+                else
+                    sprintf(txtstr," < Join Failed >");
+
+                if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+                if (mdot_radio->getFrequencyBand() == mDot::FB_868)
+                {
+                    join_delay = mdot_radio->getNextTxMs();
+                }
+                else
+                {
+                    join_delay = 10;
+                }
+                printf("Join Delay = %lu\r\n",join_delay);
+                osDelay(join_delay + 1);
+                toggle_text = !toggle_text;
+            }
+
+            /*
+             * Setting TX power and Data Rate for radio just in case user requested by SW2
+             */
+            mdot_mutex.lock();      // lock mdot mutex before setting change
+            mdot_radio->setTxPower(pwr_val);
+            mdot_radio->setTxDataRate(sf_val);
+            mdot_mutex.unlock();        // unlock mdot mutex after settings change so SW1 can work
+
+        } while (mdot_ret != mDot::MDOT_OK);
+
+        printf("Successfully Joined LoRa Network...\r\n");
+
+        sprintf(txtstr,"*Network Joined*");
+        if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+    }
+    else
+    {
+        printf("ERROR:  Unable to Join LoRa Network...\r\n");
+        sprintf(txtstr,"Radio Init Failed!");
+        if( bHasLCD ) evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+        printf("%s\r\n",txtstr);
+        exit(1);
+    }
+
+    // Check for MDOT-BOX Configuration (GPS)
+
+    if( bHasACC && bHasLCD )
+    {
+        printf("Instantiate GPS...\r\n");
+        mdot_gps = new GPSPARSER(&gps_serial, led_cont);
+		osDelay(1000);
+        if(!mdot_gps->gpsDetected())
+        {
+            printf(">>>> No GPS Detected... Not an MDOT-BOX, EVB Identified\r\n");
+
+            sprintf(txtstr,"*No GPS Detected*");
+            if( bHasLCD ) evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+        }
+        else
+        {
+            // main_single = main_sweep = false;
+            printf(">>>> GPS Detected... MDOT-BOX Identified\r\n");
+            sprintf(txtstr,"*GPS Detected*");
+            if( bHasLCD ) evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+            bHasGPS = true;
+        }
+    }
+
+    printf("Initialization/Configuration Completed...\r\n");
+
+    osDelay(1500);
+    if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
+
+    // sets LED2 to 50% max current
+    if( bHasLCD ) evbBackLight->setLEDCurrent(16);
+
+
+    // Check for PB1 press during network join attempt
+    /*
+    if (exit_program)
+    {
+        printf("PB1 Pressed, Exiting Program...\r\n");
+        if( bHasLCD ) evbLCD->clearBuffer();
+        sprintf(txtstr,"Exiting Program");
+        if( bHasLCD ) evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+        exit(1);
+    }
+    */
+
+    // Enter Main Data Acquisition Loop...
+    printf("Processing Data Acquisition Scan Loop...\r\n");
+
+    i = 0;
+    cycle_cnt = 100;
+
+    if( bHasLCD ) evbLCD->clearBuffer();
+
+    do
+    {
+        //BOX
+        if(bHasGPS)
+        {
+            //GPS code
+                if (mdot_gps->getLockStatus())
+                {
+				
+                    //Retrieve and print out Latitude data
+                	lat_data = mdot_gps->getLatitude();
+                	sat_lock = 1;
+                	//Conversion from DMS to decimal 
+                	if(lat_data.degrees>0)
+                	{
+                		lat = (lat_data.degrees + lat_data.minutes/60.0 + lat_data.seconds/600000.0);
+                	}
+                	else
+                	{
+                		lat = (lat_data.degrees - lat_data.minutes/60.0 - lat_data.seconds/600000.0);
+                	}
+                	sprintf(txtstr, "Lat = %.7f",lat);
+                	sprintf(lora_lat_string,"%.7f",lat);
+                	evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+					//Retrieve and print out Longitude data
+                	lng_data = mdot_gps->getLongitude();
+                	//Conversion from DMS to decimal 
+                	if(lng_data.degrees>0)
+                	{
+                		lng = (lng_data.degrees + lng_data.minutes/60.0 + lng_data.seconds/600000.0);
+                	}
+                	else
+                	{
+                		lng = (lng_data.degrees - lng_data.minutes/60.0 - lng_data.seconds/600000.0);
+                	}
+                	sprintf(txtstr, "Lng = %.7f",lng);
+                	sprintf(lora_lng_string,"%.7f",lng);
+                	evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+                }
+                else
+                {
+					//reset sat_lock, lat, and lng while device doesn't have lock
+                    sprintf(txtstr," > no GPS lock <  ");
+                    evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+                    evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+                    printf("%s \r\n",txtstr);
+                    sat_lock = 0;
+                    lat = 0;
+                    lng = 0;
+                    sprintf(lora_lat_string, "%f",lat);
+                	sprintf(lora_lng_string, "%f",lng);
+
+
+                }
+            
+            // Check Accelerometer XYZ data ready bit to see if acquisition complete
+            failtime = FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbAccel->getStatus();
+                failtime--;
+            } while ((result & MMA845x::XYZDR) == 0 && failtime > 0);
+
+            if (failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and print out accelerometer data
+
+            accel_data = evbAccel->getXYZ();
+            sprintf(txtstr, "Accel-X = %d", accel_data._x);
+            evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
+            sprintf(txtstr, "Accel-Y = %d", accel_data._y);
+            evbLCD->writeText(0,1,font_6x8,txtstr,strlen(txtstr));
+            sprintf(txtstr, "Accel-Z = %d", accel_data._z );
+            evbLCD->writeText(0,2,font_6x8,txtstr,strlen(txtstr));
+
+            // Trigger a Barometric Pressure Reading
+            evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+            evbBaro->triggerOneShot();
+
+            // Test Barometer Device, Check to see if acquisition is complete
+            failtime=FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbBaro->getStatus();
+                failtime--;
+            } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
+
+            if(failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and Display Barometric Pressure
+            pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
+            num_whole = pressure >> 2;                  // 18 bit integer significant
+            num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
+
+            // If failtime reached 0 , indicates that the result might be junk.
+            sprintf(txtstr,"Press=%ld.%01d Pa", num_whole, num_frac/10);
+
+            pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
+            num_whole = pressure >> 2;                  // 18 bit integer significant
+            num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
+
+            writeValueOrError();                        // will write to  lorapresstring and txtstr
+
+            // Trigger a Altitude reading
+            // evbBaro->setAltitudeCalib(101);
+            evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+            // evbBaro->setAltitudeCalib(101);
+            evbBaro->triggerOneShot();
+
+            // Test barometer device status to see if acquisition is complete
+            failtime=FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbBaro->getStatus();
+                failtime--;
+            } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
+
+            if (failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and Display Altimeter Reading
+            baro_data = evbBaro->getAllData(false);
+            baro_data._baro /= 4096;                                    // convert 32 bit signed to 20 bit signed value
+            num_whole = baro_data._baro / 16;                           // 18 bit signed significant integer (JEK Added 60 as SWAG Offset for Boca)
+            num_frac = (baro_data._baro & 0xF) * 625 / 100;             // 4 bit fractional .0625 per bit
+            sprintf(txtstr,"Alti=%ld.%03d m", num_whole, num_frac);
+            sprintf(lora_alt_string,"%ld.%03d", num_whole, num_frac);
+            evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Temperature Reading
+            num_whole = baro_data._temp / 16;                           // 8 bit signed significant integer
+            num_frac = (baro_data._temp & 0x0F) * 625 / 100;            // 4 bit fractional .0625 per bit
+            sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac);
+            sprintf(lora_temp_string,"%ld.%03d", num_whole, num_frac);
+            //evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Ambient Light Level
+            lux_data = evbAmbLight->getData();
+            num_whole = lux_data * 24 / 100;        // 16000 lux full scale .24 lux per bit
+            num_frac = lux_data * 24 % 100;
+            sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac );
+            sprintf(lora_light_string, "%ld.%02d", num_whole, num_frac );
+            //evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Current Sensor Level (EVB Analog Input)
+            current = (double) current_sensor * 65535.0;
+            sprintf(lora_current_string, "%d", (int) current);
+
+            // Handle Pushbutton #1 (SW1) - This should be handled by the 'pb1_debounce' thread.
+            if( pb1_low )
+            {
+                sw1_state = !sw1_state;
+                if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,0);  // enable LED2 on EVB and set to 0% PWM
+
+                sprintf(txtstr,"PB1 Press-SW1: %d", sw1_state);
+                if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                printf("%s \r\n",txtstr);
+
+                pb1_low = false;
+            }
+
+            // Handle Pushbutton #2 (SW2) - This should be handled by the 'pb2_debounce' thread.
+             if( pb2_low )
+            {
+                sw2_state = !sw2_state;
+                if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
+
+                sprintf(txtstr,"PB2 Press-SW2: %d", sw2_state);
+                if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                printf("%s \r\n",txtstr);
+
+                pb2_low = false;
+            }
+        }
+        
+        //EVB
+        else if( bHasACC && bHasLCD )
+        {
+            // Check Accelerometer XYZ data ready bit to see if acquisition complete
+            failtime = FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbAccel->getStatus();
+                failtime--;
+            } while ((result & MMA845x::XYZDR) == 0 && failtime > 0);
+
+            if (failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and print out accelerometer data
+            accel_data = evbAccel->getXYZ();
+            sprintf(txtstr, "Accel-X = %d", accel_data._x);
+            evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr));
+            sprintf(txtstr, "Accel-Y = %d", accel_data._y);
+            evbLCD->writeText(0,1,font_6x8,txtstr,strlen(txtstr));
+            sprintf(txtstr, "Accel-Z = %d", accel_data._z );
+            evbLCD->writeText(0,2,font_6x8,txtstr,strlen(txtstr));
+
+            // Trigger a Barometric Pressure Reading
+            evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+            evbBaro->triggerOneShot();
+
+            // Test Barometer Device, Check to see if acquisition is complete
+            failtime=FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbBaro->getStatus();
+                failtime--;
+            } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
+
+            if(failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and Display Barometric Pressure
+            pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
+            num_whole = pressure >> 2;                  // 18 bit integer significant
+            num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
+
+            // If failtime reached 0 , indicates that the result might be junk.
+            sprintf(txtstr,"Press=%ld.%01d Pa", num_whole, num_frac/10);
+
+            pressure = evbBaro->getBaroData() >> 12;    // convert 32 bit signed to 20 bit unsigned value
+            num_whole = pressure >> 2;                  // 18 bit integer significant
+            num_frac = (pressure & 0x3) * 25;           // 2 bit fractional  0.25 per bit
+
+            writeValueOrError();                        // will write to  lorapresstring and txtstr
+
+            // Trigger an Altitude reading
+            // evbBaro->setAltitudeCalib(101);
+            evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+            // evbBaro->setAltitudeCalib(101);
+            evbBaro->triggerOneShot();
+
+            // Test barometer device status to see if acquisition is complete
+            failtime=FAIL_MAX;
+            do
+            {
+                osDelay(100);           // allows other threads to process
+                result = evbBaro->getStatus();
+                failtime--;
+            } while ((result & MPL3115A2::PTDR) == 0 && failtime > 0 );
+
+            if (failtime==0)
+            {
+                evbBaro=resetBaro(evbBaro);
+                continue;
+            }
+
+            // Retrieve and Display Altimeter Reading
+            baro_data = evbBaro->getAllData(false);
+            baro_data._baro /= 4096;                                    // convert 32 bit signed to 20 bit signed value
+            num_whole = baro_data._baro / 16;                           // 18 bit signed significant integer (JEK Added 60 as SWAG Offset for Boca)
+            num_frac = (baro_data._baro & 0xF) * 625 / 100;             // 4 bit fractional .0625 per bit
+            sprintf(txtstr,"Alti=%ld.%03d m", num_whole, num_frac);
+            sprintf(lora_alt_string,"%ld.%03d", num_whole, num_frac);
+            evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Temperature Reading
+            num_whole = baro_data._temp / 16;                           // 8 bit signed significant integer
+            num_frac = (baro_data._temp & 0x0F) * 625 / 100;            // 4 bit fractional .0625 per bit
+            sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac);
+            sprintf(lora_temp_string,"%ld.%03d", num_whole, num_frac);
+            evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Ambient Light Level
+            lux_data = evbAmbLight->getData();
+            num_whole = lux_data * 24 / 100;        // 16000 lux full scale .24 lux per bit
+            num_frac = lux_data * 24 % 100;
+            sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac );
+            sprintf(lora_light_string, "%ld.%02d", num_whole, num_frac );
+            evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr));
+
+            // Retrieve and Display Current Sensor Level (EVB Analog Input)
+            current = (double) current_sensor * 65535.0;
+            sprintf(lora_current_string, "%d", (int) current);
+
+            // Handle Pushbutton #1 (SW1) - This should be handled by the 'pb1_debounce' thread.
+            if( pb1_low )
+            {
+                sw1_state = !sw1_state;
+                if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,0);  // enable LED2 on EVB and set to 0% PWM
+
+                sprintf(txtstr,"PB1 Press-SW1: %d", sw1_state);
+                if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                printf("%s \r\n",txtstr);
+
+                pb1_low = false;
+            }
+
+            // Handle Pushbutton #2 (SW2) - This should be handled by the 'pb2_debounce' thread.
+             if( pb2_low )
+            {
+                sw2_state = !sw2_state;
+                if( bHasLCD ) evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM
+
+                sprintf(txtstr,"PB2 Press-SW2: %d", sw2_state);
+                if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+                printf("%s \r\n",txtstr);
+
+                pb2_low = false;
+            }
+        }
+        //MEMS
+        else if(!bHasLCD && bHasACC)
+        {
+
+            std::vector<uint8_t> tx_data;
+
+
+            // 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
+            */
+
+            // HTS221 Humidity sensor
+            ret |= (!CALL_METH(memsTemp1, GetTemperature, &temp_value, 0.0f) ? 0x0 : 0x1);
+            ret |= (!CALL_METH(memsHumidity, GetHumidity, &humid_value, 0.0f) ? 0x0 : 0x2);;
+
+			/*
+            //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
+            int_temp_value = floor(temp_value*10 + 0.5f);
+            tx_data.push_back(uint8_t( 0xFF & (int_temp_value >> 8)));
+            tx_data.push_back(uint8_t(0xFF & int_temp_value));
+
+
+            tx_data.push_back(uint8_t(2)); // data id
+            tx_data.push_back(uint8_t(0x68)); // data type - humidity
+            int_humid_value = floor(humid_value * 2.0f + 0.5f);
+            tx_data.push_back(uint8_t(0xFF & int_humid_value ));
+			*/
+
+            ret |= (!CALL_METH(memsPressure, GetPressure, &pressure_value, 0.0f) ? 0x0 : 0x4);;
+
+			/*
+            // pressure is reported in mbar
+            // 1mbar = 1 hPa
+            int_pressure_value = floor(pressure_value * 100.0f + 0.5f);
+
+            tx_data.push_back(uint8_t(3)); // data id
+            tx_data.push_back(uint8_t(0x73)); // data type - pressure
+            int_pressure_value = floor(pressure_value / 0.1f + 0.5f);
+            tx_data.push_back(uint8_t(0xFF & (int_pressure_value >> 8)));
+            tx_data.push_back(uint8_t(0xFF & int_pressure_value));
+			*/
+
+            // Get accelerometer data
+            // returns in mG
+            memsAccel->Get_X_Axes(accel_vector);
+
+			/*
+            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]));
+            }
+			*/
+
+            // Get gyro data
+            memsGyro->Get_G_Axes(gyro_vector);
+
+            /*
+            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++) {
+                gyro_vector[i] /= 10;
+                tx_data.push_back(uint8_t(0xFF & (gyro_vector[i] >> 8)));
+                tx_data.push_back(uint8_t(0xFF & gyro_vector[i]));
+            }
+			*/
+
+            // Get magnetometer data
+            memsMag->Get_M_Axes(mag_vector);
+            
+           /*
+            tx_data.push_back(uint8_t(5)); //data id
+            tx_data.push_back(uint8_t(0x99)); // data type - mangetometer
+            for(int i=0; i<3; i++) {
+                mag_vector[i] /= 10;
+                tx_data.push_back(uint8_t(0xFF & (mag_vector[i] >> 8)));
+                tx_data.push_back(uint8_t(0xFF & mag_vector[i]));
+            }
+            */
+
+		}
+		else
+		{
+			//Basic mDot... fabricated data
+        	sprintf(lora_press_string, "%ld.%02d", 101967, 33 );	
+        	sprintf(lora_alt_string, "%ld.%02d", 53, 22 );
+        	sprintf(lora_temp_string, "%ld.%03d", 22, 123 );
+        	sprintf(lora_light_string, "%ld.%02d", 399, 62 );	
+        	sprintf(lora_current_string, "%ld.%01d", 88, 62 );	
+		}
+		
+		
+            //send_data(tx_data);
+
+            //---------------------------------------------------------------------------
+            // Verbose Text Format:  Least Data Payload, Most Human Readible
+            //---------------------------------------------------------------------------
+
+  			/*
+            if(!bHasLCD && bHasACC)
+            {
+
+                sprintf(sensor_text, "accel-x:%d|accel-y:%d|accel-z:%d|gyro-x:%d|gyro-y:%d|gyro-z:%d|mag-x:%d|mag-y:%d|mag-x:%d|press:%s|temp:%s|humid:%s",
+                    accel_vector[0],
+                    accel_vector[1],
+                    accel_vector[2],
+                    gyro_vector[0],
+                    gyro_vector[1],
+                    gyro_vector[2],
+                    mag_vector[0],
+                    mag_vector[1],
+                    mag_vector[2],
+                    printDouble(buffer3, pressure_value),
+                    printDouble(buffer1, temp_value),
+                    printDouble(buffer2, humid_value));
+            }
+            else
+            {
+                sprintf(sensor_text, "accel-x:%d|accel-y:%d|accel-z:%d|press:%s|alti:%s|temp:%s|light:%s|moist:%s",
+                    accel_data._x,
+                    accel_data._y,
+                    accel_data._z,
+                    lora_press_string,
+                    lora_alt_string,
+                    lora_temp_string,
+                    lora_light_string,
+                    lora_current_string);
+
+            }
+
+
+             if ((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) {
+                log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
+            } else {
+                printf("Ok, Successfully Sent Data to Gateway...\r\n");
+            }
+ 			*/
+
+            //---------------------------------------------------------------------------
+            // Byte Vector Format:  More Data Payload, Less Human Readible
+            //---------------------------------------------------------------------------
+
+		//MDOT-BOX
+        if (bHasGPS) {
+            sprintf(sensor_text, "ax:%d,ay:%d,az:%d,ll:%d,la:%s,lg:%s,p:%s,a:%s,t:%s,l:%s,c:%s",
+                    accel_data._x,
+                    accel_data._y,
+                    accel_data._z,
+                    sat_lock,
+                    lora_lat_string,
+                    lora_lng_string,
+                    lora_press_string,
+                    lora_alt_string,
+                    lora_temp_string,
+                    lora_light_string,
+                    lora_current_string);
+        //EVB
+        } else if(bHasLCD && bHasACC) {
+            sprintf(sensor_text, "ax:%d,ay:%d,az:%d,p:%s,a:%s,t:%s,l:%s,c:%s",
+                    accel_data._x,
+                    accel_data._y,
+                    accel_data._z,
+                    lora_press_string,
+                    lora_alt_string,
+                    lora_temp_string,
+                    lora_light_string,
+                    lora_current_string);
+        }
+        
+        //MEMS
+        else if(!bHasLCD && bHasACC){
+        
+            sprintf(sensor_text, "ax:%d,ay:%d,az:%d,gx:%d,gy:%d,gz:%d,mx:%d,my:%d,mz:%d,p:%s,t:%s,h:%s",
+                    accel_vector[0],
+                    accel_vector[1],
+                    accel_vector[2],
+                    gyro_vector[0],
+                    gyro_vector[1],
+                    gyro_vector[2],
+                    mag_vector[0],
+                    mag_vector[1],
+                    mag_vector[2],
+                    printDouble(buffer3, pressure_value),
+                    printDouble(buffer1, temp_value),
+                    printDouble(buffer2, humid_value));
+        }
+        
+        //Basic mDot
+        else{
+
+            sprintf(sensor_text, "p:%s,a:%s,t:%s,l:%s,c:%s",
+                    lora_press_string,
+                    lora_alt_string,
+                    lora_temp_string,
+                    lora_light_string,
+                    lora_current_string);
+        }
+
+        if ((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) {
+            log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
+        } else {
+            printf("Ok, Successfully Sent Data to Gateway...\r\n");
+        }
+
+            /*
+            //---------------------------------------------------------------------------
+            // Binary Encoded Format:  Most Data Payload, Not Human Readible
+            //---------------------------------------------------------------------------
+            mdot_data.clear();
+            mdot_data.push_back(0x0E);              // key for Current Acceleration 3-Axis Value
+            converts.f_s = accel_data._x *4;        // shift data 2 bits while retaining sign
+            mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
+            converts.f_s = accel_data._y * 4;       // shift data 2 bits while retaining sign
+            mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
+            converts.f_s = accel_data._z * 4;       // shift data 2 bits while retaining sign
+            mdot_data.push_back(converts.t_u[1]);   // get 8 MSB of 14 bit value
+            mdot_data.push_back(0x08);              // key for Current Pressure Value
+            convertl.f_u = pressure;                // pressure data is 20 bits unsigned
+            mdot_data.push_back(convertl.t_u[2]);
+            mdot_data.push_back(convertl.t_u[1]);
+            mdot_data.push_back(convertl.t_u[0]);
+            mdot_data.push_back(0x05);              // key for Current Ambient Light Value
+            converts.f_u = lux_data;                // data is 16 bits unsigned
+            mdot_data.push_back(converts.t_u[1]);
+            mdot_data.push_back(converts.t_u[0]);
+            mdot_data.push_back(0x0B);              // key for Current Temperature Value
+            converts.f_s = baro_data._temp;         // temperature is signed 12 bit
+            mdot_data.push_back(converts.t_u[1]);
+            mdot_data.push_back(converts.t_u[0]);
+
+            if ((mdot_ret = mdot_radio->send(mdot_data)) != mDot::MDOT_OK) {
+                log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret);
+            } else {
+                printf("Ok, Successfully Sent Data to Gateway...\r\n");
+            }
+
+            */
+
+            osDelay(CYCLE_TIME);
+            sprintf(txtstr,"Scanning...     ");
+            if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+
+
+        // Put Thread to Sleep for 30 Seconds...
+        // osDelay(30000);
+
+    } while(i < 86400);
+
+    printf("End of Data Collection Cycle (24 Hours) - Ending Application, GoodBye...\r\n");
+
+    if( bHasLCD ) evbLCD->clearBuffer();
+    sprintf(txtstr,"Exiting Program");
+    if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+}
+
+/*** Interrupt Handler Top-Halves ------------------------------------------------------ ***/
+/* Called in interrupt context, therefore just set a trigger variable */
+static void timer_irq(void) {
+    timer_irq_triggered = true;
+}
+
+/* Called in interrupt context, therefore just set a trigger variable */
+static void ff_irq(void) {
+    ff_irq_triggered = true;
+
+    /* Disable IRQ until handled */
+    mems_expansion_board->gyro_lsm6ds3->Disable_Free_Fall_Detection_IRQ();
+}
+
+
+/*** Interrupt Handler Bottom-Halves ------------------------------------------------- ***/
+/* Handle Free Fall Interrupt
+   (here we are in "normal" context, i.e. not in IRQ context)
+*/
+static void handle_ff_irq(void) {
+    printf("\nFree Fall Detected!\n\n");
+
+    /* Re-enable IRQ */
+    mems_expansion_board->gyro_lsm6ds3->Enable_Free_Fall_Detection_IRQ();
+}
+
+/*===================================================================================
+Send String Payload to Conduit Gateway
+===================================================================================*/
+int32_t sendString(const std::string text)
+{
+    int32_t ret;
+    if (mdot_radio->getNextTxMs() != 0)
+    {
+        printf("Sending in %lu ms...\r\n", mdot_radio->getNextTxMs());
+        return false;
+    }
+
+    printf("Sending: '%s'\r\n", text.c_str());
+    std::vector<uint8_t> data(text.begin(), text.end());
+    if ((ret = mdot_radio->send(data, 1)) != mDot::MDOT_OK)
+    {
+        log_error(mdot_radio, "ERROR: Failed to Send Data", ret);
+    }
+
+    return ret;
+}
+
+/*===================================================================================
+Interrupt Service Request Handler - Sets pb1_low flag. Flag is cleared in pb1_debounce thread
+===================================================================================*/
+void pb1ISR(void)
+{
+    pb1_low = true;
+}
+
+/*===================================================================================
+Pushbutton Debounce - Debounces pb1 PB1 changes SW1 State Value (Sets LED Off)
+===================================================================================*/
+void pb1_debounce(void const *args)
+{
+    printf("Thread pb1_debounce started...\r\n");
+
+    while(true)
+    {
+        // if( pb1_low && (mDot08 == 0))
+        if( pb1_low )
+        {
+            sprintf(txtstr,"PB1 Pressed...");
+            if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+            printf("%s\r\n",txtstr);
+
+            pb1_low = false;
+        }
+
+        Thread::wait(50);
+    }
+}
+
+/*===================================================================================
+Interrupt Service Request Handler - Sets pb1_low flag. Flag is cleared in pb1_debounce thread
+===================================================================================*/
+void pb2ISR(void)
+{
+    pb2_low = true;
+}
+
+/*===================================================================================
+Pushbutton Debounce - Debounces pb2 PB2 changes SW2 State Value (Sets LED On)
+===================================================================================*/
+void pb2_debounce(void const *args)
+{
+    printf("Thread pb2_debounce started...\r\n");
+
+    while(true)
+    {
+        // if( pb2_low && (mDot09 == 1))
+        if( pb2_low )
+        {
+            sprintf(txtstr,"PB2 Pressed...");
+            if( bHasLCD ) evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr));
+            printf("%s \r\n",txtstr);
+
+            pb2_low = false;
+        }
+
+        Thread::wait(50);
+    }
+}
+
+/*===================================================================================
+Display Value/Error String of Barometric Pressure Sensor
+===================================================================================*/
+bool writeValueOrError()
+{
+    bool res;
+
+    if (failtime==0)
+    {
+        sprintf(lora_press_string, "%s", "--.--");
+        sprintf(txtstr, "%s", "--.--");
+        if( bHasLCD ) evbLCD->writeText(0,4,font_6x8,txtstr, strlen(txtstr));
+        res=false;
+    }
+    else
+    {
+        sprintf(lora_press_string, "%ld.%02d", num_whole, num_frac);
+        if( bHasLCD ) evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr));
+        res=true;
+    }
+
+    return res;
+}
+
+/*===================================================================================
+Resets Barometric Pressure Sensor
+===================================================================================*/
+MPL3115A2* resetBaro(const MPL3115A2* oldBaro)
+{
+    delete oldBaro;
+    MPL3115A2* baro = new MPL3115A2(mDoti2c);
+    baro->testWhoAmI();
+
+    printf("Resetting barometer.. %x \n\r", baro->getStatus() );
+    baro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, MPL3115A2::AT_1);
+    evbBaro->clearMinMaxRegs();
+
+    return baro;
+}
+
+/*===================================================================================
+Print clear text verion of mDot/EVB errors
+===================================================================================*/
+void log_error(mDot* dot, const char* msg, int32_t retval)
+{
+    printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
+}