UDK + Shield
Dependencies: DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B libmDot_1012-hotifx mbed-rtos mbed-src Senet_Packet X_NUCLEO_IKS01A1
Fork of MTDOT-EVBDemo_Senet by
main.cpp
00001 /** 00002 * @file main.cpp 00003 * @brief Main application for mDot-EVB demo 00004 * @author Tim Barr MultiTech Systems Inc. 00005 * @version 1.03 00006 * @see 00007 * 00008 * Copyright (c) 2015 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 * 00022 * 1.01 TAB 7/6/15 Removed NULL pointer from evbAmbientLight creation call. 00023 * 00024 * 1.02 TAB 7/8/15 Send logo to LCD before attempting connection to LoRa network. Added 00025 * information on setting up for public LoRa network. Moved SW setup to 00026 * beginning of main. Removed printf call from ISR functions. Added 00027 * additional checks for exit_program. 00028 * 00029 * 1.03 TAB 7/15/15 Added threads for push button switch debounce. 00030 * 00031 */ 00032 00033 #include "mbed.h" 00034 #include "senet_packet.h" 00035 00036 #if !defined(MTDOT_EVB) && !defined(MTDOT_UDK) 00037 #define MTDOT_UDK 00038 #define REFLECT_FAST_TX 00039 #endif 00040 00041 // EVB Sensors 00042 #ifdef MTDOT_EVB 00043 00044 #include "MMA845x.h" 00045 #include "MPL3115A2.h" 00046 #include "ISL29011.h" 00047 #include "NCP5623B.h" 00048 #include "DOGS102.h" 00049 #include "font_6x8.h" 00050 #include "MultiTech_Logo.h" 00051 00052 // Added period delay 00053 #define PERIOD_DELAY 0 00054 00055 // Fast send period 00056 #define FAST_SEND_PERIOD pckt_time 00057 00058 // Send frame period 00059 #define SEND_PERIOD 100 00060 00061 #elif defined(MTDOT_UDK) 00062 00063 #include "x_nucleo_iks01a1.h" 00064 00065 // Added period delay 00066 #define PERIOD_DELAY 3000 00067 00068 // Fast send period 00069 #define FAST_SEND_PERIOD 1 00070 00071 // Send frame period 00072 #define SEND_PERIOD 10 00073 00074 #endif 00075 00076 #include "mDot.h" 00077 #include "rtos.h" 00078 #include <string> 00079 #include <vector> 00080 00081 /* 00082 * Board sensor data 00083 */ 00084 struct BoardSensorData 00085 { 00086 float temperature; 00087 float pressure; 00088 int32_t accel_x; 00089 int32_t accel_y; 00090 int32_t accel_z; 00091 00092 inline void init() 00093 { 00094 temperature= 0; 00095 pressure = 0; 00096 accel_x = 0; 00097 accel_y = 0; 00098 accel_z = 0; 00099 } 00100 00101 BoardSensorData() { init(); } 00102 }; 00103 00104 #ifdef MTDOT_EVB 00105 00106 //DigitalIn mDot02(PA_2); // GPIO/UART_TX 00107 //DigitalOut mDot03(PA_3); // GPIO/UART_RX 00108 //DigitalIn mDot04(PA_6); // GPIO/SPI_MISO 00109 //DigitalIn mDot06(PA_8); // GPIO/I2C_SCL 00110 //DigitalIn mDot07(PC_9); // GPIO/I2C_SDA 00111 00112 InterruptIn mDot08(PA_12); // GPIO/USB PB S1 on EVB 00113 InterruptIn mDot09(PA_11); // GPIO/USB PB S2 on EVB 00114 00115 //DigitalIn mDot11(PA_7); // GPIO/SPI_MOSI 00116 00117 InterruptIn mDot12(PA_0); // GPIO/UART_CTS PRESSURE_INT2 on EVB 00118 DigitalOut mDot13(PC_13,1); // GPIO LCD_C/D 00119 InterruptIn mDot15(PC_1); // GPIO LIGHT_PROX_INT on EVB 00120 InterruptIn mDot16(PA_1); // GPIO/UART_RTS ACCEL_INT2 on EVB 00121 DigitalOut mDot17(PA_4,1); // GPIO/SPI_NCS LCD_CS on EVB 00122 00123 //DigitalIn mDot18(PA_5); // GPIO/SPI_SCK 00124 00125 //DigitalInOut mDot19(PB_0,PIN_INPUT,PullNone,0); // GPIO PushPull LED Low=Red High=Green set MODE=INPUT to turn off 00126 AnalogIn mDot20(PB_1); // GPIO Current Sense Analog in on EVB 00127 Serial debugUART(PA_9, PA_10); // mDot debug UART 00128 //Serial mDotUART(PA_2, PA_3); // mDot external UART mDot02 and mDot03 00129 I2C mDoti2c(PC_9,PA_8); // mDot External I2C mDot6 and mDot7 00130 00131 SPI mDotspi(PA_7,PA_6,PA_5); // mDot external SPI mDot11, mDot4, and mDot18 00132 #elif defined(MTDOT_UDK) 00133 00134 Serial debugUART(USBTX, USBRX); // mDot debug UART 00135 00136 #endif 00137 00138 /* 00139 * LoRaWAN Configuration 00140 */ 00141 00142 // Senet Developer Portal Application EUI 00143 static uint8_t app_id[8] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01}; 00144 00145 // Get Application Key from Senet Developer Portal Device Edit page 00146 static uint8_t app_key[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; 00147 00148 static std::vector<uint8_t> config_app_id(app_id,app_id+sizeof(app_id)/sizeof(uint8_t)); 00149 static std::vector<uint8_t> config_app_key(app_key,app_key+sizeof(app_key)/sizeof(uint8_t)); 00150 static uint8_t config_frequency_sub_band = 0; 00151 static bool config_adr_on = true; 00152 00153 bool position_changed = true; 00154 uint32_t sample_period = 0; 00155 00156 #ifdef MTDOT_EVB 00157 MMA845x_DATA accel_data; 00158 MPL3115A2_DATA baro_data; 00159 uint16_t lux_data; 00160 MMA845x* evbAccel; 00161 MPL3115A2* evbBaro; 00162 ISL29011* evbAmbLight; 00163 NCP5623B* evbBackLight; 00164 DOGS102* evbLCD; 00165 00166 /* 00167 * EVB Application state 00168 */ 00169 uint8_t position_value = 0xFF; // 00 unknown, 01 is flat, 02 is vertical 00170 uint8_t reflected_value = 0xFE; 00171 00172 unsigned char test; 00173 char txtstr[17]; 00174 int32_t num_whole; 00175 uint32_t pressure; 00176 int16_t num_frac; 00177 uint8_t result, pckt_time=100; 00178 char data; 00179 // flags for pushbutton debounce code 00180 bool pb1_low = false; 00181 bool pb2_low = false; 00182 00183 void pb1ISR(void); 00184 void pb2ISR(void); 00185 void pb1_debounce(void const *args); 00186 void pb2_debounce(void const *args); 00187 Thread* thread_3; 00188 00189 void config_pkt_xmit (void const *args); 00190 00191 #elif defined(MTDOT_UDK) 00192 00193 uint16_t position_value = 0; 00194 uint16_t reflected_value = 0; 00195 00196 static X_NUCLEO_IKS01A1 *mems_shield; 00197 00198 #endif 00199 00200 mDot* mdot_radio; 00201 bool exit_program = false; 00202 Ticker joinTicker; 00203 DigitalOut APP_LED(PA_0); 00204 00205 // join status 00206 #define JOIN_LED APP_LED 00207 00208 // server sync status 00209 #define SYNC_LED APP_LED 00210 00211 #define SYNC_LED_OK 0 // synced 00212 #define SYNC_LED_OOS 1 // out of sync 00213 00214 00215 /* 00216 * Process downlink 00217 */ 00218 static void ReceiveData(std::vector<uint8_t> frame); 00219 00220 static bool checkForExit(bool exit); 00221 00222 /* 00223 * prints of mDot error 00224 */ 00225 void log_error(mDot* dot, const char* msg, int32_t retval) 00226 { 00227 printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str()); 00228 } 00229 00230 /* 00231 * Send frame 00232 */ 00233 void SendFrame(std::vector<uint8_t> frame) 00234 { 00235 int32_t mdot_ret; 00236 00237 if ((mdot_ret = mdot_radio->send(frame)) != mDot::MDOT_OK) { 00238 log_error(mdot_radio, "failed to send", mdot_ret); 00239 } 00240 else { 00241 printf("successfully sent data\r\n"); 00242 frame.clear(); 00243 if ((mdot_ret = mdot_radio->recv(frame)) == mDot::MDOT_OK) { 00244 printf("recv data: "); 00245 for(uint32_t i = 0;i < frame.size();i++) 00246 printf("%02X",frame[i]); 00247 printf("\r\n"); 00248 00249 ReceiveData(frame); 00250 } 00251 position_changed = false; 00252 } 00253 } 00254 00255 #ifdef MTDOT_EVB 00256 00257 void ReceiveData(std::vector<uint8_t> frame) 00258 { 00259 reflected_value = frame[0]; 00260 00261 if(reflected_value == position_value) 00262 { 00263 evbBackLight->setLEDCurrent(16); 00264 // Set LED to indicate server in agreement 00265 SYNC_LED=SYNC_LED_OK; 00266 } 00267 else 00268 { 00269 evbBackLight->setLEDCurrent(0); 00270 } 00271 } 00272 00273 void BoardInit() 00274 { 00275 static Thread thread_1(pb1_debounce); // threads for de-bouncing pushbutton switches 00276 static Thread thread_2(pb2_debounce); 00277 00278 debugUART.baud(115200); 00279 // mDotUART.baud(9600); // mdot UART unused but available on external connector 00280 00281 thread_3 = new Thread(config_pkt_xmit); // start thread that sends LoRa packet when SW2 pressed 00282 00283 evbAccel = new MMA845x(mDoti2c,MMA845x::SA0_VSS); // setup Accelerometer 00284 evbBaro = new MPL3115A2(mDoti2c); // setup Barometric sensor 00285 evbAmbLight = new ISL29011(mDoti2c); // Setup Ambient Light Sensor 00286 evbBackLight = new NCP5623B(mDoti2c); // setup backlight and LED 2 driver chip 00287 evbLCD = new DOGS102(mDotspi, mDot17, mDot13); // setup LCD 00288 00289 /* 00290 * Setup SW1 as program stop function 00291 */ 00292 mDot08.disable_irq(); 00293 mDot08.fall(&pb1ISR); 00294 00295 /* 00296 * need to call this function after rise or fall because rise/fall sets 00297 * mode to PullNone 00298 */ 00299 mDot08.mode(PullUp); 00300 00301 mDot08.enable_irq(); 00302 00303 /* 00304 * Setup SW2 as packet time change 00305 */ 00306 mDot09.disable_irq(); 00307 mDot09.fall(&pb2ISR); 00308 00309 /* 00310 * need to call this function after rise or fall because rise/fall sets 00311 * mode to PullNone 00312 */ 00313 mDot09.mode(PullUp); 00314 00315 mDot09.enable_irq(); 00316 00317 /* 00318 * Setting other InterruptIn pins with Pull Ups 00319 */ 00320 mDot12.mode(PullUp); 00321 mDot15.mode(PullUp); 00322 mDot16.mode(PullUp); 00323 00324 printf("font table address %p\n\r",&font_6x8); 00325 printf("bitmap address %p\n\r",&MultiTech_Logo); 00326 00327 // Setup and display logo on LCD 00328 evbLCD->startUpdate(); 00329 00330 evbLCD->writeBitmap(0,0,MultiTech_Logo); 00331 00332 sprintf(txtstr,"MTDOT"); 00333 evbLCD->writeText(24,3,font_6x8,txtstr,strlen(txtstr)); 00334 sprintf(txtstr,"Evaluation"); 00335 evbLCD->writeText(24,4,font_6x8,txtstr,strlen(txtstr)); 00336 sprintf(txtstr,"Board"); 00337 evbLCD->writeText(24,5,font_6x8,txtstr,strlen(txtstr)); 00338 00339 evbLCD->endUpdate(); 00340 00341 pckt_time = 10; 00342 } 00343 00344 void PostJoinInit() 00345 { 00346 osDelay(200); 00347 evbBackLight->setPWM(NCP5623B::LED_3,16); // enable LED2 on EVB and set to 50% PWM 00348 00349 // sets LED2 to 50% max current 00350 evbBackLight->setLEDCurrent(16); 00351 00352 printf("Start of Test\n\r"); 00353 00354 osDelay (500); // allows other threads to process 00355 printf("shutdown LED:\n\r"); 00356 evbBackLight->shutdown(); 00357 00358 osDelay (500); // allows other threads to process 00359 printf("Turn on LED2\n\r"); 00360 evbBackLight->setLEDCurrent(16); 00361 00362 data = evbAccel->getWhoAmI(); 00363 printf("Accelerometer who_am_i value = %x \n\r", data); 00364 00365 result = evbAccel->getStatus(); 00366 printf("status byte = %x \n\r", result); 00367 00368 printf("Barometer who_am_i check = %s \n\r", evbBaro->testWhoAmI() ? "TRUE" : "FALSE"); 00369 00370 result = evbBaro->getStatus(); 00371 printf("status byte = %x \n\r", result); 00372 00373 /* 00374 * Setup the Accelerometer for 8g range, 14 bit resolution, Noise reduction off, sample rate 1.56 Hz 00375 * normal oversample mode, High pass filter off 00376 */ 00377 evbAccel->setCommonParameters(MMA845x::RANGE_8g,MMA845x::RES_MAX,MMA845x::LN_OFF, 00378 MMA845x::DR_1_56,MMA845x::OS_NORMAL,MMA845x::HPF_OFF ); 00379 00380 /* 00381 * Setup the Barometric sensor for post processed Ambient pressure, 4 samples per data acquisition. 00382 * and a sample taken every second when in active mode 00383 */ 00384 evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, 00385 MPL3115A2::AT_1); 00386 /* 00387 * Setup the Ambient Light Sensor for continuous Ambient Light Sensing, 16 bit resolution, 00388 * and 16000 lux range 00389 */ 00390 00391 evbAmbLight->setMode(ISL29011::ALS_CONT); 00392 evbAmbLight->setResolution(ISL29011::ADC_16BIT); 00393 evbAmbLight->setRange(ISL29011::RNG_16000); 00394 00395 /* 00396 * Set the accelerometer for active mode 00397 */ 00398 evbAccel->activeMode(); 00399 00400 /* 00401 * Clear the min-max registers in the Barometric Sensor 00402 */ 00403 evbBaro->clearMinMaxRegs(); 00404 00405 evbBackLight->setLEDCurrent(0); 00406 00407 /* 00408 * Check for PB1 press during network join attempt 00409 */ 00410 if (exit_program) { 00411 printf("Exiting program\n\r"); 00412 evbLCD->clearBuffer(); 00413 sprintf(txtstr,"Exiting Program"); 00414 evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); 00415 exit(1); 00416 } 00417 } 00418 00419 void ReadSensors(BoardSensorData &sensorData) 00420 { 00421 MMA845x_DATA accel_data; 00422 /* 00423 * Test Accelerometer XYZ data ready bit to see if acquisition complete 00424 */ 00425 do { 00426 osDelay(100); // allows other threads to process 00427 result = evbAccel->getStatus(); 00428 } while ((result & MMA845x::XYZDR) == 0 ); 00429 00430 /* 00431 * Retrieve and print out accelerometer data 00432 */ 00433 accel_data = evbAccel->getXYZ(); 00434 00435 sprintf(txtstr,"Accelerometer"); 00436 evbLCD->writeText(0,0,font_6x8,txtstr,strlen(txtstr)); 00437 sprintf(txtstr, "x = %d", accel_data._x); 00438 evbLCD->writeText(20,1,font_6x8,txtstr,strlen(txtstr)); 00439 sprintf(txtstr, "y = %d", accel_data._y); 00440 evbLCD->writeText(20,2,font_6x8,txtstr,strlen(txtstr)); 00441 sprintf(txtstr, "z = %d", accel_data._z ); 00442 evbLCD->writeText(20,3,font_6x8,txtstr,strlen(txtstr)); 00443 00444 sensorData.accel_x = accel_data._x; 00445 sensorData.accel_y = accel_data._y; 00446 sensorData.accel_z = accel_data._z; 00447 00448 // Update accelerometer state 00449 evbLCD->startUpdate(); 00450 evbLCD->clearBuffer(); 00451 00452 // convert to simple position value for use in send/recv 00453 if((accel_data._x > 500)&&(accel_data._z < 500)) 00454 { 00455 if(position_value != 0x02) 00456 position_changed = true; 00457 position_value = 0x02; 00458 } 00459 else if((accel_data._x < 500)&&(accel_data._z > 500)) 00460 { 00461 if(position_value != 0x01) 00462 position_changed = true; 00463 position_value = 0x01; 00464 } 00465 else 00466 { 00467 if(position_value != 0x00) 00468 position_changed = true; 00469 position_value= 0x00; 00470 } 00471 00472 if(position_changed){ 00473 evbBackLight->setLEDCurrent(0); 00474 // Turn LED off to indicate server not in agreement 00475 SYNC_LED=SYNC_LED_OOS; 00476 // Set reflected_value to an out of range value to stay 00477 // in fast transmit mode until server responds 00478 reflected_value = 0; 00479 } 00480 00481 /* 00482 * Trigger a Pressure reading 00483 */ 00484 evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_BAROMETER, MPL3115A2::OR_16, 00485 MPL3115A2::AT_1); 00486 evbBaro->triggerOneShot(); 00487 00488 /* 00489 * Test barometer device status to see if acquisition is complete 00490 */ 00491 do { 00492 osDelay(100); // allows other threads to process 00493 result = evbBaro->getStatus(); 00494 } while ((result & MPL3115A2::PTDR) == 0 ); 00495 00496 /* 00497 * Retrieve and print out barometric pressure 00498 */ 00499 pressure = evbBaro->getBaroData() >> 12; // convert 32 bit signed to 20 bit unsigned value 00500 num_whole = pressure >> 2; // 18 bit integer significant 00501 num_frac = (pressure & 0x3) * 25; // 2 bit fractional 0.25 per bit 00502 sensorData.pressure = pressure + (.25 * num_frac); 00503 00504 sprintf(txtstr,"Press=%ld.%02d Pa", num_whole, num_frac); 00505 evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); 00506 00507 /* 00508 * Trigger a Altitude reading 00509 */ 00510 evbBaro->setParameters(MPL3115A2::DATA_NORMAL, MPL3115A2::DM_ALTIMETER, MPL3115A2::OR_16, 00511 MPL3115A2::AT_1); 00512 evbBaro->triggerOneShot(); 00513 00514 /* 00515 * Test barometer device status to see if acquisition is complete 00516 */ 00517 do { 00518 osDelay(100); // allows other threads to process 00519 result = evbBaro->getStatus(); 00520 } while ((result & MPL3115A2::PTDR) == 0 ); 00521 00522 /* 00523 * Retrieve and print out altitude and temperature 00524 */ 00525 baro_data = evbBaro->getAllData(false); 00526 baro_data._baro /= 4096; // convert 32 bit signed to 20 bit signed value 00527 num_whole = baro_data._baro / 16; // 18 bit signed significant integer 00528 num_frac = (baro_data._baro & 0xF) * 625 / 100; // 4 bit fractional .0625 per bit 00529 sprintf(txtstr,"Alti=%ld.%03d m", num_whole, num_frac); 00530 evbLCD->writeText(0,5,font_6x8,txtstr,strlen(txtstr)); 00531 num_whole = baro_data._temp / 16; // 8 bit signed significant integer 00532 num_frac = (baro_data._temp & 0x0F) * 625 / 100; // 4 bit fractional .0625 per bit 00533 sensorData.temperature = num_whole + ((float)num_frac / 100); 00534 sprintf(txtstr,"Temp=%ld.%03d C", num_whole, num_frac); 00535 evbLCD->writeText(0,6,font_6x8,txtstr,strlen(txtstr)); 00536 00537 /* 00538 * retrieve and print out Ambient Light level 00539 */ 00540 lux_data = evbAmbLight->getData(); 00541 num_whole = lux_data * 24 / 100; // 16000 lux full scale .24 lux per bit 00542 num_frac = lux_data * 24 % 100; 00543 sprintf(txtstr, "Light=%ld.%02d lux", num_whole, num_frac ); 00544 evbLCD->writeText(0,7,font_6x8,txtstr,strlen(txtstr)); 00545 00546 evbLCD->endUpdate(); 00547 } 00548 00549 uint32_t PrepareFrame(std::vector<uint8_t> &frame, BoardSensorData &data) 00550 { 00551 frame.clear(); 00552 00553 #ifdef REFLECT_FAST_TX 00554 if((reflected_value != position_value)|| position_changed || ( ( sample_period % SEND_PERIOD ) == 0 ) ) 00555 #else 00556 if( position_changed || ( ( sample_period % SEND_PERIOD ) == 0 ) ) 00557 #endif 00558 { 00559 // we will send a simple byte descriptor of the current position of the device: 01 is laying flat, 02 is vertically oriented 00560 frame.push_back(0x00); 00561 frame.push_back(position_value); 00562 } 00563 00564 return frame.size(); 00565 } 00566 00567 bool checkForExit(bool _exit) 00568 { 00569 // Check for PB1 press during network join attempt 00570 if (exit_program) { 00571 printf("Exiting program\n\r"); 00572 evbLCD->clearBuffer(); 00573 sprintf(txtstr,"Exiting Program"); 00574 evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); 00575 if(_exit) 00576 exit(1); 00577 } 00578 00579 return false; 00580 } 00581 00582 void ExitingProgram() 00583 { 00584 evbBaro->triggerOneShot(); 00585 do { 00586 osDelay(200); // allows other threads to process 00587 result = evbBaro->getStatus(); 00588 } while ((result & MPL3115A2::PTDR) == 0 ); 00589 00590 baro_data = evbBaro->getAllData(true); 00591 printf ("minBaro=%ld maxBaro=%ld minTemp=%d maxTemp=%d\n\r", baro_data._minbaro, baro_data._maxbaro, 00592 baro_data._mintemp, baro_data._maxtemp); 00593 evbLCD->clearBuffer(); 00594 sprintf(txtstr,"Exiting Program"); 00595 evbLCD->writeText(0,4,font_6x8,txtstr,strlen(txtstr)); 00596 printf("End of Test\n\r"); 00597 } 00598 00599 00600 /* 00601 * Sets pb1_low flag. Slag is cleared in pb1_debounce thread 00602 */ 00603 void pb1ISR(void) 00604 { 00605 if (!pb1_low) 00606 pb1_low = true; 00607 } 00608 00609 /* 00610 * Debounces pb1. Also exits program if pushbutton 1 is pressed 00611 */ 00612 void pb1_debounce(void const *args) 00613 { 00614 static uint8_t count = 0; 00615 00616 while (true) { 00617 if (pb1_low && (mDot08 == 0)) 00618 count++; 00619 else { 00620 count = 0; 00621 pb1_low = false; 00622 } 00623 00624 if (count == 5) 00625 exit_program = true; 00626 00627 Thread::wait(5); 00628 } 00629 } 00630 00631 /* 00632 * Sets pb2_low flag. Flag is cleared in pb2_debounce thread 00633 */ 00634 void pb2ISR(void) 00635 { 00636 if (!pb2_low) 00637 pb2_low = true; 00638 } 00639 00640 /* 00641 * Debounces pb2. Also changes packet transmit time to every other, 00642 * every fifth, or every tenth sample when SW2 pushed 00643 * Also triggers a thread to transmit a configuration packet 00644 */ 00645 void pb2_debounce(void const *args) 00646 { 00647 static uint8_t count = 0; 00648 00649 while (true) { 00650 00651 if (pb2_low && (mDot09 == 0)) 00652 count++; 00653 else { 00654 count = 0; 00655 pb2_low = false; 00656 } 00657 00658 if (count == 5){ 00659 if (pckt_time >= 5) 00660 pckt_time /= 2; 00661 else 00662 pckt_time = 20; 00663 00664 //thread_3->signal_set(0x10); // signal config_pkt_xmit to send packet 00665 position_changed = true; 00666 } 00667 Thread::wait(5); 00668 } 00669 } 00670 00671 /* 00672 * Thread that is triggered by SW2 ISR. Sends a packet to the LoRa server with the new Packet Transmission time setting 00673 */ 00674 void config_pkt_xmit (void const *args) 00675 { 00676 int32_t mdot_ret; 00677 00678 std::vector<uint8_t> data; 00679 00680 while (true) { 00681 Thread::signal_wait(0x10); // wait for pb2ISR to signal send 00682 data.clear(); 00683 data.push_back(0x0F); // key for Configuration data (packet transmission timer) 00684 data.push_back(pckt_time); 00685 00686 if ((mdot_ret = mdot_radio->send(data)) != mDot::MDOT_OK) { 00687 log_error(mdot_radio, "failed to send config data", mdot_ret); 00688 } else { 00689 printf("sent config data to gateway\r\n"); 00690 } 00691 } 00692 } 00693 00694 #elif defined(MTDOT_UDK) 00695 00696 void ReceiveData(std::vector<uint8_t> frame) 00697 { 00698 uint16_t value; 00699 00700 if(frame.size() >= 2) 00701 { 00702 value = frame[0] << 8 | frame[1]; 00703 if(value == position_value) 00704 { 00705 reflected_value = value; 00706 // Turn LED on to indicate server in agreement 00707 SYNC_LED=SYNC_LED_OK; 00708 } 00709 } 00710 } 00711 00712 void BoardInit() 00713 { 00714 debugUART.baud(115200); 00715 00716 // ST X-NUCLEO-IKS01A1 MEMS Shield 00717 mems_shield = X_NUCLEO_IKS01A1::Instance(NULL, NC); 00718 // mems_shield = X_NUCLEO_IKS01A1::Instance(); 00719 } 00720 00721 void PostJoinInit() { } 00722 00723 00724 void ReadSensors(BoardSensorData &data) 00725 { 00726 uint32_t ret = 0; 00727 int32_t accel_data[3]; 00728 00729 // Temperature 00730 ret |= (!CALL_METH(mems_shield->pt_sensor, GetTemperature, &data.temperature, 0.0f) ? 0x0 : 0x1); 00731 00732 // Pressure 00733 ret |= (!CALL_METH(mems_shield->pt_sensor, GetPressure, &data.pressure, 0.0f) ? 0x0 : 0x1); 00734 00735 // Accelerometer 00736 MotionSensor *motionSensor = mems_shield->GetAccelerometer(); 00737 if( motionSensor != NULL) 00738 { 00739 motionSensor->Get_X_Axes(accel_data); 00740 00741 data.accel_x = accel_data[0]; 00742 data.accel_y = accel_data[1]; 00743 data.accel_z = accel_data[2]; 00744 /* z-axis : > 0 = rightside up, < 0 upside down 00745 * x-axis: com LED to the left x < 0, x > 0 on the right 00746 * y-axis: y > 0 COM LED down, y < 0 COM LED up 00747 */ 00748 bool up = false; 00749 bool down = false; 00750 bool right = false; 00751 bool left = false; 00752 bool horizontal = false; 00753 bool upsidedown = false; 00754 uint16_t next_value = 0; 00755 00756 // rightside up 00757 if(data.accel_z >= 750) 00758 { 00759 horizontal = true; 00760 } 00761 // upside down 00762 else if(data.accel_z <= -750) 00763 { 00764 horizontal = true; 00765 upsidedown = true; 00766 position_value = (2 << 12) | (1 << 8); 00767 } 00768 // vertical down 00769 else if(data.accel_y >= 900 ) 00770 { 00771 down = true; 00772 } 00773 // vertical up 00774 else if(data.accel_y <= -900 ) 00775 { 00776 up = true; 00777 } 00778 // side right 00779 else if(data.accel_x > 900) 00780 { 00781 right = true; 00782 } 00783 // side left 00784 else 00785 { 00786 left = true; 00787 } 00788 00789 if(horizontal) 00790 { 00791 next_value = (2 << 12) | (upsidedown << 8); 00792 } 00793 else 00794 { 00795 next_value = (up << 12) | (left << 8) | (down << 4) | right; 00796 } 00797 00798 if(next_value != position_value) 00799 { 00800 position_value = next_value; 00801 position_changed = true; 00802 00803 // Set reflected_value to an out of range value to stay 00804 // in fast transmit mode until server responds 00805 reflected_value = 0; 00806 00807 // Turn LED off to indicate server is not in agreement 00808 SYNC_LED=SYNC_LED_OOS; 00809 } 00810 } 00811 00812 printf("%s: position_value=%04x, reflected_value=%04x\r\n",__func__, position_value, reflected_value); 00813 } 00814 00815 uint32_t PrepareFrame(std::vector<uint8_t> &frame, BoardSensorData &data) 00816 { 00817 static uint8_t buffer[64]; 00818 00819 frame.clear(); 00820 00821 // Sensor packet type serialized to the LMIC frame buffer 00822 SensorPacket packet(buffer, sizeof(buffer)); 00823 00824 #ifdef REFLECT_FAST_TX 00825 if( position_changed || (reflected_value != position_value) || ( ( sample_period % SEND_PERIOD ) == 0 ) ) 00826 #else 00827 if( position_changed || ( ( sample_period % SEND_PERIOD ) == 0 ) ) 00828 #endif 00829 { 00830 packet.setPrimarySensor(position_value); 00831 packet.setTemperature(data.temperature); 00832 packet.setPressure(data.pressure); 00833 00834 // Serialize packet 00835 packet.serialize(); 00836 00837 frame.assign(packet.payload(), packet.payload() + packet.length()); 00838 } 00839 00840 return frame.size(); 00841 } 00842 00843 bool checkForExit(bool _exit) { return false;} 00844 00845 00846 void ExitingProgram() 00847 { 00848 printf("Exiting\n\r"); 00849 } 00850 00851 #else 00852 #error Board type not defined! 00853 #endif 00854 00855 void joinLedToggle() 00856 { 00857 JOIN_LED = !JOIN_LED; 00858 } 00859 00860 void mDotConfigureAndJoin() 00861 { 00862 bool ok; 00863 int32_t mdot_ret; 00864 00865 printf("Configuring mDot\r\n"); 00866 00867 // get mDot handle 00868 mdot_radio = mDot::getInstance(); 00869 if(mdot_radio == NULL) 00870 { 00871 while(1) { 00872 printf("radio setup failed\n\r"); 00873 osDelay(1000); 00874 } 00875 } 00876 00877 do{ 00878 ok = true; 00879 00880 printf("\n\r setup mdot\n\r"); 00881 00882 // reset to default config so we know what state we're in 00883 mdot_radio->resetConfig(); 00884 //mdot_radio->setLogLevel(6); 00885 00886 mdot_radio->setAntennaGain(-3); 00887 00888 // Setting up LED1 as activity LED 00889 #ifdef MTDOT_EVB 00890 mdot_radio->setActivityLedPin(PB_0); 00891 mdot_radio->setActivityLedEnable(true); 00892 #endif 00893 00894 // Read node ID 00895 std::vector<uint8_t> mdot_EUI; 00896 mdot_EUI = mdot_radio->getDeviceId(); 00897 printf("mDot EUI = "); 00898 00899 for (uint8_t i=0; i<mdot_EUI.size(); i++) { 00900 printf("%02x ", mdot_EUI[i]); 00901 } 00902 printf("\n\r"); 00903 00904 00905 /* 00906 * This call sets up private or public mode on the MTDOT. Set the function to true if 00907 * connecting to a public network 00908 */ 00909 printf("setting Public Network Mode\r\n"); 00910 if ((mdot_ret = mdot_radio->setPublicNetwork(true)) != mDot::MDOT_OK) { 00911 log_error(mdot_radio, "failed to set Public Network Mode", mdot_ret); 00912 } 00913 mdot_radio->setTxDataRate(mDot::DR0); 00914 mdot_radio->setTxPower(14); 00915 mdot_radio->setJoinRetries(1); 00916 mdot_radio->setJoinMode(mDot::OTA); 00917 00918 /* 00919 * Frequency sub-band is valid for NAM only and for Private networks should be set to a value 00920 * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only. 00921 * This function can be commented out for EU networks 00922 */ 00923 printf("setting frequency sub band\r\n"); 00924 if ((mdot_ret = mdot_radio->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) { 00925 log_error(mdot_radio, "failed to set frequency sub band", mdot_ret); 00926 ok = false; 00927 } 00928 00929 printf("setting ADR\r\n"); 00930 if ((mdot_ret = mdot_radio->setAdr(config_adr_on)) != mDot::MDOT_OK) { 00931 log_error(mdot_radio, "failed to set ADR", mdot_ret); 00932 ok = false; 00933 } 00934 00935 /* 00936 * setNetworkName is used for private networks. 00937 * Use setNetworkID(AppID) for public networks 00938 */ 00939 printf("setting network name\r\n"); 00940 if ((mdot_ret = mdot_radio->setNetworkId(config_app_id)) != mDot::MDOT_OK) { 00941 log_error(mdot_radio, "failed to set network name", mdot_ret); 00942 ok = false; 00943 } 00944 00945 /* 00946 * setNetworkPassphrase is used for private networks 00947 * Use setNetworkKey for public networks 00948 */ 00949 printf("setting network key\r\n"); 00950 if ((mdot_ret = mdot_radio->setNetworkKey(config_app_key)) != mDot::MDOT_OK) { 00951 log_error(mdot_radio, "failed to set network password", mdot_ret); 00952 ok = false; 00953 } 00954 00955 checkForExit(true); 00956 00957 }while(ok == false); 00958 00959 joinTicker.attach(joinLedToggle,1); 00960 00961 // attempt to join the network 00962 printf("joining network\r\n"); 00963 while ((mdot_ret = mdot_radio->joinNetwork()) != mDot::MDOT_OK) { 00964 log_error(mdot_radio,"failed to join network:", mdot_ret); 00965 if (mdot_radio->getFrequencyBand() == mDot::FB_868){ 00966 mdot_ret = mdot_radio->getNextTxMs(); 00967 } 00968 else { 00969 mdot_ret = 0; 00970 } 00971 checkForExit(true); 00972 printf("delay = %lu\n\r",mdot_ret); 00973 osDelay(mdot_ret + 10000); 00974 } 00975 printf("network joined\r\n"); 00976 00977 joinTicker.detach(); 00978 JOIN_LED=1; 00979 } 00980 00981 00982 int main() 00983 { 00984 BoardSensorData sensorData; 00985 std::vector<uint8_t> frame; 00986 00987 // Board specific initialization 00988 BoardInit(); 00989 00990 // Configure mDot and join 00991 mDotConfigureAndJoin(); 00992 00993 // Do board specific post join configuration 00994 PostJoinInit(); 00995 00996 /* 00997 * Main data acquisition loop 00998 */ 00999 while(!checkForExit(false)) 01000 { 01001 if( PERIOD_DELAY > 0 ) 01002 osDelay( PERIOD_DELAY ); 01003 01004 // Minimum delay between sampling 01005 if( ( sample_period % FAST_SEND_PERIOD ) == 0 ) 01006 { 01007 // Acquire sensor values 01008 ReadSensors(sensorData); 01009 01010 // Generate frame if send conditions are satisified 01011 if( PrepareFrame(frame, sensorData) > 0 ) 01012 { 01013 // Send sensor packets 01014 SendFrame( frame ); 01015 } 01016 } 01017 sample_period++; 01018 } 01019 01020 ExitingProgram(); 01021 }
Generated on Tue Jul 19 2022 04:04:44 by
1.7.2
