LMIC transmit example for NAmote-72 with GPS
Dependencies: lib_gps lib_mpl3115a2 lmic_MOTE_L152RC mbed
main.cpp
00001 /******************************************************************************* 00002 * Copyright (c) 2014-2015 IBM Corporation. 00003 * All rights reserved. This program and the accompanying materials 00004 * are made available under the terms of the Eclipse Public License v1.0 00005 * which accompanies this distribution, and is available at 00006 * http://www.eclipse.org/legal/epl-v10.html 00007 * 00008 * Contributors: 00009 * IBM Zurich Research Lab - initial API, implementation and documentation 00010 *******************************************************************************/ 00011 00012 #include "lmic.h" 00013 #include "debug.h" 00014 #include <mbed.h> 00015 #include "gps.h" 00016 #include "mpl3115a2.h" 00017 00018 #define FHS_MAX_POW 30 /* Frequency Hopping Max Power */ 00019 #define DMTS_MAX_POW 26 /* Digital Modulation Max Power */ 00020 #define HS_MAX_POW 20 /* Hybrid System Max Power */ 00021 00022 bool joined; 00023 typedef enum { 00024 MOTE_NONE = 0, 00025 MOTE_V2, 00026 MOTE_V3 00027 } mote_version_e; 00028 mote_version_e mote_version = MOTE_NONE; 00029 00030 DigitalOut gps_en(PB_11); // dis/enables voltage divider on PA_1 00031 DigitalOut pc_7(PC_7); 00032 DigitalIn pc_1(PC_1); 00033 AnalogIn *bat; 00034 #define LOW_BAT_THRESHOLD 3.45 00035 #define AIN_VREF 3.3 // stm32 internal refernce 00036 #define AIN_VBAT_DIV 2 // resistor divider 00037 00038 #define LED_ON 0 00039 #define LED_OFF 1 00040 static DigitalOut led_red(PB_1); 00041 static DigitalOut led_yellow(PB_10); 00042 //static DigitalOut led_green(PC_3); 00043 static DigitalOut led_usr(PA_5); 00044 00045 00046 GPS gps(PB_6, PB_7, PB_11); 00047 I2C i2c(I2C_SDA, I2C_SCL); 00048 DigitalIn i2c_int_pin(PB_4); 00049 MPL3115A2 mpl3115a2(i2c, i2c_int_pin); 00050 volatile bool AppLedStateOn = false; 00051 00052 00053 ////////////////////////////////////////////////// 00054 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) 00055 ////////////////////////////////////////////////// 00056 00057 static const u1_t app_eui[ 8] = { APPEUI }; 00058 //static u1_t dev_eui[ 8] = { OUI, 0x00, 0xff, 0xff, 0xff, 0xff }; 00059 static u1_t dev_eui[ 8] = { DEVEUI }; 00060 static const u1_t dev_key[16] = { DEVKEY }; 00061 00062 00063 ////////////////////////////////////////////////// 00064 // APPLICATION CALLBACKS 00065 ////////////////////////////////////////////////// 00066 00067 // provide application router ID (8 bytes, LSBF) 00068 void os_getArtEui (u1_t* buf) { 00069 LMIC_reverse_memcpy(buf, app_eui, sizeof(app_eui)); 00070 } 00071 00072 // provide device ID (8 bytes, LSBF) 00073 void os_getDevEui (u1_t* buf) { 00074 LMIC_reverse_memcpy(buf, dev_eui, sizeof(dev_eui)); 00075 } 00076 00077 // provide device key (16 bytes) 00078 void os_getDevKey (u1_t* buf) { 00079 memcpy(buf, dev_key, sizeof(dev_key)); 00080 } 00081 00082 00083 ////////////////////////////////////////////////// 00084 // MAIN - INITIALIZATION AND STARTUP 00085 ////////////////////////////////////////////////// 00086 void get_mote_version() 00087 { 00088 char first; 00089 00090 pc_7 = 1; 00091 first = pc_1; 00092 pc_7 = 0; 00093 if (first && !pc_1) { 00094 gps.en_invert = 1; 00095 mote_version = MOTE_V2; 00096 bat = new AnalogIn(PA_0); 00097 } else { 00098 mote_version = MOTE_V3; 00099 bat = new AnalogIn(PA_1); 00100 //gps.en_invert = 0; 00101 gps_en = 0; 00102 } 00103 } 00104 00105 ////////////////////////////////////////////////// 00106 // Display network parameters (DevEUI, AppEUI etc) 00107 ////////////////////////////////////////////////// 00108 void DisplayNetworkParam() 00109 { 00110 int i; 00111 00112 if(mote_version == MOTE_V2) 00113 printf("\r\nNA Mote Ver. 2\r\n"); 00114 else 00115 if(mote_version == MOTE_V3) 00116 printf("\r\nNA Mote Ver. 3\r\n"); 00117 else 00118 printf("\r\nNA Mote Ver. NOT DEFINED\r\n"); 00119 00120 printf("DEVEUI:"); 00121 for (i = 0; i < sizeof(dev_eui); i++) { 00122 printf("%02x", dev_eui[i]); 00123 if (i < sizeof(dev_eui)-1) 00124 printf("-"); 00125 } 00126 printf("\r\n"); 00127 00128 printf("APPEUI:"); 00129 for (i = 0; i < sizeof(app_eui); i++) { 00130 printf("%02x", app_eui[i]); 00131 if (i < sizeof(app_eui)-1) 00132 printf("-"); 00133 } 00134 printf("\r\n"); 00135 00136 printf("DEVKEY:"); 00137 for (i = 0; i < sizeof(dev_key); i++) { 00138 printf("%02x ", dev_key[i]); 00139 } 00140 printf("\r\n"); 00141 } 00142 00143 void DisplayData(uint8_t *pData, int len) 00144 { 00145 int i; 00146 00147 for(i = 0; i < len; i++) 00148 printf("%x ", pData[i]); 00149 printf("\r\n"); 00150 } 00151 00152 osjob_t nJoinedJob; 00153 00154 static void on_not_joined(osjob_t* j) 00155 { 00156 if (joined) 00157 return; 00158 00159 DisplayNetworkParam(); 00160 00161 os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(7000), on_not_joined ); 00162 } 00163 00164 00165 // initial job 00166 static void initfunc (osjob_t* j) 00167 { 00168 u4_t* id; 00169 u4_t* u4_ptr; 00170 00171 u4_ptr = (u4_t*)&dev_eui[4]; // [4] to [7] 00172 00173 if(*u4_ptr == 0) 00174 { 00175 id = (u4_t*)0x1ff800d0; // STM32L1xx Cat3 00176 *u4_ptr = *id; 00177 id = (u4_t*)0x1ff800d4; 00178 *u4_ptr ^= *id; 00179 id = (u4_t*)0x1ff800e4; 00180 *u4_ptr ^= *id; 00181 } 00182 00183 get_mote_version(); 00184 gps.init(); 00185 00186 gps.enable(1); 00187 mpl3115a2.init(); 00188 00189 // reset MAC state 00190 LMIC_reset(); 00191 00192 os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(3000), on_not_joined ); 00193 joined = false; 00194 // start joining 00195 LMIC_startJoining(); 00196 00197 led_red = LED_ON; // indicate joining 00198 led_yellow = LED_OFF; 00199 //led_green = LED_OFF; 00200 // init done - onEvent() callback will be invoked... 00201 } 00202 00203 00204 // application entry point 00205 int main () { 00206 osjob_t initjob; 00207 00208 // initialize runtime env 00209 os_init(); 00210 // initialize debug library 00211 debug_init(); 00212 // setup initial job 00213 os_setCallback(&initjob, initfunc); 00214 // execute scheduled jobs and events 00215 os_runloop(); 00216 // (not reached) 00217 return 0; 00218 } 00219 00220 static void 00221 restore_hsi() 00222 { 00223 RCC_OscInitTypeDef osc_init; 00224 /* if HSI was shut off in deep sleep (needed for AnalogIn) */ 00225 HAL_RCC_GetOscConfig(&osc_init); 00226 if (osc_init.HSIState != RCC_HSI_ON) { 00227 // Enable the HSI (to clock the ADC) 00228 osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSI; 00229 osc_init.HSIState = RCC_HSI_ON; 00230 osc_init.PLL.PLLState = RCC_PLL_NONE; 00231 HAL_RCC_OscConfig(&osc_init); 00232 } 00233 } 00234 00235 osjob_t sendFrameJob; 00236 osjob_t indicateJob; 00237 00238 static void tx_ind_cb(osjob_t* j) 00239 { 00240 led_red = LED_OFF; 00241 } 00242 00243 static void onSendFrame (osjob_t* j) 00244 { 00245 uint16_t altitudeGps; 00246 00247 if (LMIC.opmode & OP_TXRXPEND) { 00248 return; 00249 } 00250 00251 #ifdef FIXED_DR 00252 LMIC.datarate = FIXED_DR; 00253 #endif 00254 00255 #ifdef FIXED_TX_POWER 00256 LMIC.txpow = FIXED_TX_POWER; 00257 #endif 00258 00259 restore_hsi(); 00260 00261 if(LMIC.datarate == DR_SF8C) 00262 LMIC.txpow_limit = DMTS_MAX_POW; 00263 else 00264 #ifdef CHNL_HYBRID 00265 LMIC.txpow_limit = HS_MAX_POW; 00266 #else 00267 LMIC.txpow_limit = FHS_MAX_POW; 00268 #endif 00269 00270 if( LMIC.txpow > LMIC.txpow_limit) 00271 LMIC.txpow = LMIC.txpow_limit; 00272 00273 float volts = bat->read()*AIN_VREF*AIN_VBAT_DIV; 00274 if (volts < LOW_BAT_THRESHOLD) { 00275 if (LMIC.txpow_limit > 20) 00276 LMIC.txpow_limit = 20; 00277 if (LMIC.txpow > 20) 00278 LMIC.txpow = 20; 00279 } 00280 00281 /////////////////////////////////////////////////////////////////// 00282 gps.service(); 00283 mpl3115a2.ReadTemperature(); 00284 00285 uint8_t tmpData[PAYLOAD_LENGTH] = {0}; 00286 00287 tmpData[0] = 15-(LMIC.txpow>>1); 00288 tmpData[0] <<= 4; 00289 #ifdef CHNL_HYBRID 00290 tmpData[0] |= 0x04; // 8ch: set bit2 00291 #else 00292 tmpData[0] |= 0x08; // 64ch: set bit3 00293 #endif 00294 00295 tmpData[0] |= AppLedStateOn & 1; // (bit 0 == 1) => LED on 00296 tmpData[1] = (int)mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So, +/-63 C 00297 tmpData[2] = (bat->read_u16() >> 8) + (bat->read_u16() >> 9) ; // per LoRaMAC spec; 0=Charging; 1...254 = level, 255 = N/A 00298 00299 tmpData[3] = ( gps.LatitudeBinary >> 16 ) & 0xFF; 00300 tmpData[4] = ( gps.LatitudeBinary >> 8 ) & 0xFF; 00301 tmpData[5] = gps.LatitudeBinary & 0xFF; 00302 tmpData[6] = ( gps.LongitudeBinary >> 16 ) & 0xFF; 00303 tmpData[7] = ( gps.LongitudeBinary >> 8 ) & 0xFF; 00304 tmpData[8] = gps.LongitudeBinary & 0xFF; 00305 00306 altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude); 00307 tmpData[9] = ( altitudeGps >> 8 ) & 0xFF; 00308 tmpData[10] = altitudeGps & 0xFF; 00309 if (PAYLOAD_LENGTH > 11) { 00310 for (int i = 11; i < PAYLOAD_LENGTH; i++) 00311 tmpData[i] = i - 10; 00312 } 00313 00314 for(int i = 0; i < PAYLOAD_LENGTH; i++) 00315 LMIC.frame[i] = tmpData[i]; 00316 00317 // port, buffer, buffer length, need_ack 00318 LMIC_setTxData2(5, LMIC.frame, PAYLOAD_LENGTH, 0); 00319 00320 led_red = LED_ON; 00321 00322 // Display Info 00323 00324 DisplayNetworkParam(); 00325 00326 printf("Seq# %d\r\n",LMIC.seqnoUp-1); 00327 00328 printf("TX Data: "); 00329 DisplayData(tmpData, PAYLOAD_LENGTH); 00330 00331 printf("TX Power: %d dBm\r\n",LMIC.txpow); 00332 00333 printf("Battery: %f Volts\r\n",volts); 00334 00335 os_setTimedCallback( &indicateJob, os_getTime() + ms2osticks(30), tx_ind_cb ); 00336 00337 } 00338 00339 00340 ////////////////////////////////////////////////// 00341 // LMIC EVENT CALLBACK 00342 ////////////////////////////////////////////////// 00343 00344 void onEvent (ev_t ev) 00345 { 00346 debug_event(ev); 00347 00348 switch(ev) { 00349 case EV_JOINED: 00350 // network joined, session established 00351 debug_val("netid = ", LMIC.netid); 00352 joined = true; 00353 led_red = LED_OFF; // indicate joined 00354 goto tx; 00355 case EV_TXCOMPLETE: 00356 // scheduled data sent (optionally data received) 00357 if(LMIC.dataLen) { // data received in rx slot after tx 00358 led_yellow = led_yellow ? 0 : 1; 00359 if (LMIC.dataLen == 1) { // set LED state if exactly one byte is received 00360 led_usr = LMIC.frame[LMIC.dataBeg] & 0x01; 00361 } 00362 debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen); 00363 } 00364 tx: 00365 os_setTimedCallback( &sendFrameJob, os_getTime() + ms2osticks(MS_DELAY_NEXT_TX), onSendFrame ); 00366 break; 00367 default: 00368 led_red = LED_ON; // indicate not joined 00369 break; 00370 } // ..switch(ev) 00371 }
Generated on Tue Jul 12 2022 21:37:59 by 1.7.2