Demonstration of Class-A LoRaWAN device using NAMote-72

Dependencies:   LoRaWAN-lib mbed lib_mpl3115a2 lib_mma8451q lib_gps SX1272Lib

Dependents:   LoRaWAN-NAMote72-BVS-confirmed-tester-0-7v1_copy

LoRaWAN-NAMote72 Application Demo is a Class-A device example project using LoRaWAN-lib and SX1272Lib libraries.

This project is compliant with LoRaWAN V1.0.1 specification.

Comissioning.h (LoRaWAN Network Configuration)

The end-device can be activated in one of the two ways:

Over the Air (OTA) activation can be enabled as shown in the figure below. /media/uploads/ubhat/ota_enable.png

The end-device must be configured with the following parameters:

  • LORAWAN_DEVICE_EUI (8 Bytes) : Fist 3 Bytes is the Organizationally Unique Identifier (OUI) followed by 5 bytes of unique ID. If not defined by user, then the firmware automatically assigns one to the end-device
  • LORAWAN_APPLICATION_EUI (8 Bytes)
  • LORAWAN_APPLICATION_KEY (or DEVKEY) (16 Bytes)

/media/uploads/ubhat/ota_eui.png

Activation by Personalization (ABP) can be enabled as shown in the figure below. /media/uploads/ubhat/abp_enable.png

The end-device must be configured with the following parameters:

  • LORAWAN_DEVICE_ADDRESS (4 Bytes) : If not defined by user, then the firmware automatically assigns one to the end-device
  • LORAWAN_NWKSKEY (16 Bytes)
  • LORAWAN_APPSKEY (16 Bytes)

/media/uploads/ubhat/abp_key.png

Config.h (LoRaWAN Communication Parameters)

  • Mode of Operation : Hybrid If the end-device needs to be configured to operate over 8-channels, then Hybrid Mode needs to be enabled /media/uploads/ubhat/hybridenable.png
  • Mode of Operation : Frequency Hop If the end-device needs to be configured to operate over 64-channels, then Hybrid Mode needs to be disabled
  • Delay between successive JOIN REQUESTs : The delay between successive Join Requests (until the end-device joins the network) can be configured using the parameter OVER_THE_AIR_ACTIVATION_DUTYCYCLE
  • Inter-Frame Delay : One can change the delay between each frame transmission using APP_TX_DUTYCYCLE It is advisable that APP_TX_DUTYCYCLE is greater than or equal to 3sec.
  • Data Rate : The data rate can be configured as per LoRaWAN specification using the paramter LORAWAN_DEFAULT_DATARATE. The range of values are DR_0, DR_1, DR_2, DR_3 and DR_4
  • Confirmed/Unconfirmed Messages : The uplink message or payload can be chosen to be confirmed or unconfirmed using the parameter LORAWAN_CONFIRMED_MSG_ON. When set to 1, the transmitted messages need to be confirmed with an ACK by the network server in the subsequent RX window. When set to 0, no ACK is requested.
  • ADR ON/OFF : The ADR can be enabled or disabled using the parameter LORAWAN_ADR_ON. When set to 1, ADR is enabled and disabled when set to 0.
  • Application Port : The application port can be set using parameter LORAWAN_APP_PORT.
  • Payload Length : The lenght of the payload (in bytes) to be transmitted can be configured using LORAWAN_APP_DATA_SIZE
  • Transmit Power : The transmit power can be configured using LORAWAN_TX_POWER (LoRaMAC verifies if the set power is compliant with the LoRaWAN spec and FCC guidelines)

/media/uploads/ubhat/loraconfig.png

Main.cpp (Device State Machine)

The end-device state machine is defined.

  • Initial State : Device is initialized.
  • Join State : For OTA, Join Request is transmitted to the network until Join Accept is received by the end-device. Join event function is called that sets Red LED ON.
  • Send State : Transmit payload frame is prepared. Tx event is called that blinks the Red LED indicating uplink transmission.
  • Cycle State : Next packet transmission is scheduled

LoRaEventProc.cpp (Events and On-board Application)

Define events during Join, Tx & Rx. Prepare TX packet by appending with appropriate application data.

