LoRa transmission decoding on Arduino NANO
published: 14 October 2020 / updated 14 October 2020
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:
- +RCV message header indicating AT + RCV reception
- 22 address of the LoRa sender who sent the message
- 36 length of data received
- This is our first LoRa Transmission! data received
- -37 RSSI value (Received Signal Strength Indicator)
- 31 SNR value (Signal-to-noise ratio)
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:
- RSSI minimum = -120 dBm.
- if RSSI=-30dBm: signal is strong.
- if RSSI=-120dBm: signal is weak.
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.
- if SNR is greater than 0, the received signal operates above the noise floor.
- if SNR is smaller than 0, the received signal operates below the noise floor.
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:
- the sender sends a message containing RELAY1 on
- the receiver decodes the message and stores RELAY1 on in
RCVdata
/li> - the content of
RCVdata
is parsed and executed by a sequenceRCVdata execute
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.