LoRa transmission decoding on Arduino NANO

published: 14 October 2020 / updated 14 October 2020

Lire cette page en français

 

Preamble

Before decoding a message sent by our LoRa transmitter, we will define two words: string and $!

\ define a strvar 
: string  ( n --- names_strvar) 
    create 
        dup 
        c,      \ n is maxlength 
        0 c,    \ 0 is real length 
        allot 
    does> 
        2 + 
        dup 1 - c@ 
  ; 
 
\ store str into strvar 
: $!  ( str strvar ---) 
    drop 
    dup 2- c@       \ get maxlength of strvar 
    rot min         \ keep min length 
    2dup swap 1- c! \ store real length 
    cmove           \ copy string 
  ; 

The word string creates an alphanumeric string variable. Example:

80 string RCVdata 

reserves in RAM memory an area of 80 bytes intended to store a text.

The word $! is used to store a character string in an alphanumeric variable. Example:

: example ( ---) 
    s" Store a text in RCVdata" 
    RCVdata $! 
  ; 

Running our word example transfers the string Store a text in RCVdata in the alphanumeric variable RCVdata. We can see the content of this variable:

RCVdata type 
\ display: Store a text in RCVdata 

Transmission decoding

In our previous article Our first LoRa transmission from an Arduino NANO we sent a message. On the LoRa transmitter that received this message, we have received this:
  +RCV=22,36,This is our first LoRa Transmission!,-37,31

Decomposition of the LoRa message

We will break down this message:

To memorize each of these elements, thus allowing a treatment with other words, we will create four variables and two alphanumeric strings:

\ RCV analyse 
12 string RCVhead   \ head transmission 
0 value  RCVaddr    \ master LoRa address 
0 value  RCVlength  \ length transmitted datas 
80 string RCVdata   \ transmitted datas 
0 value  RCVrssi    \ Received Signal Strength Indicator 
0 value  RCVsnr     \ Signal-to-noise ratio 

Note: the size of the RCVdata string has been limited to 80 characters. A LoRa transmission can be up to 243 characters long. If you need to manage data of more than 80 characters, you can change the initialization of RCVdata.

Message content scan

In a message transmitted over our LoRa network, there are two characters which will serve as delimiters: "=" and ",". If the data contain a "," character, we will bypass this character.

We will create the word RCVscan which searches for a string delimiter from a given point in a chain. This word leaves on the stack the address and length of the string between our starting point of analysis and this delimiter.

Definition of RCVscan

\ scan RCV string, search char delimiter 
: RCVscan ( str1 char --- str2) 
    >r 
    2dup 
    r> scan 
    swap drop - 
  ; 

Example:

-test 
marker -test 
 
: test01 
    \ test string, leave addr len on stack 
    s" +RCV=22,36,This is our first LoRa Transmission!,-37,31" 
    61 RCVscan          \ search character '=' 
  ; 
test01  \ leave 33569 4 on stack 
type    \ display +RCV 

The sequence 61 RCVscan searches for the character "=" from from the start of the string s" +RCV=22,36,This is our first LoRa Transmission!,-37,31"

Complete decoding of a message

To test our decoding word, we will create the word test. This word contains the text of our message. In the word defines attached to the application of transmission, the text will be intercepted by the FlashForth input buffer.

Complete and operational definition of test:

-test 
marker -test 
 
: test 
    \ test string, leave addr len on stack 
    s" +RCV=22,36,This is our first LoRa Transmission!,-37,31" 
    over over >r >r     \ save initial address 
    \ *** Decode and store RCVhead 
    61 RCVscan          \ search character '=' 
    2dup RCVhead $!     \ store result in RCVhead 
    1+ +  10            \ new offset after '=' 
    \ *** Decode and store RCVaddr 
    44 RCVscan          \ search character ',' 
    2dup interpret      \ convert string to n 
    to RCVaddr          \ store n in RCVaddr 
    1+ +  10            \ new offset after ',' 
    \ *** Decode and store RCVlength 
    44 RCVscan          \ search second character ',' 
    2dup  interpret     \ convert string to n 
    to RCVlength        \ store n in RCVlength 
    \ *** Decode and store RCVdata 
    1+ + dup RCVlength RCVdata 
    $! \ store datas in RCVdata 
    \ *** Decode and store RCVrssi 
    1+ RCVlength + 10 
    44 RCVscan          \ search character ',' 
    2dup 
    interpret           \ convert string to n 
    to RCVrssi          \ store n in RCVrssi 
    \ *** Decode and store RCVsnr 
    \ end of string 
    + 1+ 
    r> r> + 
     over  - 
    interpret           \ convert string to n 
    to RCVsnr 
  ; 

We analyze and save all fields of the message, including RSSI and SNR.

RSSI

The Received Signal Strength Indication (RSSI) is the received signal power in milliwatts and is measured in dBm.

This value can be used as a measurement of how well a receiver can “hear” a signal from a sender.

The RSSI is measured in dBm and is a negative value.

The closer to 0 the better the signal is.

Typical LoRa RSSI values are:

SNR

Signal-to-Noise Ratio (SNR) is the ratio between the received power signal and the noise floor power level.

The noise floor is an area of all unwanted interfering signal sources which can corrupt the transmitted signal and therefore re-transmissions will occur.

Normally the noise floor is the physical limit of sensitivity, however LoRa works below the noise level.

Typical LoRa SNR values are between: -20dB and +10dB

A value closer to +10dB means the received signal is less corrupted.

LoRa can demodulate signals which are -7.5 dB to -20 dB below the noise floor.

Processing of the Data field

Let's come back to the word test and more particularly to this portion of code:

\ *** Decode and store RCVaddr 
44 RCVscan          \ search character ',' 
2dup interpret      \ convert string to n 
to RCVaddr          \ store n in RCVaddr 

We see the word interpret. If a character string contains code in FORTH language, the word interpret will analyze and execute this FORTH code!

Let's take an example. To do this, let's review the relay management as explained in the article
  Management of a 4 relay module.

In this article, the activation of a relay can be requested simply from the terminal by:

RELAY1 high 

If a LoRa module issues a message containing this Forth command, our decoding program of LoRa message will store this data RELAY1 high in the variable RCVdata.

To run this content and activate a relay connected to our ARDUINO NANO remotely, you must therefore:

There you go! Thanks to two LoRa transmitters, two ARDUINO NANO cards, you can activate any device, transmit data...

But are we sure that our relay is activated?

We could simply do several tests and find that triggering an action occurs with every solicitation.

But it only takes one time that the transmission process fails to have a few worries.

We must therefore consider the management of a real exchange protocol. This is the subject of the next article.