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:
0:69f2e28d12c1
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: VT100 terminal support class
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 #ifndef __VT100_H__
ubhat 0:69f2e28d12c1 16 #define __VT100_H__
ubhat 0:69f2e28d12c1 17
ubhat 0:69f2e28d12c1 18 #ifndef STRING_STACK_LIMIT
ubhat 0:69f2e28d12c1 19 #define STRING_STACK_LIMIT 120
ubhat 0:69f2e28d12c1 20 #endif
ubhat 0:69f2e28d12c1 21
ubhat 0:69f2e28d12c1 22 /**
ubhat 0:69f2e28d12c1 23 * Implements VT100 terminal commands support.
ubhat 0:69f2e28d12c1 24 * Implments also the same behaviour has RawSerial class. The only difference
ubhat 0:69f2e28d12c1 25 * is located in putc fucntion where writeable check is made befor sending the character.
ubhat 0:69f2e28d12c1 26 */
ubhat 0:69f2e28d12c1 27 class VT100 : public SerialBase
ubhat 0:69f2e28d12c1 28 {
ubhat 0:69f2e28d12c1 29 public:
ubhat 0:69f2e28d12c1 30 enum TextAttributes
ubhat 0:69f2e28d12c1 31 {
ubhat 0:69f2e28d12c1 32 ATTR_OFF = 0,
ubhat 0:69f2e28d12c1 33 BOLD = 1,
ubhat 0:69f2e28d12c1 34 USCORE = 4,
ubhat 0:69f2e28d12c1 35 BLINK = 5,
ubhat 0:69f2e28d12c1 36 REVERSE = 7,
ubhat 0:69f2e28d12c1 37 BOLD_OFF = 21,
ubhat 0:69f2e28d12c1 38 USCORE_OFF = 24,
ubhat 0:69f2e28d12c1 39 BLINK_OFF = 25,
ubhat 0:69f2e28d12c1 40 REVERSE_OFF = 27,
ubhat 0:69f2e28d12c1 41 };
ubhat 0:69f2e28d12c1 42
ubhat 0:69f2e28d12c1 43 enum Colors
ubhat 0:69f2e28d12c1 44 {
ubhat 0:69f2e28d12c1 45 BLACK = 0,
ubhat 0:69f2e28d12c1 46 RED = 1,
ubhat 0:69f2e28d12c1 47 GREEN = 2,
ubhat 0:69f2e28d12c1 48 BROWN = 3,
ubhat 0:69f2e28d12c1 49 BLUE = 4,
ubhat 0:69f2e28d12c1 50 MAGENTA = 5,
ubhat 0:69f2e28d12c1 51 CYAN = 6,
ubhat 0:69f2e28d12c1 52 WHITE = 7,
ubhat 0:69f2e28d12c1 53 };
ubhat 0:69f2e28d12c1 54
mluis 18:18408c3c2d0c 55 VT100( PinName tx, PinName rx ): SerialBase( tx, rx, 115200 )
ubhat 0:69f2e28d12c1 56 {
ubhat 0:69f2e28d12c1 57 // initializes terminal to "power-on" settings
ubhat 0:69f2e28d12c1 58 // ESC c
ubhat 0:69f2e28d12c1 59 this->printf( "\x1B\x63" );
ubhat 0:69f2e28d12c1 60 }
ubhat 0:69f2e28d12c1 61
ubhat 0:69f2e28d12c1 62 void ClearScreen( uint8_t param )
ubhat 0:69f2e28d12c1 63 {
ubhat 0:69f2e28d12c1 64 // ESC [ Ps J
ubhat 0:69f2e28d12c1 65 // 0 Clear screen from cursor down
ubhat 0:69f2e28d12c1 66 // 1 Clear screen from cursor up
ubhat 0:69f2e28d12c1 67 // 2 Clear entire screen
ubhat 0:69f2e28d12c1 68 this->printf( "\x1B[%dJ", param );
ubhat 0:69f2e28d12c1 69 }
ubhat 0:69f2e28d12c1 70
ubhat 0:69f2e28d12c1 71 void ClearLine( uint8_t param )
ubhat 0:69f2e28d12c1 72 {
ubhat 0:69f2e28d12c1 73 // ESC [ Ps K
ubhat 0:69f2e28d12c1 74 // 0 Erase from the active position to the end of the line, inclusive (default)
ubhat 0:69f2e28d12c1 75 // 1 Erase from the start of the screen to the active position, inclusive
ubhat 0:69f2e28d12c1 76 // 2 Erase all of the line, inclusive
ubhat 0:69f2e28d12c1 77 this->printf( "\x1B[%dK", param );
ubhat 0:69f2e28d12c1 78 }
ubhat 0:69f2e28d12c1 79
ubhat 0:69f2e28d12c1 80 void SetAttribute( uint8_t attr )
ubhat 0:69f2e28d12c1 81 {
ubhat 0:69f2e28d12c1 82 // ESC [ Ps;...;Ps m
ubhat 0:69f2e28d12c1 83 this->printf( "\x1B[%dm", attr );
ubhat 0:69f2e28d12c1 84 }
ubhat 0:69f2e28d12c1 85
ubhat 0:69f2e28d12c1 86 void SetAttribute( uint8_t attr, uint8_t fgcolor, uint8_t bgcolor )
ubhat 0:69f2e28d12c1 87 {
ubhat 0:69f2e28d12c1 88 // ESC [ Ps;...;Ps m
ubhat 0:69f2e28d12c1 89 this->printf( "\x1B[%d;%d;%dm", attr, fgcolor + 30, bgcolor + 40 );
ubhat 0:69f2e28d12c1 90 }
ubhat 0:69f2e28d12c1 91
ubhat 0:69f2e28d12c1 92 void SetCursorMode( uint8_t visible )
ubhat 0:69f2e28d12c1 93 {
ubhat 0:69f2e28d12c1 94 if( visible == true )
ubhat 0:69f2e28d12c1 95 {
ubhat 0:69f2e28d12c1 96 // ESC [ ? 25 h
ubhat 0:69f2e28d12c1 97 this->printf( "\x1B[?25h" );
ubhat 0:69f2e28d12c1 98 }
ubhat 0:69f2e28d12c1 99 else
ubhat 0:69f2e28d12c1 100 {
ubhat 0:69f2e28d12c1 101 // ESC [ ? 25 l
ubhat 0:69f2e28d12c1 102 this->printf( "\x1B[?25l" );
ubhat 0:69f2e28d12c1 103 }
ubhat 0:69f2e28d12c1 104 }
ubhat 0:69f2e28d12c1 105
ubhat 0:69f2e28d12c1 106 void SetCursorPos( uint8_t line, uint8_t col )
ubhat 0:69f2e28d12c1 107 {
ubhat 0:69f2e28d12c1 108 // ESC [ Pl ; Pc H
ubhat 0:69f2e28d12c1 109 this->printf( "\x1B[%d;%dH", line, col );
ubhat 0:69f2e28d12c1 110 }
ubhat 0:69f2e28d12c1 111
ubhat 0:69f2e28d12c1 112 void PutStringAt( uint8_t line, uint8_t col, const char *s )
ubhat 0:69f2e28d12c1 113 {
ubhat 0:69f2e28d12c1 114 this->SetCursorPos( line, col );
ubhat 0:69f2e28d12c1 115 this->printf( "%s", s );
ubhat 0:69f2e28d12c1 116 }
ubhat 0:69f2e28d12c1 117
ubhat 0:69f2e28d12c1 118 void PutCharAt( uint8_t line, uint8_t col, uint8_t c )
ubhat 0:69f2e28d12c1 119 {
ubhat 0:69f2e28d12c1 120 this->SetCursorPos( line, col );
ubhat 0:69f2e28d12c1 121 this->printf( "%c", c );
ubhat 0:69f2e28d12c1 122 }
ubhat 0:69f2e28d12c1 123
ubhat 0:69f2e28d12c1 124 void PutHexAt( uint8_t line, uint8_t col, uint16_t n )
ubhat 0:69f2e28d12c1 125 {
ubhat 0:69f2e28d12c1 126 this->SetCursorPos( line, col );
ubhat 0:69f2e28d12c1 127 this->printf( "%X", n );
ubhat 0:69f2e28d12c1 128 }
ubhat 0:69f2e28d12c1 129
ubhat 0:69f2e28d12c1 130 void PutBoxDrawingChar( uint8_t c )
ubhat 0:69f2e28d12c1 131 {
ubhat 0:69f2e28d12c1 132 this->printf( "\x1B(0%c\x1b(B", c );
ubhat 0:69f2e28d12c1 133 }
ubhat 0:69f2e28d12c1 134
ubhat 0:69f2e28d12c1 135 bool Readable( void )
ubhat 0:69f2e28d12c1 136 {
ubhat 0:69f2e28d12c1 137 return this->readable( );
ubhat 0:69f2e28d12c1 138 }
ubhat 0:69f2e28d12c1 139
ubhat 0:69f2e28d12c1 140 uint8_t GetChar( void )
ubhat 0:69f2e28d12c1 141 {
ubhat 0:69f2e28d12c1 142 return this->getc( );
ubhat 0:69f2e28d12c1 143 }
ubhat 0:69f2e28d12c1 144
ubhat 0:69f2e28d12c1 145 /*
ubhat 0:69f2e28d12c1 146 * RawSerial class implmentation copy.
ubhat 0:69f2e28d12c1 147 */
ubhat 0:69f2e28d12c1 148 /** Read a char from the serial port
ubhat 0:69f2e28d12c1 149 *
ubhat 0:69f2e28d12c1 150 * @returns The char read from the serial port
ubhat 0:69f2e28d12c1 151 */
ubhat 0:69f2e28d12c1 152 int getc( )
ubhat 0:69f2e28d12c1 153 {
mluis 18:18408c3c2d0c 154 return _base_getc( );
ubhat 0:69f2e28d12c1 155 }
ubhat 0:69f2e28d12c1 156
ubhat 0:69f2e28d12c1 157 /** Write a char to the serial port
ubhat 0:69f2e28d12c1 158 *
ubhat 0:69f2e28d12c1 159 * @param c The char to write
ubhat 0:69f2e28d12c1 160 *
ubhat 0:69f2e28d12c1 161 * @returns The written char or -1 if an error occured
ubhat 0:69f2e28d12c1 162 */
ubhat 0:69f2e28d12c1 163 int putc( int c )
ubhat 0:69f2e28d12c1 164 {
ubhat 0:69f2e28d12c1 165 while( this->writeable( ) != 1 );
ubhat 0:69f2e28d12c1 166 return _base_putc( c );
ubhat 0:69f2e28d12c1 167 }
ubhat 0:69f2e28d12c1 168
ubhat 0:69f2e28d12c1 169 /** Write a string to the serial port
ubhat 0:69f2e28d12c1 170 *
ubhat 0:69f2e28d12c1 171 * @param str The string to write
ubhat 0:69f2e28d12c1 172 *
ubhat 0:69f2e28d12c1 173 * @returns 0 if the write succeeds, EOF for error
ubhat 0:69f2e28d12c1 174 */
ubhat 0:69f2e28d12c1 175 int puts( const char *str )
ubhat 0:69f2e28d12c1 176 {
ubhat 0:69f2e28d12c1 177 while( *str )
ubhat 0:69f2e28d12c1 178 putc( *str++ );
ubhat 0:69f2e28d12c1 179 return 0;
ubhat 0:69f2e28d12c1 180 }
ubhat 0:69f2e28d12c1 181
ubhat 0:69f2e28d12c1 182 // Experimental support for printf in RawSerial. No Stream inheritance
ubhat 0:69f2e28d12c1 183 // means we can't call printf() directly, so we use sprintf() instead.
ubhat 0:69f2e28d12c1 184 // We only call malloc() for the sprintf() buffer if the buffer
ubhat 0:69f2e28d12c1 185 // length is above a certain threshold, otherwise we use just the stack.
ubhat 0:69f2e28d12c1 186 int printf( const char *format, ... )
ubhat 0:69f2e28d12c1 187 {
ubhat 0:69f2e28d12c1 188 std::va_list arg;
ubhat 0:69f2e28d12c1 189 va_start( arg, format );
ubhat 0:69f2e28d12c1 190 int len = vsnprintf( NULL, 0, format, arg );
ubhat 0:69f2e28d12c1 191 if( len < STRING_STACK_LIMIT )
ubhat 0:69f2e28d12c1 192 {
ubhat 0:69f2e28d12c1 193 char temp[STRING_STACK_LIMIT];
ubhat 0:69f2e28d12c1 194 vsprintf( temp, format, arg );
ubhat 0:69f2e28d12c1 195 puts( temp );
ubhat 0:69f2e28d12c1 196 }
ubhat 0:69f2e28d12c1 197 else
ubhat 0:69f2e28d12c1 198 {
ubhat 0:69f2e28d12c1 199 char *temp = new char[len + 1];
ubhat 0:69f2e28d12c1 200 vsprintf( temp, format, arg );
ubhat 0:69f2e28d12c1 201 puts( temp );
ubhat 0:69f2e28d12c1 202 delete[] temp;
ubhat 0:69f2e28d12c1 203 }
ubhat 0:69f2e28d12c1 204 va_end( arg );
ubhat 0:69f2e28d12c1 205 return len;
ubhat 0:69f2e28d12c1 206 }
ubhat 0:69f2e28d12c1 207
ubhat 0:69f2e28d12c1 208 private:
ubhat 0:69f2e28d12c1 209
ubhat 0:69f2e28d12c1 210 };
ubhat 0:69f2e28d12c1 211
ubhat 0:69f2e28d12c1 212 #endif // __VT100_H__