Décodage de la transmission LoRa avec ESP32Forth
publication: 22 janvier 2022 / mis à jour 31 janvier 2022
Appel à collaboration
Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.
Partagez-les ici sur ce site.
ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.
Vos montages peuvent aider d'autres développeurs.
Les montages des autres développeurs peuvent vous aider.
Pour proposer un article ou un montage, cliquez ici
Listing complet: Decoding LoRa transmission with ESP32Forth
Environnement de développement requis
Pour décoder la chaîne reçue par le transmetteur LoRa REYAX RYLR890, il faut:
- utiliser strings management for ESP32forth
On reconstitue la variable alphanumérique LoRaRX
et on lui
affectue un contenu identique à celui reçu par le transmetteur LoRa SLAV2
(voir précédent article):
256 string LoRaRX s"+RCV=55,27,this is a transmission test,-36,40 " LoRaRX $! $0d LoRaRX c+$! $0a LoRaRX c+$!
Décodage de la transmission
Ici, le dump mémoire de LoRaRX
strictement identique à celui
reçu par le transmetteur LoRa:
--addr--- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ------chars----- 3FFF-84D0 E0 BB FF 3F 00 01 00 00 30 00 00 00 2B 52 43 56 ...?....0...+RCV 3FFF-84E0 3D 35 35 2C 32 37 2C 74 68 69 73 20 69 73 20 61 =55,27,this is a 3FFF-84F0 20 74 72 61 6E 73 6D 69 73 73 69 6F 6E 20 74 65 transmission te 3FFF-8500 73 74 2C 2D 33 36 2C 34 30 20 0D 0A FB 9B 52 60 st,-36,40 ....R`
On va se débarrasser des deux octets 0D 0A en créant le mot normalize$
:
2 string $crlf $0d $crlf c+$! $0a $crlf c+$! \ delete crlf at end of string : normalize$ ( addr len -- ) 2dup + 2 - 2 $crlf $= if \ if end string = crlf 2 - swap cell - ! \ substract 2 at length of string else 2drop then ;
Le mot normalize$
teste si la chaîne qui lui est présentée se
termine par 0D 0A. Si c'est le cas, la taille de la chaîne est
diminuée de deux unités.
Une fois normalisée, la chaîne de caractères du message LoRa peut être analysée:
+RCV=55,27,this is a transmission test,-36,40
Décomposition du message LoRa
Nous allons décomposer ce message:
- +RCV= en-tête du message indiquant une réception AT+RCV
- 55 adresse de l'émetteur LoRa qui a envoyé le message
- 27 longueur des données reçues
- this is a transmission test données reçues
- -36 valeur RSSI (Received Signal Strength Indicator)
- 40 valeur SNR (Signal-to-noise ratio)
Pour mémoriser chacun de ces éléments, donc permettre un traitement avec d'autres mots, on va créer six chaînes alphanumériques:
\ RCV analyse 12 string RCVhead \ head transmission 6 string RCVaddr \ master LoRa address 4 string RCVlength \ length transmitted datas 256 string RCVdata \ transmitted datas 5 string RCVrssi \ Received Signal Strength Indicator 5 string RCVsnr \ Signal-to-noise ratio
Pour voir le contenu de ces variables alphanumériques, on crée le mot disVar
.
ce mot n'aura pas d'autre utilité plus tard:
: disVars ( -- )
cr
." RCVhead.....: " RCVhead type cr
." RCVaddr.....: " RCVaddr type cr
." RCVlength...: " RCVlength type cr
." RCVdata.....: " RCVdata type cr
." RCVrssi.....: " RCVrssi type cr
." RCVsnr......: " RCVsnr type cr
;
Décomposition de la transmission LoRa
Le but de notre code sera de placer dans chaque variable alphanumérique
RCVhead RCVaddr RCVlength RCVdata RCVrssi RCVsnr RCVsnr
les différents champs du message reçu par le transmetteur LoRa.
On va d'abord créer un mot qui remet à zéro ces variables alphanumériques:
\ set length of all strings to 0 : initStrings ( -- ) RCVhead 0$! RCVaddr 0$! RCVlength 0$! RCVdata 0$! RCVrssi 0$! RCVsnr 0$! ;
On définit ensuite RCV?
qui détermine si la transmission reçue
commence par +RCV=. Ce mot évitera de traiter un message qui n'est pas issu
d'une transmission LoRa:
\ test if string begin with "+RCV=" : RCV? ( addr len -- fl ) dup 0 > if drop 5 s" +RCV=" $= else 2drop 0 then ;
On définit ensuite le mot scan$
qui recherche la présence d'un caractère
donné. L'analyse de la chaîne s'interrompt si le caractère recherché est trouvé et
ajuste la longeur de la chaîne analysée:
: scan$ { char addr len -- addr len' } 0 \ start index begin dup addr + c@ char <> over len < and while 1+ \ increment index repeat addr swap dup len = if drop 0 then ;
Le code FORTH qui suit contient beaucoup de petites définitions. C'est volontaire. Cette méthode permet de vérifier chaque définition via le terminal. Il est possible d'optimiser le code, mais le but est en priorité de définir des mots efficaces et fonctionnels et faciles à comprendre.
Le mot calcNewPosition
restitue la sous-chaîne issue de LoRaRX
en prenant en compte chaque variable alphanumérique extraite:
variable strPos
: calcNewPosition ( -- addr len )
0 strPos !
RCVhead nip ?dup
if strPos +! then
RCVaddr nip ?dup
if 1+ strPos +! then
RCVlength nip ?dup
if 1+ strPos +! then
RCVdata nip ?dup
if 1+ strPos +! then
RCVrssi nip ?dup
if 1+ strPos +! then
LoRaRX swap strPos @ +
swap strPos @ -
;
On part du groupe de variables alphanumériques RCVhead RCVaddr RCVlength
RCVdata RCVrssi RCVsnr RCVsnr
, donc toutes avec une taille nulle.
On extrait le premier champ de LoRaRX
vers RCVhead
.
Ce n'est pas une vraie extraction, mais une instanciation qui ne s'effectuera que
si LoRaRX
commence par +RCV=:
\ extract RCVhead : getRCVhead ( -- ) s" +RCV=" RCVhead $! ;
L'exécution de ce mot getRCVhead
modifiera le comportement du mot
calcNewPosition
. Chaque mot qui récupère le contenu d'une variable
alphanumérique aura donc une action sur le comportement de calcNewPosition
:
\ extract RCVaddr : getRCVaddr ( -- ) [char] , calcNewPosition scan$ RCVaddr $! ; \ extract RCVlength : getRCVlength ( -- ) [char] , calcNewPosition scan$ RCVlength $! ; : eval$ ( addr len -- n ) S>NUMBER? ?dup if drop then ; \ extract RCVdata : getRCVdata ( -- ) calcNewPosition drop RCVlength eval$ RCVdata $! ; \ extract RCVrssi : getRCVrssi ( -- ) [char] , calcNewPosition scan$ RCVrssi $! ; \ extract RCVrssi : getRCVsnr ( -- ) calcNewPosition RCVsnr $! ;
Il n'était pas possible de découper les champs de LoRaRX
comme si
c'était un enregistrement dans une base de données. certes, on a comme séparateur le
caractère ",", mais si ce caractère se retrouve dans le contenu du champ RCVdata
on risque de perturber un décodage s'appuyant sur un scan simple. D'ailleurs, le mot
getRCVdata
s'appuie sur le contenu du champ RCVlength
en
évaluant son contenu pour passer au champ suivant.
Et enfin, on arrive au mot RXdecode
qui fait l'analyse du contenu de
LoRaRX
. Cette analyse ne s'effectue que si le contenu de LoraRX
commence par +RCV=:
: RXdecode ( -- ) LoRaRX normalize$ \ extract RCVhead LoRaRX RCV? if \ test if LoRaRX begin with "+RCV=" initStrings \ empty all strings getRCVhead getRCVaddr getRCVlength getRCVdata getRCVrssi getRCVsnr then ;
Il suffit d'exécuter RXdecode
puis de voir le contenu des
variables alphanumériques en tapant disVars
:
--> disVars RCVhead.....: +RCV= RCVaddr.....: 55 RCVlength...: 27 RCVdata.....: this is a transmission test RCVrssi.....: -36 RCVsnr......: 40
On va vous donner une première piste pour l'interface avec d'autres programmes.
Le secret, c'est l'évaluation du contenu de la variable alphanumérique RCVdata
.
Si on a un relais à activer avec la séquence FORTH relay01 on
,
il suffit que le transmetteur LoRa envoie comme contenu du message la
chaine FORTH relay01 on
. Le mot FORTH de ESP32Forth qui effectuera
l'interface est evaluate
...
Et c'est tout!!!!
C'est ce que nous verrons dans l'article suivant...
Legal: site web personnel sans commerce / personal site without seling