Demonstration program for Multitech System MTDOT-EVB an evaluation board for the mDot LoRa module
Dependencies: DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B libmDot mbed-rtos mbed
Diff: main.cpp
- Revision:
- 9:ed86d5ae29cc
- Parent:
- 7:85445a8cc189
diff -r 85445a8cc189 -r ed86d5ae29cc main.cpp --- a/main.cpp Wed Oct 28 17:58:55 2015 +0000 +++ b/main.cpp Mon Nov 23 14:51:32 2015 +0000 @@ -2,7 +2,7 @@ * @file main.cpp * @brief Main application for mDot-EVB demo * @author Tim Barr MultiTech Systems Inc. - * @version 1.03 + * @version 1.05 * @see * * Copyright (c) 2015 @@ -32,6 +32,11 @@ * public netework setup. Swapped \n and \r in prinf calls because * Windows seems to be picky about the order * + * 1.05 TAB 11/17/15 Changed baud rate for debug from 921k to 115k. Added code to support + * 868 MHz band operation. Added mutex around certain mDot radio commands. + * Changed network name and passphrase. Changed pb references to sw to + * match MTDOT-BOX overlay. Changed function of SW1 from end program to + * cycle through power levels and data rates. */ #include "mbed.h" @@ -76,8 +81,8 @@ //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 +InterruptIn mDot08(PA_12); // GPIO/USB PB SW1 on EVB +InterruptIn mDot09(PA_11); // GPIO/USB PB SW2 on EVB //DigitalIn mDot11(PA_7); // GPIO/SPI_MOSI @@ -101,17 +106,13 @@ SPI mDotspi(PA_7,PA_6,PA_5); // mDot external SPI mDot11, mDot4, and mDot18 /* **** replace these values with the proper public or private network settings **** - * config_network_nameand config_network_pass are for private networks. + * config_network_name and config_network_pass are for private networks. */ -//settings for my bench -static std::string config_network_name = "TAB-CubeNet"; -static std::string config_network_pass = "1nt3gral"; -static uint8_t config_frequency_sub_band = 5; //Default network server settings -//static std::string config_network_name = "YOUR-NETWORK-NAME"; -//static std::string config_network_pass = "YOUR-NETWORK-PASSPHRASE"; -//static uint8_t config_frequency_sub_band = 3; +static std::string config_network_name = "Multitech"; +static std::string config_network_pass = "Multitech"; +static uint8_t config_frequency_sub_band = 3; /* 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}; @@ -120,15 +121,17 @@ std::vector<uint8_t> config_app_key; */ -uint8_t result, pckt_time=10; +uint8_t result, mdot_freq; +uint8_t pckt_time = 8; +uint16_t xmit_delay = 8; char data; unsigned char test; char txtstr[17]; -int32_t num_whole, mdot_ret; +int32_t num_whole, mdot_ret, join_delay; uint32_t pressure; int16_t num_frac; - -bool exit_program = false; +uint8_t sf_val = mDot::SF_7; +uint8_t pwr_val = 11; // dBm MMA845x_DATA accel_data; MPL3115A2_DATA baro_data; @@ -139,18 +142,20 @@ NCP5623B* evbBackLight; DOGS102* evbLCD; mDot* mdot_radio; +Mutex mdot_mutex; convert32 convertl; convert16 converts; // flags for pushbutton debounce code -bool pb1_low = false; -bool pb2_low = false; +bool sw1_low = false; +bool sw2_low = false; +bool toggle_text = false; -void pb1ISR(void); -void pb2ISR(void); -void pb1_debounce(void const *args); -void pb2_debounce(void const *args); +void sw1ISR(void); +void sw2ISR(void); +void sw1_debounce(void const *args); +void sw2_debounce(void const *args); Thread* thread_3; void log_error(mDot* dot, const char* msg, int32_t retval); @@ -163,12 +168,13 @@ std::vector<uint8_t> mdot_data; std::vector<uint8_t> mdot_EUI; uint16_t i = 0; + uint8_t j =0; - debugUART.baud(921600); + debugUART.baud(115200); // mDotUART.baud(9600); // mdot UART unused but available on external connector - Thread thread_1(pb1_debounce); // threads for de-bouncing pushbutton switches - Thread thread_2(pb2_debounce); + Thread thread_1(sw1_debounce); // threads for de-bouncing pushbutton switches + Thread thread_2(sw2_debounce); thread_3 = new Thread(config_pkt_xmit); // start thread that sends LoRa packet when SW2 pressed @@ -182,7 +188,7 @@ * Setup SW1 as program stop function */ mDot08.disable_irq(); - mDot08.fall(&pb1ISR); + mDot08.fall(&sw1ISR); /* * need to call this function after rise or fall because rise/fall sets @@ -196,7 +202,7 @@ * Setup SW2 as packet time change */ mDot09.disable_irq(); - mDot09.fall(&pb2ISR); + mDot09.fall(&sw2ISR); /* * need to call this function after rise or fall because rise/fall sets @@ -221,21 +227,14 @@ evbLCD->writeBitmap(0,0,MultiTech_Logo); - sprintf(txtstr,"MTDOT"); - evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr)); - sprintf(txtstr,"Evaluation"); - evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr)); - sprintf(txtstr,"Board"); - evbLCD->writeText(24,5,font_6x8,txtstr,strlen(txtstr)); - - evbLCD->endUpdate(); - printf("\r\n setup mdot\r\n"); // get a mDot handle mdot_radio = mDot::getInstance(); if (mdot_radio) { + mdot_mutex.lock(); // lock mdot before setting configuration + // reset to default config so we know what state we're in mdot_radio->resetConfig(); @@ -243,14 +242,31 @@ mdot_radio->setActivityLedPin(PB_0); mdot_radio->setActivityLedEnable(true); - // Read node ID + // Read node ID and frequency band mdot_EUI = mdot_radio->getDeviceId(); + mdot_freq = mdot_radio->getFrequencyBand(); + printf("mDot EUI = "); for (i=0; i<mdot_EUI.size(); i++) { printf("%02x ", mdot_EUI[i]); } printf("\r\n"); + sprintf(txtstr,"MTDOT EVB"); + printf("mDot Frequency = "); + if (mdot_freq == mDot::FB_868) { + printf( "868 MHz\r\n"); + sprintf(txtstr,"%s 868 MHz",txtstr); + } else { + printf("915 MHz\r\n"); + sprintf(txtstr,"%s 915 MHz",txtstr); + } + + evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr)); + sprintf(txtstr,"Sensor Demo"); + evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr)); + + evbLCD->endUpdate(); // Setting up the mDot with network information. @@ -269,9 +285,11 @@ * 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, "failed to set frequency sub band", mdot_ret); + if (mdot_freq == mDot::FB_915) { + printf("setting frequency sub band\r\n"); + if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) { + log_error(mdot_radio, "failed to set frequency sub band", mdot_ret); + } } /* @@ -300,34 +318,68 @@ log_error(mdot_radio, "failed to set network password", mdot_ret); } - // attempt to join the network - printf("joining network\r\n"); - while (((mdot_ret = mdot_radio->joinNetwork()) != mDot::MDOT_OK) && (!exit_program)) { - log_error(mdot_radio,"failed to join network:", mdot_ret); - if (mdot_radio->getFrequencyBand() == mDot::FB_868) { - mdot_ret = mdot_radio->getNextTxMs(); - } else { - mdot_ret = 0; - } - - printf("delay = %lu\r\n",mdot_ret); - osDelay(mdot_ret + 1); + /* + * 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, "failed to set TX power level", mdot_ret); } /* - * Check for PB1 press during network join attempt + * Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_9 */ - if (exit_program) { - printf("Exiting program\r\n"); - evbLCD->clearBuffer(); - sprintf(txtstr,"Exiting Program"); - evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); - exit(1); + 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, "failed to set TX data rate", mdot_ret); } + mdot_mutex.unlock(); // unlock mdot mutex before join attempt so SW1 can work + + // attempt to join the network + printf("joining 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,"failed to join network:", mdot_ret); + + if (toggle_text) + sprintf(txtstr," > Join Failed <"); + else + sprintf(txtstr," < Join Failed >"); + + 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("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 + + } while (mdot_ret != mDot::MDOT_OK); + + sprintf(txtstr,"*Network Joined*"); + evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); + } else { - printf("radio setup failed\r\n"); - //exit(1); + sprintf(txtstr,"Radio Init Failed!"); + evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); + printf("%s\r\n",txtstr); + exit(1); } osDelay(200); @@ -392,25 +444,17 @@ evbBackLight->setLEDCurrent(0); /* - * Check for PB1 press during network join attempt - */ - if (exit_program) { - printf("Exiting program\r\n"); - evbLCD->clearBuffer(); - sprintf(txtstr,"Exiting Program"); - evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); - exit(1); - } - - /* * Main data acquisition loop */ - pckt_time = 10; - i = 0; + i = 0; + do { evbLCD->startUpdate(); - evbLCD->clearBuffer(); + // clear LCD line 0-6 only + sprintf(txtstr, " "); + for (j=0; j<6; j++) + evbLCD->writeText(0,j,font_6x8,txtstr,strlen(txtstr)); /* * Test Accelerometer XYZ data ready bit to see if acquisition complete @@ -425,14 +469,12 @@ */ accel_data = evbAccel->getXYZ(); - sprintf(txtstr,"Accelerometer"); + sprintf(txtstr, "Accel: x = %d", accel_data._x); evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr)); - sprintf(txtstr, "x = %d", accel_data._x); - evbLCD->writeText(20,1,font_6x8,txtstr,strlen(txtstr)); sprintf(txtstr, "y = %d", accel_data._y); - evbLCD->writeText(20,2,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(42,1,font_6x8,txtstr,strlen(txtstr)); sprintf(txtstr, "z = %d", accel_data._z ); - evbLCD->writeText(20,3,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(42,2,font_6x8,txtstr,strlen(txtstr)); /* * Trigger a Pressure reading @@ -456,7 +498,7 @@ num_whole = pressure >> 2; // 18 bit integer significant num_frac = (pressure & 0x3) * 25; // 2 bit fractional 0.25 per bit sprintf(txtstr,"Press=%ld.%02d Pa", num_whole, num_frac); - evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(0,3,font_6x8,txtstr,strlen(txtstr)); /* * Trigger a Altitude reading @@ -481,11 +523,11 @@ num_whole = baro_data._baro / 16; // 18 bit signed significant integer num_frac = (baro_data._baro & 0xF) * 625 / 100; // 4 bit fractional .0625 per bit sprintf(txtstr,"Alti=%ld.%02d m", num_whole, num_frac); - evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); 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); - evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); /* * retrieve and print out Ambient Light level @@ -494,13 +536,28 @@ 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 ); - evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); + evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr)); evbLCD->endUpdate(); + printf("finished iteration %d\r\n",(++i)); - if (i % pckt_time == 0) { // check packet counter will send packet every 2-5-10 data collection loops + /* Transmit data packet based on pckt_time setting and result of + * mdot_radio->getNextTxMs() function and mutex available. The getNextTxMs() + * function returns the number of millisecond before another packet can be + * sent in 868 MHz band. This can vary depending on wther the 10%, 1% or 0.1% + * channel is used and the time on air for a specific setup of the radio + */ + + if ((xmit_delay <= i) && (mdot_radio->getNextTxMs() == 0) && (mdot_mutex.trylock())) { + /* + * Setting TX power and Data Rate for radio just in case user requested by SW2 + */ + mdot_radio->setTxPower(pwr_val); + mdot_radio->setTxDataRate(sf_val); + mdot_data.clear(); + mdot_data.push_back(0x1D); // key for start of data 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 @@ -513,6 +570,24 @@ mdot_data.push_back(convertl.t_u[2]); mdot_data.push_back(convertl.t_u[1]); mdot_data.push_back(convertl.t_u[0]); + + /* for 915 MHz band and SF_10 max packet size is 11 bytes. + * so the payload gets split in two packets here. + */ + if ((mdot_freq == mDot::FB_915) && (sf_val == mDot::SF_10)) { + mdot_ret = mdot_radio->send(mdot_data); + if ( mdot_ret != mDot::MDOT_OK) { + sprintf(txtstr,"mDot Send failed"); + evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); + log_error(mdot_radio, txtstr, mdot_ret); + continue; + } else { + printf("successfully sent packet 1 to gateway\r\n"); + } + mdot_data.clear(); // clear data for next "chunk" + } + + 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]); @@ -521,14 +596,28 @@ 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]); + mdot_data.push_back(0x1D); // key for end of data - if ((mdot_ret = mdot_radio->send(mdot_data)) != mDot::MDOT_OK) { + mdot_ret = mdot_radio->send(mdot_data); + if (mdot_ret != mDot::MDOT_OK) { log_error(mdot_radio, "failed to send", mdot_ret); + sprintf(txtstr,"PKT Send Failed"); + evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); } else { - printf("successfully sent data to gateway\r\n"); + sprintf(txtstr,"SENT DR=%2d Pwr=%2d",(12 - sf_val),pwr_val); + evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); + printf("%s \r\n",txtstr); } + mdot_mutex.unlock(); // unlock mutex after all data transmitted + xmit_delay = i + pckt_time; + if (mdot_freq == mDot::FB_868) + printf("Next transmit time = %d milliseconds \r\n",mdot_radio->getNextTxMs()); + + } else { + sprintf(txtstr," DR=%2d Pwr=%2d ",(12 - sf_val),pwr_val); + evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); } - } while(!exit_program && (i < 65000)); + } while(i < 65000); evbBaro->triggerOneShot(); @@ -550,71 +639,105 @@ } /* - * Sets pb1_low flag. Slag is cleared in pb1_debounce thread + * Sets sw1_low flag. Slag is cleared in sw1_debounce thread */ -void pb1ISR(void) +void sw1ISR(void) { - if (!pb1_low) - pb1_low = true; + if (!sw1_low) + sw1_low = true; } /* - * Debounces pb1. Also exits program if pushbutton 1 is pressed + * Debounces sw1 changes spreading factor and output power + * Cycles through SF_7-SF_9 for 4 power levels for 915 MHz band + * Cycles through SF_7-SF_12 for 4 power levels for 868 MHz band */ -void pb1_debounce(void const *args) +void sw1_debounce(void const *args) { - static uint8_t count = 0; + static uint8_t test_sf = 0; + static uint8_t test_pwr = 0; while (true) { - if (pb1_low && (mDot08 == 0)) + if (sw1_low && (mDot08 == 0)) count++; else { count = 0; - pb1_low = false; + sw1_low = false; } - if (count == 5) - exit_program = true; + if (count == 5) { + test_sf++; + + if (((test_sf > 3) && (mdot_freq == mDot::FB_915)) || ((test_sf > 5) && (mdot_freq == mDot::FB_868))) { + test_sf = 0; + test_pwr ++; + if (test_pwr > 3) + test_pwr = 0; + } + + // selects power output level using upper bits for select + switch(test_pwr) { + case 0: + pwr_val = 11; + break; + case 1: + pwr_val = 14; + break; + case 2: + pwr_val = 18; + break; + case 3: + pwr_val = 20; + } + + // sets data rate based on lower bits + sf_val = mDot::SF_7 - (test_sf & 0x07); + + sprintf(txtstr," DR=%2d Pwr=%2d ",(12 - sf_val),pwr_val); + evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); + printf("%s \r\n",txtstr); + } Thread::wait(5); } } /* - * Sets pb2_low flag. Flag is cleared in pb2_debounce thread + * Sets sw2_low flag. Flag is cleared in sw2_debounce thread */ -void pb2ISR(void) +void sw2ISR(void) { - if (!pb2_low) - pb2_low = true; + if (!sw2_low) + sw2_low = true; } /* - * Debounces pb2. Also changes packet transmit time to every other, - * every fifth, or every tenth sample when SW2 pushed + * Debounces sw2. Changes packet transmit time to every 2nd, + * 4th, 8th, or 16th sample when SW2 pushed. For 868 MHz mode + * the time for next packet value is also tested. * Also triggers a thread to transmit a configuration packet */ -void pb2_debounce(void const *args) +void sw2_debounce(void const *args) { static uint8_t count = 0; while (true) { - if (pb2_low && (mDot09 == 0)) + if (sw2_low && (mDot09 == 0)) count++; else { count = 0; - pb2_low = false; + sw2_low = false; } if (count == 5) { - if (pckt_time >= 5) + if (pckt_time >= 4) pckt_time /= 2; - else pckt_time = 20; + else pckt_time = 16; thread_3->signal_set(0x10); // signal config_pkt_xmit to send packet } @@ -624,7 +747,7 @@ } /* - * Function that print clear text verion of mDot errors + * Function that prints clear text verion of mDot errors */ void log_error(mDot* dot, const char* msg, int32_t retval) { @@ -638,17 +761,24 @@ { std::vector<uint8_t> data; + uint16_t wait_time; while (true) { - Thread::signal_wait(0x10); // wait for pb2ISR to signal send + Thread::signal_wait(0x10); // wait for sw2ISR to signal send data.clear(); data.push_back(0x0F); // key for Configuration data (packet transmission timer) data.push_back(pckt_time); + + mdot_mutex.lock(); // lock mdot mutex before packet send + + if ((wait_time = mdot_radio->getNextTxMs()) > 0) // wait for next xmit time + osDelay(wait_time); if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) { log_error(mdot_radio, "failed to send config data", mdot_ret); } else { printf("sent config data to gateway\r\n"); } + mdot_mutex.unlock(); // unlock mdot mutex after packet send } }