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 01:40:42 2016 +0000
Revision:
5:6ffeac53b7cb
Parent:
0:69f2e28d12c1
Child:
18:18408c3c2d0c
Change state machine flow in main.cpp

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: MAC Layer Services: MLME & MCPS
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: Uttam Bhat
ubhat 0:69f2e28d12c1 14 */
ubhat 0:69f2e28d12c1 15
ubhat 0:69f2e28d12c1 16 #include "LoRaMacLayerService.h"
ubhat 0:69f2e28d12c1 17
ubhat 0:69f2e28d12c1 18 /*!
ubhat 0:69f2e28d12c1 19 * \brief MCPS-Confirm event function
ubhat 0:69f2e28d12c1 20 *
ubhat 0:69f2e28d12c1 21 * \param [IN] McpsConfirm - Pointer to the confirm structure,
ubhat 0:69f2e28d12c1 22 * containing confirm attributes.
ubhat 0:69f2e28d12c1 23 */
ubhat 0:69f2e28d12c1 24 void McpsConfirm( McpsConfirm_t *McpsConfirm )
ubhat 0:69f2e28d12c1 25 {
ubhat 0:69f2e28d12c1 26 if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
ubhat 0:69f2e28d12c1 27 {
ubhat 0:69f2e28d12c1 28 switch( McpsConfirm->McpsRequest )
ubhat 0:69f2e28d12c1 29 {
ubhat 0:69f2e28d12c1 30 case MCPS_UNCONFIRMED:
ubhat 0:69f2e28d12c1 31 {
ubhat 0:69f2e28d12c1 32 // Check Datarate
ubhat 0:69f2e28d12c1 33 // Check TxPower
ubhat 0:69f2e28d12c1 34 break;
ubhat 0:69f2e28d12c1 35 }
ubhat 0:69f2e28d12c1 36 case MCPS_CONFIRMED:
ubhat 0:69f2e28d12c1 37 {
ubhat 0:69f2e28d12c1 38 // Check Datarate
ubhat 0:69f2e28d12c1 39 // Check TxPower
ubhat 0:69f2e28d12c1 40 // Check AckReceived
ubhat 0:69f2e28d12c1 41 // Check NbRetries
ubhat 0:69f2e28d12c1 42 LoRaMacUplinkStatus.Acked = McpsConfirm->AckReceived;
ubhat 0:69f2e28d12c1 43 break;
ubhat 0:69f2e28d12c1 44 }
ubhat 0:69f2e28d12c1 45 case MCPS_PROPRIETARY:
ubhat 0:69f2e28d12c1 46 {
ubhat 0:69f2e28d12c1 47 break;
ubhat 0:69f2e28d12c1 48 }
ubhat 0:69f2e28d12c1 49 default:
ubhat 0:69f2e28d12c1 50 break;
ubhat 0:69f2e28d12c1 51 }
ubhat 0:69f2e28d12c1 52 }
ubhat 0:69f2e28d12c1 53
ubhat 0:69f2e28d12c1 54 LoRaMacUplinkStatus.Datarate = McpsConfirm->Datarate;
ubhat 0:69f2e28d12c1 55 LoRaMacUplinkStatus.UplinkCounter = McpsConfirm->UpLinkCounter;
ubhat 0:69f2e28d12c1 56 LoRaMacUplinkStatus.TxPower = McpsConfirm->TxPower;
ubhat 0:69f2e28d12c1 57
ubhat 5:6ffeac53b7cb 58 IsTxIntUpdate = true;
ubhat 0:69f2e28d12c1 59 }
ubhat 0:69f2e28d12c1 60
ubhat 0:69f2e28d12c1 61 /*!
ubhat 0:69f2e28d12c1 62 * \brief MCPS-Indication event function
ubhat 0:69f2e28d12c1 63 *
ubhat 0:69f2e28d12c1 64 * \param [IN] McpsIndication - Pointer to the indication structure,
ubhat 0:69f2e28d12c1 65 * containing indication attributes.
ubhat 0:69f2e28d12c1 66 */
ubhat 0:69f2e28d12c1 67 void McpsIndication( McpsIndication_t *McpsIndication )
ubhat 0:69f2e28d12c1 68 {
ubhat 0:69f2e28d12c1 69 uint8_t port;
ubhat 0:69f2e28d12c1 70
ubhat 0:69f2e28d12c1 71 Gps.service( );
ubhat 0:69f2e28d12c1 72
ubhat 0:69f2e28d12c1 73 if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
ubhat 0:69f2e28d12c1 74 {
ubhat 0:69f2e28d12c1 75 return;
ubhat 0:69f2e28d12c1 76 }
ubhat 0:69f2e28d12c1 77
ubhat 0:69f2e28d12c1 78 switch( McpsIndication->McpsIndication )
ubhat 0:69f2e28d12c1 79 {
ubhat 0:69f2e28d12c1 80 case MCPS_UNCONFIRMED:
ubhat 0:69f2e28d12c1 81 {
ubhat 0:69f2e28d12c1 82 break;
ubhat 0:69f2e28d12c1 83 }
ubhat 0:69f2e28d12c1 84 case MCPS_CONFIRMED:
ubhat 0:69f2e28d12c1 85 {
ubhat 0:69f2e28d12c1 86 break;
ubhat 0:69f2e28d12c1 87 }
ubhat 0:69f2e28d12c1 88 case MCPS_PROPRIETARY:
ubhat 0:69f2e28d12c1 89 {
ubhat 0:69f2e28d12c1 90 break;
ubhat 0:69f2e28d12c1 91 }
ubhat 0:69f2e28d12c1 92 case MCPS_MULTICAST:
ubhat 0:69f2e28d12c1 93 {
ubhat 0:69f2e28d12c1 94 break;
ubhat 0:69f2e28d12c1 95 }
ubhat 0:69f2e28d12c1 96 default:
ubhat 0:69f2e28d12c1 97 break;
ubhat 0:69f2e28d12c1 98 }
ubhat 0:69f2e28d12c1 99
ubhat 0:69f2e28d12c1 100 // Check Multicast
ubhat 0:69f2e28d12c1 101 // Check Port
ubhat 0:69f2e28d12c1 102 // Check Datarate
ubhat 0:69f2e28d12c1 103 // Check FramePending
ubhat 0:69f2e28d12c1 104 // Check Buffer
ubhat 0:69f2e28d12c1 105 // Check BufferSize
ubhat 0:69f2e28d12c1 106 // Check Rssi
ubhat 0:69f2e28d12c1 107 // Check Snr
ubhat 0:69f2e28d12c1 108 // Check RxSlot
ubhat 0:69f2e28d12c1 109 LoRaMacDownlinkStatus.Rssi = McpsIndication->Rssi;
ubhat 0:69f2e28d12c1 110 if( McpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
ubhat 0:69f2e28d12c1 111 {
ubhat 0:69f2e28d12c1 112 // Invert and divide by 4
ubhat 0:69f2e28d12c1 113 LoRaMacDownlinkStatus.Snr = ( ( ~McpsIndication->Snr + 1 ) & 0xFF ) >> 2;
ubhat 0:69f2e28d12c1 114 LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
ubhat 0:69f2e28d12c1 115 }
ubhat 0:69f2e28d12c1 116 else
ubhat 0:69f2e28d12c1 117 {
ubhat 0:69f2e28d12c1 118 // Divide by 4
ubhat 0:69f2e28d12c1 119 LoRaMacDownlinkStatus.Snr = ( McpsIndication->Snr & 0xFF ) >> 2;
ubhat 0:69f2e28d12c1 120 }
ubhat 0:69f2e28d12c1 121 LoRaMacDownlinkStatus.DownlinkCounter++;
ubhat 0:69f2e28d12c1 122 LoRaMacDownlinkStatus.RxData = McpsIndication->RxData;
ubhat 0:69f2e28d12c1 123 LoRaMacDownlinkStatus.Port = McpsIndication->Port;
ubhat 0:69f2e28d12c1 124 LoRaMacDownlinkStatus.Buffer = McpsIndication->Buffer;
ubhat 0:69f2e28d12c1 125 LoRaMacDownlinkStatus.BufferSize = McpsIndication->BufferSize;
ubhat 0:69f2e28d12c1 126 LoRaMacDownlinkStatus.RxSlot = McpsIndication->RxSlot;
ubhat 0:69f2e28d12c1 127
ubhat 0:69f2e28d12c1 128 if( ComplianceTest.Running == 1 )
ubhat 0:69f2e28d12c1 129 {
ubhat 0:69f2e28d12c1 130 port = 224;
ubhat 0:69f2e28d12c1 131 ComplianceTest.DownLinkCounter++;
ubhat 0:69f2e28d12c1 132 }
ubhat 0:69f2e28d12c1 133 else
ubhat 0:69f2e28d12c1 134 {
ubhat 0:69f2e28d12c1 135 port = McpsIndication->Port;
ubhat 0:69f2e28d12c1 136 }
ubhat 0:69f2e28d12c1 137
ubhat 0:69f2e28d12c1 138 if( McpsIndication->RxData == true )
ubhat 0:69f2e28d12c1 139 {
ubhat 0:69f2e28d12c1 140 switch( port )
ubhat 0:69f2e28d12c1 141 {
ubhat 0:69f2e28d12c1 142 case 1: // The application LED can be controlled on port 1 or 2
ubhat 0:69f2e28d12c1 143 case 2:
ubhat 0:69f2e28d12c1 144 break;
ubhat 0:69f2e28d12c1 145 case 224:
ubhat 0:69f2e28d12c1 146 PrepareComplianceTestFrame( McpsIndication );
ubhat 0:69f2e28d12c1 147 break;
ubhat 0:69f2e28d12c1 148 default:
ubhat 0:69f2e28d12c1 149 break;
ubhat 0:69f2e28d12c1 150 }
ubhat 0:69f2e28d12c1 151 }
ubhat 0:69f2e28d12c1 152
ubhat 0:69f2e28d12c1 153 IsRxUpdate = true;
ubhat 0:69f2e28d12c1 154
ubhat 0:69f2e28d12c1 155 }
ubhat 0:69f2e28d12c1 156
ubhat 0:69f2e28d12c1 157 /*!
ubhat 0:69f2e28d12c1 158 * \brief MLME-Confirm event function
ubhat 0:69f2e28d12c1 159 *
ubhat 0:69f2e28d12c1 160 * \param [IN] MlmeConfirm - Pointer to the confirm structure,
ubhat 0:69f2e28d12c1 161 * containing confirm attributes.
ubhat 0:69f2e28d12c1 162 */
ubhat 0:69f2e28d12c1 163 void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
ubhat 0:69f2e28d12c1 164 {
ubhat 0:69f2e28d12c1 165 if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
ubhat 0:69f2e28d12c1 166 {
ubhat 0:69f2e28d12c1 167 switch( MlmeConfirm->MlmeRequest )
ubhat 0:69f2e28d12c1 168 {
ubhat 0:69f2e28d12c1 169 case MLME_JOIN:
ubhat 0:69f2e28d12c1 170 {
ubhat 0:69f2e28d12c1 171 // Status is OK, node has joined the network
ubhat 0:69f2e28d12c1 172 IsNetworkJoinedStatusUpdate = true;
ubhat 0:69f2e28d12c1 173 break;
ubhat 0:69f2e28d12c1 174 }
ubhat 0:69f2e28d12c1 175 case MLME_LINK_CHECK:
ubhat 0:69f2e28d12c1 176 {
ubhat 0:69f2e28d12c1 177 // Check DemodMargin
ubhat 0:69f2e28d12c1 178 // Check NbGateways
ubhat 0:69f2e28d12c1 179 if( ComplianceTest.Running == true )
ubhat 0:69f2e28d12c1 180 {
ubhat 0:69f2e28d12c1 181 ComplianceTest.LinkCheck = true;
ubhat 0:69f2e28d12c1 182 ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin;
ubhat 0:69f2e28d12c1 183 ComplianceTest.NbGateways = MlmeConfirm->NbGateways;
ubhat 0:69f2e28d12c1 184 }
ubhat 0:69f2e28d12c1 185 break;
ubhat 0:69f2e28d12c1 186 }
ubhat 0:69f2e28d12c1 187 default:
ubhat 0:69f2e28d12c1 188 break;
ubhat 0:69f2e28d12c1 189 }
ubhat 0:69f2e28d12c1 190 }
ubhat 0:69f2e28d12c1 191
ubhat 5:6ffeac53b7cb 192 // Schedule next packet transmission
ubhat 5:6ffeac53b7cb 193 TimerSetValue( &TxNextPacketTimer, OVER_THE_AIR_ACTIVATION_DUTYCYCLE );
ubhat 5:6ffeac53b7cb 194 TimerStart( &TxNextPacketTimer );
ubhat 5:6ffeac53b7cb 195
ubhat 5:6ffeac53b7cb 196 DeviceState = DEVICE_STATE_SLEEP;
ubhat 0:69f2e28d12c1 197 }