Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ISL29011 libxDot-mbed5
main.cpp
00001 /*================================================================================ 00002 * 00003 * CLASIFICATION: **** PUBLIC RELEASE AS-IS APPLICATION EXAMPLE **** 00004 * 00005 * SOURCE FILE NAME: main.cpp 00006 * 00007 * DESCRIPTIVE NAME: MBED Source for MultiTech mDot, EVB, and MDOT-BOX Devices 00008 * 00009 * COPYRIGHT: Copyright 2014-2017, Telit 00010 * 00011 ** WEB SITE: www.telit.com 00012 * 00013 * WRITTEN BY: John Keever 00014 * 00015 * DATE: 27 July, 2017 00016 * 00017 * VERSION: 1.00 00018 * 00019 * FUNCTION: Provide working example for LoRa 'Sensor-to-Cloud' 00020 * Demonstration using MultiTech LoRa Starter Kit and 00021 * Telit Data and Cloud Platform Services Offerings 00022 * 00023 * SOURCE FILE TYPE: MBED C++ 00024 * 00025 * FUNCTIONS/ENTRY POINTS: main 00026 * 00027 * INPUT = None. 00028 * OUTPUT = None. 00029 * 00030 * EXIT-NORMAL = N/A 00031 * EXIT-ERROR = N/A 00032 * 00033 * EXTERNAL REFERENCES = None. 00034 * 00035 * EXTERNAL FUNCTIONS = None. 00036 * 00037 * CONTROL BLOCKS = None. 00038 * 00039 *================================================================================*/ 00040 /* LEGAL DISCLAIMER */ 00041 /*================================================================================ 00042 00043 Redistribution and use in source and binary forms, with or without 00044 modification, are permitted provided that the following conditions 00045 are met: 00046 00047 Neither the name of ILS Technology nor Telit nor the names of its 00048 contributors may be used to endorse or promote products derived 00049 from this software without specific prior written permission. 00050 00051 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00052 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00053 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00054 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00055 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00056 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00057 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00058 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00059 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00060 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00061 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00062 00063 *================================================================================*/ 00064 /* CHANGE LOG */ 00065 /*================================================================================*/ 00066 /* |Changed | | */ 00067 /* Date | by |Version ID| Comments */ 00068 /*----------+--------+----------+-------------------------------------------------*/ 00069 /*07-27-2017|JEK |V1.00 |Original Version - xDot (Light Sensor, S2 Button)*/ 00070 /* | | | */ 00071 /*================================================================================*/ 00072 /*NOTE: Please keep the change log up to date!!! */ 00073 /*================================================================================*/ 00074 00075 #include "mbed.h" 00076 #include "mDot.h" 00077 #include "rtos.h" 00078 #include "ChannelPlans.h" 00079 00080 #include "ISL29011.h" 00081 00082 #include <cmath> 00083 #include <string> 00084 #include <vector> 00085 #include <ctime> 00086 00087 #ifndef CHANNEL_PLAN 00088 #define CHANNEL_PLAN CP_US915 00089 #endif 00090 00091 static volatile bool timer_irq_triggered = false; 00092 static volatile bool ff_irq_triggered = false; 00093 00094 //static std::string config_network_name = "MTCDT-19186797"; 00095 //static std::string config_network_pass = "MTCDT-19186797"; 00096 //static uint8_t config_frequency_sub_band = 1; 00097 00098 static std::string config_network_name = "MTCDT-19186799"; 00099 static std::string config_network_pass = "MTCDT-19186799"; 00100 static uint8_t config_frequency_sub_band = 1; 00101 00102 uint8_t result; 00103 uint8_t data; 00104 uint8_t sf_val = mDot::DR2; 00105 uint8_t pwr_val = 11; // dBm 00106 uint8_t swp_pwr; 00107 uint8_t swp_sf; 00108 00109 int32_t mdot_ret; 00110 int32_t join_delay; 00111 00112 osThreadId mainThreadID; 00113 00114 // Physical I/O Instantiation 00115 DigitalOut led(LED1); 00116 DigitalIn s2(PA_0); 00117 00118 I2C i2c(I2C_SDA, I2C_SCL); 00119 ISL29011 lux(i2c); 00120 // InterruptIn btn(PA_0); /* S2 - button */ 00121 00122 // flags for push button debounce code 00123 bool pb1_low = false; 00124 bool pb2_low = false; 00125 bool toggle_text = false; 00126 bool sw1_state = false; 00127 bool sw2_state = false; 00128 00129 uint32_t num_whole; 00130 uint16_t num_frac; 00131 00132 uint32_t pressure; 00133 double current; 00134 00135 bool exit_program = false; 00136 00137 mDot* mdot_radio; 00138 Mutex mdot_mutex; 00139 00140 static Ticker ticker; 00141 00142 void pb1ISR(void); 00143 void pb2ISR(void); 00144 void pb1_debounce(void const *args); 00145 void pb2_debounce(void const *args); 00146 00147 //MPL3115A2* resetBaro(const MPL3115A2* oldBaro); 00148 void log_error(mDot* dot, const char* msg, int32_t retval); 00149 int32_t sendString(const std::string text); 00150 bool writeValueOrError(); 00151 00152 const int FAIL_MAX=15; 00153 int failtime=FAIL_MAX; 00154 int cycle_cnt = 0; 00155 00156 char sensor_text[64]; 00157 char lora_temp_string[16]; 00158 char lora_alt_string[16]; 00159 char lora_press_string[16]; 00160 char lora_light_string[16]; 00161 char lora_current_string[16]; 00162 char lora_humid_string[16]; 00163 00164 bool bHasGPS = false; 00165 bool bHasACC = false; 00166 bool bHasLCD = false; 00167 00168 //Helper Functions... Interrupt Handlers 00169 00170 void rise() 00171 { 00172 printf("\r\nS2 Button Interrupt... RISE (on)\r\n"); 00173 //led.write(true); 00174 led = 1; 00175 } 00176 00177 void fall() 00178 { 00179 printf("\r\nS2 Button Interrupt... FALL (off)\r\n"); 00180 //led.write(false); 00181 led = 0; 00182 } 00183 00184 int xmitDataPayload( int, int, int ); 00185 00186 /*=================================================================================== 00187 Main Program Logic - Entry 00188 ===================================================================================*/ 00189 int main() 00190 { 00191 std::vector<uint8_t> mdot_data; 00192 std::vector<uint8_t> mdot_EUI; 00193 uint16_t i = 0; 00194 00195 printf ("\r\nStarting xDot Demonstration Application...\r\n"); 00196 00197 mainThreadID = osThreadGetId(); 00198 00199 printf("Begin I2C/SPI Device Initialization...\r\n"); 00200 00201 printf("Initializing Light Sensor...\r\n"); 00202 00203 lux.setMode(ISL29011::ALS_CONT); 00204 lux.setResolution(ISL29011::ADC_16BIT); 00205 lux.setRange(ISL29011::RNG_64000); 00206 00207 printf("I2C/SPI Device Initialization Complete...\r\n"); 00208 00209 printf("Setup PushButton Interface Handlers...\r\n"); 00210 00211 //btn.rise(&rise); 00212 //btn.fall(&fall); 00213 00214 printf("S2 IRQs Set...\r\n"); 00215 00216 printf("PushButton Interface Handlers Setup...\r\n"); 00217 00218 printf("\r\nSetup xDot Radio Communications...\r\n"); 00219 00220 #if CHANNEL_PLAN == CP_AS923 00221 lora::ChannelPlan* plan = new lora::ChannelPlan_AS923(); 00222 #elif CHANNEL_PLAN == CP_US915 00223 lora::ChannelPlan* plan = new lora::ChannelPlan_US915(); 00224 #elif CHANNEL_PLAN == CP_AU915 00225 lora::ChannelPlan* plan = new lora::ChannelPlan_AU915(); 00226 #elif CHANNEL_PLAN == CP_EU868 00227 lora::ChannelPlan* plan = new lora::ChannelPlan_EU868(); 00228 #elif CHANNEL_PLAN == CP_KR920 00229 lora::ChannelPlan* plan = new lora::ChannelPlan_KR920(); 00230 #elif CHANNEL_PLAN == CP_IN865 00231 lora::ChannelPlan* plan = new lora::ChannelPlan_IN865(); 00232 #elif CHANNEL_PLAN == CP_AS923_JAPAN 00233 lora::ChannelPlan* plan = new lora::ChannelPlan_AS923_Japan(); 00234 #endif 00235 00236 printf("xDot getInstance()...\r\n"); 00237 00238 // get an xDot handle 00239 mdot_radio = mDot::getInstance( plan ); 00240 00241 if (mdot_radio) 00242 { 00243 printf("xDot getInstance()... Successful!\r\n"); 00244 00245 // reset to default config so we know what state we're in 00246 mdot_mutex.lock(); // lock mdot before setting configuration 00247 mdot_radio->resetConfig(); 00248 00249 // Setting up LED1 as activity LED 00250 mdot_radio->setActivityLedPin(LED1); 00251 mdot_radio->setActivityLedEnable(true); 00252 00253 // Read node ID 00254 mdot_EUI = mdot_radio->getDeviceId(); 00255 printf("mDot EUI = "); 00256 00257 for(i=0; i<mdot_EUI.size(); i++) 00258 { 00259 printf("%02x ", mdot_EUI[i]); 00260 } 00261 printf("\r\n"); 00262 00263 // Setting up the mDot with network information. 00264 00265 // This call sets up private or public mode on the MTDOT. Set the function to true if 00266 // connecting to a public network 00267 printf("Setting Private Network Mode...\r\n"); 00268 if ((mdot_ret = mdot_radio->setPublicNetwork(false)) != mDot::MDOT_OK) { 00269 log_error(mdot_radio, "ERROR: Failed to set Public Network Mode", mdot_ret); 00270 } 00271 00272 // Frequency sub-band is valid for NAM only and for Private networks should be set to a value 00273 // between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only. 00274 // This function can be commented out for EU networks 00275 printf("Setting Frequency Sub-Band...\r\n"); 00276 if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) { 00277 log_error(mdot_radio, "ERROR: Failed to set Frequency Sub-Band", mdot_ret); 00278 } 00279 00280 // Setting TX power for radio. Max allowed is +14dBm for EU and +20 dBm for NAM. Default is +11 dBm 00281 printf("Setting TX Power Level to %2d dBm...\r\n", pwr_val); 00282 if ((mdot_ret = mdot_radio->setTxPower(pwr_val)) != mDot::MDOT_OK) { 00283 log_error(mdot_radio, "ERROR: Failed to set TX Power Level", mdot_ret); 00284 } 00285 00286 // Turning ADR off for the purposes of demonstrating TX data rates 00287 printf("Setting ADR to Off...\r\n"); 00288 if((mdot_ret = mdot_radio->setAdr(false)) != mDot::MDOT_OK){ 00289 log_error(mdot_radio, "ERROR: Failed to set ADR", mdot_ret); 00290 } 00291 00292 // Setting TX data rate for radio. Max allowed is SF_12 for EU and SF10 dBm for NAM. Default is SF_10 00293 printf("Setting TX data rate to SF_7...\r\n"); 00294 if ((mdot_ret = mdot_radio->setTxDataRate(sf_val)) != mDot::MDOT_OK) { 00295 log_error(mdot_radio, "ERROR: Failed to set TX Data Rate", mdot_ret); 00296 } 00297 00298 // Setting Packet ACK to 1 try. 00299 printf("Setting Packet Retry to 1...\r\n"); 00300 if ((mdot_ret = mdot_radio->setAck(1)) != mDot::MDOT_OK) { 00301 log_error(mdot_radio, "ERROR: Failed to set Packet Retry\r\n", mdot_ret); 00302 } 00303 00304 // setNetworkName is used for private networks. 00305 // Use setNetworkID(AppID) for public networks 00306 // config_app_id.assign(app_id,app_id+7); 00307 00308 printf("Setting Network Name...\r\n"); 00309 if ((mdot_ret = mdot_radio->setNetworkName(config_network_name)) != mDot::MDOT_OK) { 00310 // if ((mdot_ret = mdot_radio->setNetworkID(config_app_id)) != mDot::MDOT_OK) { 00311 log_error(mdot_radio, "ERROR: Failed to set Network Name", mdot_ret); 00312 } 00313 00314 // setNetworkPassphrase is used for private networks 00315 // Use setNetworkKey for public networks 00316 // config_app_key.assign(app_key,app_key+15); 00317 00318 printf("Setting Network Password...\r\n"); 00319 if ((mdot_ret = mdot_radio->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) { 00320 // if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) { 00321 log_error(mdot_radio, "ERROR: Failed to set Network Password", mdot_ret); 00322 } 00323 00324 mdot_mutex.unlock(); // unlock mdot mutex before join attempt so SW1 can work 00325 00326 // attempt to join the network 00327 printf("Joining LoRa Network...\r\n"); 00328 do { 00329 mdot_mutex.lock(); // lock mdot mutex before join attempt 00330 mdot_ret = mdot_radio->joinNetwork(); 00331 mdot_mutex.unlock(); // unlock mdot mutex after join attempt so SW1 can work 00332 00333 if (mdot_ret != mDot::MDOT_OK) 00334 { 00335 log_error(mdot_radio,"ERROR: Failed to Join Network:", mdot_ret); 00336 00337 join_delay = 100; 00338 00339 printf("Join Delay = %lu\r\n",join_delay); 00340 osDelay(join_delay + 1); 00341 toggle_text = !toggle_text; 00342 } 00343 00344 /* 00345 * Setting TX power and Data Rate for radio just in case user requested by SW2 00346 */ 00347 mdot_mutex.lock(); // lock mdot mutex before setting change 00348 mdot_radio->setTxPower(pwr_val); 00349 mdot_radio->setTxDataRate(sf_val); 00350 mdot_mutex.unlock(); // unlock mdot mutex after settings change so SW1 can work 00351 00352 } while (mdot_ret != mDot::MDOT_OK); 00353 00354 printf("Successfully Joined LoRa Network...\r\n"); 00355 } 00356 else 00357 { 00358 printf("ERROR: Unable to Join LoRa Network...\r\n"); 00359 printf("getInstance... Radio Initialization Failed!\r\n"); 00360 00361 exit(1); 00362 } 00363 00364 printf("Initialization/Configuration Completed...\r\n"); 00365 00366 osDelay(1500); 00367 00368 // Enter Main Data Acquisition Loop... 00369 printf("Processing Data Acquisition Scan Loop...\r\n"); 00370 00371 i = 0; 00372 cycle_cnt = 100; 00373 00374 bool s2_last = 0; 00375 int lum_last = 0; 00376 int lum_delta = 0; 00377 00378 do 00379 { 00380 // Read Pushbutton #2 (S2) State... 00381 if( s2 > 0 ) 00382 { 00383 printf("S2 Pressed... State: %d\r\n", (int) s2); 00384 } 00385 00386 int delta = rand()%16; 00387 int temperature = 20 + delta; 00388 int luminosity = lux.getData(); 00389 int current = s2; 00390 00391 printf("Scan... Temperature: %d degC (delta=%d), Light: %d lux, Button: %d\r\n", temperature, delta, luminosity, current ); 00392 00393 lum_delta = abs( luminosity - lum_last ); 00394 00395 if( s2 != s2_last || lum_delta > 20 ) 00396 { 00397 printf("Data Change Event...\r\n"); 00398 00399 xmitDataPayload( temperature, luminosity, current ); 00400 00401 cycle_cnt = 0; 00402 } 00403 00404 if( cycle_cnt > 30 ) 00405 { 00406 printf("Transmitting Data... \r\n"); 00407 00408 sprintf(sensor_text, "t:%d,l:%d,c:%d", 00409 temperature, 00410 luminosity, 00411 current ); 00412 00413 if((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) 00414 { 00415 log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret); 00416 } 00417 else 00418 { 00419 printf("Ok, Successfully Sent Data to Gateway...\r\n"); 00420 } 00421 00422 /* 00423 //--------------------------------------------------------------------------- 00424 // Binary Encoded Format: Most Data Payload, Not Human Readible 00425 //--------------------------------------------------------------------------- 00426 mdot_data.clear(); 00427 mdot_data.push_back(0x0E); // key for Current Acceleration 3-Axis Value 00428 converts.f_s = accel_data._x *4; // shift data 2 bits while retaining sign 00429 mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value 00430 converts.f_s = accel_data._y * 4; // shift data 2 bits while retaining sign 00431 mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value 00432 converts.f_s = accel_data._z * 4; // shift data 2 bits while retaining sign 00433 mdot_data.push_back(converts.t_u[1]); // get 8 MSB of 14 bit value 00434 mdot_data.push_back(0x08); // key for Current Pressure Value 00435 convertl.f_u = pressure; // pressure data is 20 bits unsigned 00436 mdot_data.push_back(convertl.t_u[2]); 00437 mdot_data.push_back(convertl.t_u[1]); 00438 mdot_data.push_back(convertl.t_u[0]); 00439 mdot_data.push_back(0x05); // key for Current Ambient Light Value 00440 converts.f_u = lux_data; // data is 16 bits unsigned 00441 mdot_data.push_back(converts.t_u[1]); 00442 mdot_data.push_back(converts.t_u[0]); 00443 mdot_data.push_back(0x0B); // key for Current Temperature Value 00444 converts.f_s = baro_data._temp; // temperature is signed 12 bit 00445 mdot_data.push_back(converts.t_u[1]); 00446 mdot_data.push_back(converts.t_u[0]); 00447 00448 if ((mdot_ret = mdot_radio->send(mdot_data)) != mDot::MDOT_OK) 00449 { 00450 log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret); 00451 } 00452 else 00453 { 00454 printf("Ok, Successfully Sent Data to Gateway...\r\n"); 00455 } 00456 */ 00457 00458 osDelay(500); 00459 00460 printf("Scanning... \r\n"); 00461 cycle_cnt = 0; 00462 } 00463 00464 s2_last = s2; 00465 lum_last = luminosity; 00466 00467 osDelay(1000); 00468 cycle_cnt++; 00469 00470 // Put Thread to Sleep for 30 Seconds... 00471 // osDelay(30000); 00472 00473 } while(i < 86400); 00474 00475 printf("End of Data Collection Cycle (24 Hours) - Ending Application, GoodBye...\r\n"); 00476 } 00477 00478 /*=================================================================================== 00479 Send String Payload to Conduit Gateway 00480 ===================================================================================*/ 00481 int32_t sendString(const std::string text) 00482 { 00483 int32_t ret; 00484 if (mdot_radio->getNextTxMs() != 0) 00485 { 00486 printf("Sending in %lu ms...\r\n", mdot_radio->getNextTxMs()); 00487 return false; 00488 } 00489 00490 printf("Sending: '%s'\r\n", text.c_str()); 00491 std::vector<uint8_t> data(text.begin(), text.end()); 00492 if ((ret = mdot_radio->send(data, 1)) != mDot::MDOT_OK) 00493 { 00494 log_error(mdot_radio, "ERROR: Failed to Send Data", ret); 00495 } 00496 00497 led = 0; 00498 00499 return ret; 00500 } 00501 00502 /*=================================================================================== 00503 Transmit Data Payload to Cloud Platform 00504 ===================================================================================*/ 00505 int32_t xmitDataPayload( int temperature, int luminosity, int current ) 00506 { 00507 int32_t mdot_ret; 00508 00509 printf("Transmitting Data... \r\n"); 00510 00511 sprintf(sensor_text, "t:%d,l:%d,c:%d", temperature, luminosity, current ); 00512 00513 if((mdot_ret = sendString((const std::string)sensor_text)) != mDot::MDOT_OK) 00514 { 00515 log_error(mdot_radio, "ERROR: Failed to Send Data", mdot_ret); 00516 } 00517 else 00518 { 00519 printf("Ok, Successfully Sent Data to Gateway...\r\n"); 00520 } 00521 00522 return mdot_ret; 00523 } 00524 00525 /*=================================================================================== 00526 Print clear text verion of mDot/EVB errors 00527 ===================================================================================*/ 00528 void log_error(mDot* dot, const char* msg, int32_t retval) 00529 { 00530 printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str()); 00531 }
Generated on Tue Jul 12 2022 13:07:57 by
1.7.2