/media/uploads/ubhat/lora_events.png

  • PrepareLoRaFrame(uint8_t port ) : Prepare LoRa payload frame with on-board application data such as GPS, Temperature, Battery, etc. LoRa.ApplicationCall(AppType ) calls application AppType defined in LoRaApp.cpp. AppType is defined in LoRaApp.h

/media/uploads/ubhat/lora_app.png

LoRaApp.cpp

User-defined applications such as GPS, Temp, Accelerometer, LED indications etc. Event based actions such as LED blink on Tx, LED toggle on downlink etc /media/uploads/ubhat/apptype.png

LoRaDeviceStateProc.cpp

Process function calls corresponding to different Device states /media/uploads/ubhat/device_state.png

LoRaMacLayerService.cpp

Define MAC Layer Services: MLME & MCPS

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, application port, message type etc. are displayed on the terminal.

/media/uploads/ubhat/serial.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

Committer:
mluis
Date:
Mon Apr 24 13:47:27 2017 +0000
Revision:
18:18408c3c2d0c
Parent:
6:f8194e691dd4
WARNING: Radio API timings changed from micro-seconds to milliseconds; ; Synchronized with https://github.com/Lora-net/LoRaMac-node git revision e506c246652fa44c3f24cecb89d0707b49ece739; Updated all libraries to the latest versions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ubhat 0:69f2e28d12c1 1 /*
ubhat 0:69f2e28d12c1 2 / _____) _ | |
ubhat 0:69f2e28d12c1 3 ( (____ _____ ____ _| |_ _____ ____| |__
ubhat 0:69f2e28d12c1 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
ubhat 0:69f2e28d12c1 5 _____) ) ____| | | || |_| ____( (___| | | |
ubhat 0:69f2e28d12c1 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
ubhat 0:69f2e28d12c1 7 (C)2015 Semtech
ubhat 0:69f2e28d12c1 8
ubhat 0:69f2e28d12c1 9 Description: LoRaMac classA device implementation
ubhat 0:69f2e28d12c1 10
ubhat 0:69f2e28d12c1 11 License: Revised BSD License, see LICENSE.TXT file include in the project
ubhat 0:69f2e28d12c1 12
ubhat 0:69f2e28d12c1 13 Maintainer: Miguel Luis and Gregory Cristian
ubhat 0:69f2e28d12c1 14 */
ubhat 0:69f2e28d12c1 15 #include "mbed.h"
ubhat 0:69f2e28d12c1 16 #include "board.h"
ubhat 0:69f2e28d12c1 17 #include "radio.h"
ubhat 0:69f2e28d12c1 18
ubhat 0:69f2e28d12c1 19 #include "LoRaMac.h"
mluis 18:18408c3c2d0c 20 #include "Commissioning.h"
ubhat 0:69f2e28d12c1 21 #include "SerialDisplay.h"
ubhat 0:69f2e28d12c1 22 #include "ComplianceTest.h"
ubhat 0:69f2e28d12c1 23 #include "LoRaDeviceStateProc.h"
ubhat 0:69f2e28d12c1 24 #include "LoRaEventProc.h"
ubhat 0:69f2e28d12c1 25 #include "LoRaApp.h"
ubhat 0:69f2e28d12c1 26
mluis 18:18408c3c2d0c 27 bool Otaa = true;
ubhat 0:69f2e28d12c1 28
ubhat 0:69f2e28d12c1 29 uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
ubhat 0:69f2e28d12c1 30 uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
ubhat 0:69f2e28d12c1 31 uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
ubhat 0:69f2e28d12c1 32
mluis 18:18408c3c2d0c 33 #if( OVER_THE_AIR_ACTIVATION == 0 )
ubhat 0:69f2e28d12c1 34
ubhat 0:69f2e28d12c1 35 uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
ubhat 0:69f2e28d12c1 36 uint8_t AppSKey[] = LORAWAN_APPSKEY;
ubhat 0:69f2e28d12c1 37
ubhat 0:69f2e28d12c1 38 /*!
ubhat 0:69f2e28d12c1 39 * Device address
ubhat 0:69f2e28d12c1 40 */
ubhat 0:69f2e28d12c1 41 uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
ubhat 0:69f2e28d12c1 42
ubhat 0:69f2e28d12c1 43 #endif
ubhat 0:69f2e28d12c1 44
ubhat 0:69f2e28d12c1 45 /*!
ubhat 0:69f2e28d12c1 46 * Application port
ubhat 0:69f2e28d12c1 47 */
ubhat 0:69f2e28d12c1 48 uint8_t AppPort = LORAWAN_APP_PORT;
ubhat 0:69f2e28d12c1 49
ubhat 0:69f2e28d12c1 50 /*!
ubhat 0:69f2e28d12c1 51 * User application data size
ubhat 0:69f2e28d12c1 52 */
ubhat 0:69f2e28d12c1 53 uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
ubhat 0:69f2e28d12c1 54
ubhat 0:69f2e28d12c1 55 /*!
ubhat 0:69f2e28d12c1 56 * User application data
ubhat 0:69f2e28d12c1 57 */
ubhat 0:69f2e28d12c1 58 uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
ubhat 0:69f2e28d12c1 59
ubhat 0:69f2e28d12c1 60 /*!
ubhat 0:69f2e28d12c1 61 * Application to handle functions
ubhat 0:69f2e28d12c1 62 */
ubhat 0:69f2e28d12c1 63 Application LoRaApp( AppData );
ubhat 0:69f2e28d12c1 64
ubhat 0:69f2e28d12c1 65 /*!
ubhat 0:69f2e28d12c1 66 * Indicates if the node is sending confirmed or unconfirmed messages
ubhat 0:69f2e28d12c1 67 */
ubhat 0:69f2e28d12c1 68 uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
ubhat 0:69f2e28d12c1 69
ubhat 0:69f2e28d12c1 70 /*!
ubhat 0:69f2e28d12c1 71 * Timer to handle the application data transmission duty cycle
ubhat 0:69f2e28d12c1 72 */
ubhat 0:69f2e28d12c1 73 TimerEvent_t TxNextPacketTimer;
ubhat 0:69f2e28d12c1 74
ubhat 0:69f2e28d12c1 75 /*!
ubhat 5:6ffeac53b7cb 76 * Indicates if a new transmit interrupt can be set
ubhat 5:6ffeac53b7cb 77 */
ubhat 5:6ffeac53b7cb 78 bool IsTxIntUpdate = false;
ubhat 5:6ffeac53b7cb 79
ubhat 5:6ffeac53b7cb 80 /*!
ubhat 0:69f2e28d12c1 81 * Indicates if a new packet can be sent
ubhat 0:69f2e28d12c1 82 */
ubhat 0:69f2e28d12c1 83 bool NextTx = true;
ubhat 0:69f2e28d12c1 84
ubhat 0:69f2e28d12c1 85 /*!
ubhat 0:69f2e28d12c1 86 * LoRaWAN compliance tests support data
ubhat 0:69f2e28d12c1 87 */
ubhat 0:69f2e28d12c1 88 ComplianceTest_s ComplianceTest;
ubhat 0:69f2e28d12c1 89
ubhat 0:69f2e28d12c1 90 /*!
ubhat 0:69f2e28d12c1 91 * Indicates if the MAC layer network join status has changed.
ubhat 0:69f2e28d12c1 92 */
ubhat 0:69f2e28d12c1 93 bool IsNetworkJoinedStatusUpdate = false;
ubhat 0:69f2e28d12c1 94
ubhat 0:69f2e28d12c1 95 /*!
ubhat 0:69f2e28d12c1 96 * Indicates if the message sent.
ubhat 0:69f2e28d12c1 97 */
ubhat 0:69f2e28d12c1 98 bool IsTxUpdate = false;
ubhat 0:69f2e28d12c1 99
ubhat 0:69f2e28d12c1 100 /*!
ubhat 0:69f2e28d12c1 101 * Indicates if the message received in the RX window.
ubhat 0:69f2e28d12c1 102 */
ubhat 0:69f2e28d12c1 103 bool IsRxUpdate = false;
ubhat 0:69f2e28d12c1 104
ubhat 0:69f2e28d12c1 105
ubhat 0:69f2e28d12c1 106 /**
ubhat 0:69f2e28d12c1 107 * Main application entry point.
ubhat 0:69f2e28d12c1 108 */
ubhat 0:69f2e28d12c1 109 int main( void )
ubhat 0:69f2e28d12c1 110 {
ubhat 0:69f2e28d12c1 111
ubhat 0:69f2e28d12c1 112 // Initialize board peripherals
ubhat 0:69f2e28d12c1 113 BoardInit( );
ubhat 0:69f2e28d12c1 114
mluis 18:18408c3c2d0c 115 // Display Sw Version
mluis 18:18408c3c2d0c 116 DisplaySwVersion( );
mluis 18:18408c3c2d0c 117
ubhat 0:69f2e28d12c1 118 // Initialize Device state
ubhat 0:69f2e28d12c1 119 DeviceState = DEVICE_STATE_INIT;
ubhat 0:69f2e28d12c1 120
ubhat 0:69f2e28d12c1 121 while( 1 )
mluis 18:18408c3c2d0c 122 {
mluis 18:18408c3c2d0c 123 Gps.service( );
ubhat 0:69f2e28d12c1 124 if( IsNetworkJoinedStatusUpdate == true )
ubhat 0:69f2e28d12c1 125 {
ubhat 0:69f2e28d12c1 126 IsNetworkJoinedStatusUpdate = false;
ubhat 0:69f2e28d12c1 127
ubhat 0:69f2e28d12c1 128 DeviceJoinUpdate( );
ubhat 0:69f2e28d12c1 129 }
ubhat 0:69f2e28d12c1 130
ubhat 0:69f2e28d12c1 131 if( IsTxUpdate == true )
ubhat 0:69f2e28d12c1 132 {
ubhat 0:69f2e28d12c1 133 // If downlink received then update Serial Terminal and execute Rx event
ubhat 0:69f2e28d12c1 134 IsTxUpdate = false;
mluis 18:18408c3c2d0c 135
ubhat 0:69f2e28d12c1 136 // Update serial terminal
mluis 18:18408c3c2d0c 137 //SerialDisplayTxUpdate( );
ubhat 5:6ffeac53b7cb 138 }
ubhat 5:6ffeac53b7cb 139
ubhat 5:6ffeac53b7cb 140 if( IsTxIntUpdate == true )
ubhat 5:6ffeac53b7cb 141 {
ubhat 5:6ffeac53b7cb 142 IsTxIntUpdate = false;
mluis 18:18408c3c2d0c 143
ubhat 5:6ffeac53b7cb 144 // Initialize next Tx Interrupt
ubhat 5:6ffeac53b7cb 145 InitNextTxInterrupt( AppPort );
ubhat 0:69f2e28d12c1 146 }
ubhat 0:69f2e28d12c1 147
ubhat 0:69f2e28d12c1 148 if( IsRxUpdate == true )
ubhat 0:69f2e28d12c1 149 {
ubhat 0:69f2e28d12c1 150 // If downlink received then update Serial Terminal and execute Rx event
ubhat 0:69f2e28d12c1 151 IsRxUpdate = false;
ubhat 0:69f2e28d12c1 152 RxEvent( );
mluis 18:18408c3c2d0c 153 SerialDisplayRxUpdate( );
ubhat 0:69f2e28d12c1 154 }
ubhat 0:69f2e28d12c1 155
ubhat 0:69f2e28d12c1 156 switch( DeviceState )
ubhat 0:69f2e28d12c1 157 {
ubhat 0:69f2e28d12c1 158 case DEVICE_STATE_INIT:
ubhat 0:69f2e28d12c1 159 {
ubhat 0:69f2e28d12c1 160 // Initialize MAC, MAC services, Primitives
ubhat 0:69f2e28d12c1 161 DeviceInit( );
ubhat 0:69f2e28d12c1 162
ubhat 0:69f2e28d12c1 163 // Change Device state
ubhat 0:69f2e28d12c1 164 DeviceState = DEVICE_STATE_JOIN;
ubhat 0:69f2e28d12c1 165 break;
ubhat 0:69f2e28d12c1 166 }
ubhat 0:69f2e28d12c1 167 case DEVICE_STATE_JOIN:
ubhat 0:69f2e28d12c1 168 {
mluis 18:18408c3c2d0c 169 #if( OVER_THE_AIR_ACTIVATION != 0 ) // OTA
ubhat 0:69f2e28d12c1 170
ubhat 0:69f2e28d12c1 171 // Generate DevEUI if not defined by User
ubhat 0:69f2e28d12c1 172 BoardGetDevEUI( DevEui );
ubhat 0:69f2e28d12c1 173
ubhat 0:69f2e28d12c1 174 // Join N/w server
mluis 18:18408c3c2d0c 175 DeviceJoin( );
ubhat 0:69f2e28d12c1 176
ubhat 0:69f2e28d12c1 177 // Show on serial terminal
ubhat 0:69f2e28d12c1 178 SerialDisplayJoinUpdate( );
ubhat 0:69f2e28d12c1 179
ubhat 0:69f2e28d12c1 180 // Execute Join event
ubhat 0:69f2e28d12c1 181 JoinEvent( );
ubhat 0:69f2e28d12c1 182
ubhat 0:69f2e28d12c1 183 DeviceState = DEVICE_STATE_SLEEP;
ubhat 0:69f2e28d12c1 184
ubhat 0:69f2e28d12c1 185 #else // ABP
ubhat 0:69f2e28d12c1 186 DeviceJoin( );
ubhat 0:69f2e28d12c1 187
ubhat 0:69f2e28d12c1 188 DeviceState = DEVICE_STATE_SEND;
ubhat 0:69f2e28d12c1 189 #endif
ubhat 0:69f2e28d12c1 190 IsNetworkJoinedStatusUpdate = true;
ubhat 0:69f2e28d12c1 191 break;
ubhat 0:69f2e28d12c1 192 }
ubhat 0:69f2e28d12c1 193 case DEVICE_STATE_SEND:
mluis 18:18408c3c2d0c 194 {
ubhat 0:69f2e28d12c1 195 if( NextTx == true )
ubhat 0:69f2e28d12c1 196 {
ubhat 0:69f2e28d12c1 197 // Prepare payload frame based on application port
ubhat 0:69f2e28d12c1 198 PrepareTxFrame( AppPort );
ubhat 0:69f2e28d12c1 199
ubhat 0:69f2e28d12c1 200 // Send payload over the air
ubhat 0:69f2e28d12c1 201 NextTx = SendFrame( );
ubhat 0:69f2e28d12c1 202
ubhat 0:69f2e28d12c1 203 // Execute transmit event
mluis 18:18408c3c2d0c 204 TxEvent( );
ubhat 0:69f2e28d12c1 205 }
ubhat 5:6ffeac53b7cb 206
ubhat 5:6ffeac53b7cb 207 if( NextTx == false )
ubhat 0:69f2e28d12c1 208 {
ubhat 5:6ffeac53b7cb 209 IsTxUpdate = true;
ubhat 0:69f2e28d12c1 210 }
mluis 18:18408c3c2d0c 211
ubhat 0:69f2e28d12c1 212 DeviceState = DEVICE_STATE_SLEEP;
ubhat 0:69f2e28d12c1 213 break;
mluis 18:18408c3c2d0c 214 }
ubhat 0:69f2e28d12c1 215 case DEVICE_STATE_SLEEP:
ubhat 0:69f2e28d12c1 216 {
ubhat 0:69f2e28d12c1 217 // Wake up through events
ubhat 0:69f2e28d12c1 218 break;
ubhat 0:69f2e28d12c1 219 }
ubhat 0:69f2e28d12c1 220 default:
ubhat 0:69f2e28d12c1 221 {
ubhat 0:69f2e28d12c1 222 DeviceState = DEVICE_STATE_INIT;
ubhat 0:69f2e28d12c1 223 break;
ubhat 0:69f2e28d12c1 224 }
ubhat 0:69f2e28d12c1 225 }
ubhat 0:69f2e28d12c1 226 }
ubhat 0:69f2e28d12c1 227 }