dimanche 12 décembre 2021

HC-12

Le HC-12 est un petit module radio bon marché pour faire de la communication sans fil entre Arduino et trucs du genre. La communication se fait par ligne série et ne nécessite que 4 fils (GND, VDD, TX, Rx). Il est possible de changer les paramètres de communication au moyen de commandes 'AT' après avoir mis la ligne 'SET' à la masse (elle est équipée d'une pull-up et, par défaut, le module est en mode transmission/réception sur 433.4 MHz et 9600 bauds 8 bits, un stop bit et pas de parité. La communication radio utilise un Si4463 de Silicon Labs piloté par un microcontrôleur STM8S avec un code non public (ici, il se propose d'en modifier le firmware...).

Raspberry Pi

Les quatre fils peuvent facilement être connectés à un Raspberry Pi. La documentation du module semble être une traduction du chinois et l'utilisation des commandes 'AT' n'est pas claire... En principe, il suffirait de prendre minicom et de faire
$ minicom -b 9600 -D /dev/ttyS0
et de taper 'AT' pour voir apparaître 'OK' mais le Diable se cache dans les détails et plusieurs obstacles doivent d'abord être franchis. D'abord, pour pouvoir accéder au ttyS0 comme utilisateur normal, il faut qu'il appartienne au groupe 'dialout' (sudo usermod -a -G dialout <user>). Ensuite, comme rien ne fonctionne comme prévu, revenons à la base et connectons le TX du Raspberry Pi au TX. On s'aperçoit alors qu'il y a un getty qui tourne par défaut. Il faut le désactiver (via sudo raspi-config). Après avoir raccordé le SET du module au GND du Raspberry, on s'aperçoit que le 'T' doit suivre de très près le 'A' pour que le firmware comprenne 'AT' (copier/coller dans minicom). Et donc, tout va bien, le module semble fonctionner. Déconnectons SET et utilisons le module en configuration standard (433.4 MHz, 9600 bauds 8 bits, un stop bit et pas de parité et ...puissance radio maximum).

Il est sûrement possible de communiquer entre deux modules (c'est fait pour ça) mais, ce qui m'intéresse c'est de voir à quoi ressemble le signal radio... Pour cela, je vais émettre de manière répétée une petite chaîne de caractères constante, ou même un caractère unique. Un 'U', par exemple, dont le code ASCII est 0x55 (0101.0101). Comme le message envoyé ne va pas être très long, je peux le répéter très souvent, genre 200 fois par seconde (après avoir testé avec un rythme moins soutenu).
$ while sleep .005; do echo -n "U" > /dev/ttyS0; done

GnuRadio

Pour voir si le module émet quelque chose, j'utilise GnuRadio avec un RTL-SDR (ou équivalent à quelques euros).
Le truc de base : un module source, rtl-sdr, et deux sink QT pour la visualisation, frequency et waterfall. Je prends une fréquence d'échantillonnage raisonnable et centre le tout sur 433.4 MHz.
Donc le module fonctionne et je peux générer du signal à volonté.

rtl-sdr et GNU Octave

Maintenant, enregistrons une courte séquence avec l'utilitaire 'rtl-sdr' sur le portable :
$ rtl_sdr -f 433400000 -s 512000 -n 64000 U.iq8
et utilisons GNU Octave pour visualiser le signal que l'on suppose être un type de modulation de fréquence (GFSK ou GMSK?). On s'intéresse donc à la phase (arg(i+j.q)). On utilise unwrap() pour éviter les saut 0/360°. Et, par tâtonnement, on sélectionne un intervalle contenant le signal recherché.
$ cat print_phase.m 
s=loadFile("U.iq8");
au=unwrap(arg(s));
plot(au(10000:14100));
print -dpng "signal.png"
Et nous obtenons :
NB: loadFile() lit un fichier IQ 8 bits de rtl-sdr pour en faire un vecteur complexe flottant.
$ cat loadFile.m 
function y = loadFile(filename)
%  y = loadFile(filename)
%
% reads  complex samples from the rtlsdr file 
%

fid = fopen(filename,'rb');
y = fread(fid,'uint8=>double');

y = y-127;
y = y(1:2:end) + i*y(2:2:end);
Si j'extrais une partie intéressante, la sors dans un fichier texte et l'affiche avec une grille adéquate dans Gnuplot, cela donne (après avoir zoomé dans le graphique) :
octave> ua2=unwrap(arg(loadFile("U.4399500l.256k.iq8")));
octave> plot(ua2)
octave> zz=ua2(4030:8102);
octave> plot(zz);
octave> csvwrite ('msg.dat', zz);
---
gnuplot> set style line 100 lt 1  lw 2
gnuplot> set grid ls 100
gnuplot> set xtics autofreq 17 
gnuplot> plot 'msg.dat' with lines lw 2
On observe des intervalles où la courbe (qui représente la phase du signal) change de pente et d'autres où elle conserve sa pente.