LMIC transmit example for NAmote-72 with GPS

Dependencies:   lib_gps lib_mpl3115a2 lmic_MOTE_L152RC mbed

Deprecated and replaced with

Import programLoRaWAN-NAMote72-Application-Demo

Demonstration of Class-A LoRaWAN device using NAMote-72

LoRaWAN Network Configuration (in Config.h)

For Over the Air (OTA) activation of an End-Device, it must be configured with the following parameters:

  1. DEVEUI (8 Bytes) : Fist 3 Bytes is the Organizationally Unique Identifier (OUI) followed by 5 bytes of unique ID.
  2. APPEUI (8 Bytes)
  3. APPKey (or DEVKEY) (16 Bytes) The parameters can be entered as shown in the figure below /media/uploads/ubhat/nwkconfig.png

LoRaWAN Transmission Configuration (in Config.h)

  • Inter-Frame Delay : One can change the delay between each frame transmission using MS_DELAY_NEXT_TX It is advisable that MS_DELAY_NEXT_TX is greater than or equal to 3sec. /media/uploads/ubhat/txtiming.png
  • Payload Length : The lenght of the payload (in bytes) to be transmitted can be configured using PAYLOAD_LENGTH /media/uploads/ubhat/payload.png
  • Data Rate : The data rate can be configured as per LoRaWAN specification using the paramter FIXED_DR /media/uploads/ubhat/datarate.png
  • Channel Configuration : In the case where the End-Device is transmitting over frequencies corresponding to a block of 8 channels, the block can be specified using CHNL_HYBRID. The value 0 corresponds to Block A, 1 corresponds to Block B and so on. /media/uploads/ubhat/hybrid.png When the End-Device transmits over more than 50 channels, CHNL_HYBRID needs to be commented out /media/uploads/ubhat/frequencyhopping.png
  • Transmit Power : The power of the data to be transmitted can be configured using the parameter FIXED_TX_POWER. The maximum transmit power allowed is as per FCC regulation, depending upon the mode of transmission. /media/uploads/ubhat/txpower.png

Serial Terminal Display

By using a serial port connection using applications such as teraterm or putty, one can view the status of the End-Device. Once the End-Device Joins the network, transmission parameters such as payload data, transmit power, battery level etc. are displayed on the terminal.

/media/uploads/ubhat/teraterm.png

Default Application Payload

This application defaults to sending uplink data to logical port 5. The application payload consists of: /media/uploads/jknapp_smtc/payload.png

Sample Application Payload Calculation for Longitude/Latitude

Payload => 00 19 F6 352BBA A94C20 FFFF

Temperature Calculation

19H => 2510

Temp = 25/2 = 12.5 oC

Battery Level

FFH => 100 %

F6H => 96.5 %

Longitude Calculation

longitude = A94C20H => 1109507210

longitudinal coordinate = -360 + (longitude10 x 180/(223))

longitudinal coordinate = -121.93

Latitude Calculation

latitude = 352BBAH = 348460210

latitude coordinate = (latitude10 x 90/(223-1))

latitude coordinate = 37.39

