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:
Tue May 17 00:21:55 2016 +0000
Revision:
0:69f2e28d12c1
Child:
16:e3c1e68959cf
Project for LoRa Bootcamp

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