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:
ubhat
Date:
Wed Jun 08 22:06:26 2016 +0000
Revision:
6:f8194e691dd4
Parent:
5:6ffeac53b7cb
Child:
18:18408c3c2d0c
Add push-button application demo (assigned to Application PORT 11)

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