Revision:
0:a5e3347bad61
Child:
2:a8f00db60fdb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jun 04 21:48:47 2015 +0000
@@ -0,0 +1,250 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: MBED example application
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include "mbed.h"
+#include "lmic.h"
+#include "mpl3115a2.h"
+#include "gps.h"
+#include "debug.h"
+
+#define SENET_F
+//#define SMTC
+
+/* ****************************************** */
+/* ***** Basic App and Network Parameters *** */
+/* ****************************************** */
+// Hybrid Mode must be defined in lmic.h      //
+// DevEUI and Keys defined by Activation type //
+#define APP_DATA_SIZE               11
+#define APP_ACK                     0
+#define DELAY_NEXT_TX               10
+#ifdef SMTC
+#define OVER_THE_AIR_ACTIVATION     0
+#else
+#define OVER_THE_AIR_ACTIVATION     1
+#endif /* SMTC */
+
+/* ***************************************** */
+
+#define LED_RED         PB_1
+#define LED_YEL         PB_10
+
+static DigitalOut led1(LED_RED);
+static DigitalOut led2(LED_YEL);
+
+/*  gps(tx, rx, en); */
+GPS gps(PB_6, PB_7, PB_11);
+
+I2C i2c(I2C_SDA, I2C_SCL);
+DigitalIn i2c_int_pin(PB_4);
+MPL3115A2 mpl3115a2(i2c, i2c_int_pin);
+AnalogIn bat(PA_0);
+
+//////////////////////////////////////////////////
+// CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
+//////////////////////////////////////////////////
+#ifdef SENET_F
+// application router ID (LSBF)
+static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x25, 0x00  };
+
+// unique device ID (LSBF)
+static const u1_t DEVEUI[8]  = { 0x0f, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x25, 0x00 };
+
+// device-specific AES key (derived from device EUI)
+static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42, };
+                             //    E4   -72   -71   -C5   -F5   -30   -A9   -9F   -CF   -C4   -0E   -AB   -EA   -D7   -19   -42
+#endif /* SENET_F */
+
+#ifdef SMTC
+// Semtech Activation (v1.x server)
+// application router ID (LSBF)
+static const u1_t APPEUI[8]  = { 0xAA, 0xCC, 0x11, 0x00, 0xCC, 0xEE, 0x77, 0xEE };
+
+// unique device ID (LSBF)
+static const u1_t DEVEUI[8]  = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
+
+// device-specific AES key (derived from device EUI)
+static const u1_t DEVKEY[16] = { 0xAB, 0x89, 0xEF, 0xCD, 0x23, 0x01, 0x67, 0x45, 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA };
+
+static uint8_t NwkSKey[] = 
+{ 
+    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+};
+
+static uint8_t ArtSKey[] = 
+{ 
+    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+};
+
+#endif /* SMTC */
+
+//////////////////////////////////////////////////
+// APPLICATION CALLBACKS
+//////////////////////////////////////////////////
+
+// provide application router ID (8 bytes, LSBF)
+void os_getArtEui (u1_t* buf) {
+    memcpy(buf, APPEUI, 8);
+}
+
+// provide device ID (8 bytes, LSBF)
+void os_getDevEui (u1_t* buf) {
+    memcpy(buf, DEVEUI, 8);
+}
+
+// provide device key (16 bytes)
+void os_getDevKey (u1_t* buf) {
+    memcpy(buf, DEVKEY, 16);
+}
+
+//////////////////////////////////////////////////
+// MAIN - INITIALIZATION AND STARTUP
+//////////////////////////////////////////////////
+
+// initial job
+static void initfunc (osjob_t* j) {
+    debug_str("B: INITFUNC\n");
+    // reset MAC state
+    LMIC_reset();
+    // start joining
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+    LMIC_startJoining();
+#else
+    devaddr_t *serial_id = (devaddr_t *) 0x1FF800d0;        // cat3 device stm32l152rc
+    LMIC_setSession( 0, *serial_id, NwkSKey, ArtSKey );
+    debug_val("SN = ", *serial_id);
+#endif
+    // init done - onEvent() callback will be invoked...
+
+    //DEBUG_STR("E: INITFUNC");
+    gps.init();
+    gps.enable(1);
+    //gps.verbose = 1;
+
+    mpl3115a2.init();
+}
+
+int main(void)
+{
+    osjob_t initjob;
+
+    // initialize runtime env
+    os_init();
+    debug_init();
+    // setup initial job
+    os_setCallback(&initjob, initfunc);
+    // execute scheduled jobs and events
+    os_runloop();
+    // (not reached)
+}
+
+//////////////////////////////////////////////////
+// LMIC EVENT CALLBACK
+//////////////////////////////////////////////////
+osjob_t rxLedJob;
+osjob_t txLedJob;
+osjob_t sendFrameJob;
+
+static void onRxLed (osjob_t* j) {
+    debug_val("LED2 = ", 1 );
+    led2 = 1;
+}
+
+static void onTxLed (osjob_t* j) {
+    debug_val("LED1 = ", 1 );
+    led1 = 1;
+}
+
+static bool AppLedStateOn = false;
+
+static void PrepareDataFrame( void )
+{
+    uint16_t altitudeGps;
+    //int i;
+
+    gps.service();
+    printf("lat:%f  long:%f\r\n", gps.Latitude, gps.Longitude);
+    // printf("lat:%d  long:%d\r\n", gps.LatitudeBinary, gps.LongitudeBinary);
+    mpl3115a2.ReadTemperature();
+    //printf("temp:%d\r\n", (int)mpl3115a2.Temperature);
+
+    // immediately prepare next transmission
+    //LMIC.frame[0] = LMIC.rxq.snr;
+    LMIC.frame[0] = AppLedStateOn; // (bit 0 == 1) => LED on
+    LMIC.frame[1] = (int)mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So,  +/-63 C
+    LMIC.frame[2] = (bat.read_u16() >> 8) + (bat.read_u16() >> 9) ; // per LoRaMAC spec; 0=Charging; 1...254 = level, 255 = N/A
+    LMIC.frame[3] = ( gps.LatitudeBinary >> 16 ) & 0xFF;
+    LMIC.frame[4] = ( gps.LatitudeBinary >> 8 ) & 0xFF;
+    LMIC.frame[5] = gps.LatitudeBinary & 0xFF;
+    LMIC.frame[6] = ( gps.LongitudeBinary >> 16 ) & 0xFF;
+    LMIC.frame[7] = ( gps.LongitudeBinary >> 8 ) & 0xFF;
+    LMIC.frame[8] = gps.LongitudeBinary & 0xFF;
+
+    altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude);
+    printf("alt:%d\r\n", altitudeGps);
+    LMIC.frame[9] = ( altitudeGps >> 8 ) & 0xFF;
+    LMIC.frame[10] = altitudeGps & 0xFF;
+}
+
+static void onSendFrame (osjob_t* j) {
+    PrepareDataFrame( );
+        // schedule transmission (port 1, data[], datalen 1, ACK requested)
+        // (will be sent as soon as duty cycle permits)
+    LMIC_setTxData2(5, LMIC.frame, APP_DATA_SIZE, APP_ACK);
+}
+
+void onEvent (ev_t ev) {
+
+    debug_event(ev);
+
+    gps.service();
+
+    switch(ev) 
+    {
+    // network joined, session established
+    case EV_JOINED:
+        debug_val("Net ID = ", LMIC.netid);
+        goto tx;
+    // scheduled data sent (optionally data received)
+    case EV_TXCOMPLETE:
+        if(LMIC.dataLen) 
+        { // data received in rx slot after tx
+            debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
+            if(LMIC.dataLen == 1) { // set LED state if exactly one byte is received
+                AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
+                debug_val("LED3 = ", AppLedStateOn ? 0 : 1 );
+            }
+        }
+        if((LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2) )!= 0 )
+        {
+            debug_val("LED2 = ", 0 );
+            led2 = 0;
+            os_setTimedCallback( &rxLedJob, os_getTime() + ms2osticks(15), onRxLed );
+        }
+tx:
+        os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(DELAY_NEXT_TX), onSendFrame ); // Change the Tx periodicity
+        //onSendFrame(NULL);
+        
+        // Blink Tx LED
+        debug_val("LED1 = ", 0 );
+        led1 = 0;
+        
+        os_setTimedCallback( &txLedJob, os_getTime() + ms2osticks(25), onTxLed );
+        break;
+    default:
+        break;
+    }
+}