mercredi 10 juin 2026

StationMeteo DCF

Petite station météo radiopilotée (DFC77) d'intérieur Action à 9.99 euros chez Action en Belgique... La sonde externe envoie les mesures dans la bande ISM 433 MHz toutes les 67 secondes... On peut le voir avec l'application RF_Analyzer et une clé RTL-SDR.
Le temps s'écoule de bas en haut. On observe que le gain automatique s'adapte dès l'apparition du signal. Au départ, le bruit occupe toute la bande passante, le signal se démarque progressivement avant de disparaître. Peu de temps après, le gain augmente jusqu'à ce que le bruit occupe à nouveau toute la bande passante. Le 'démodulateur AM' du RF_Analyzer est activé juste pour avoir un signal sonore lors de la captation.
Le waterflow est bref pour s'intéresser uniquement à la transmission des données (état des piles, température et humidité) par le capteur externe avec un fichier pas trop grand. RF_Analyzer échantillonne au minimum à un million d'échantillons (de 2 octets) par seconde.
Dans octave(1), soupçonnant une communication OOK (On-Off-Keying), on s'intéresse à la norme ('abs()') des vecteurs IQ.
fid = fopen('core.iq','rb');
y = fread(fid,'uint8=>double');
y = y-127;
y = y(1:2:end) + i*y(2:2:end);

x=abs(y);
plot(x);
donne
Six salves probablement identiques dont les deux premières saturent le récepteur. La troisième se trouve encore dans la phase d'adaptation du gain automatique et les trois dernières sont stables. En zoomant sur la dernière salve
plot(x(1130000:1280000));
on obtient:
On peut encore zoomer pour avoir une idée du timing d'un bit...
plot(x(1134600:1140000));
On a donc, quelque chose comme 1 mS dans le préambule et 500 µS dans les bits qui suivent. En zoomant au plus proche sur un 'bit',
plot(x(1151659:1152144));
Et donc, 485 nS de largeur... 2400 bauds aurait donné 417 nS... Faudrait regarder sur la longueur d'une salve... En chipotant en 'C' avec la librtlsdr...
Les 6 salves sont bien identiques (à part, peut-être, le préambulle). Une salve resemble à
OregonScientific-RF-Protocols-II.pdf suggère que c'est le temps entre deux pulses qui déterminerait si il s'agit d'un '0' ou d'un '1' et que le même message est, en effet, répété un certain nombre de fois pour permettre à l'AGC de s'adapter.

À 250k échantillons par seconde, il y a 300 échantillons entre le préambule et la première impulsion et ensuite, 100 ou 200 échantillons suivant que c'est un '0' ou un '1'. Si on décode les messages pendant un certain temps, on obtient chaque fois cinq octets du genre :
10000110 00000000 01100101 10100101 01010001
10000110 00100000 01100101 11110101 01010001
10000110 01110000 01100101 11100101 01010001
10000110 10000000 01100101 11010101 01010001
10000110 11010000 01100101 11000101 01010001

ou (en échangeant les '0' et les '1')

01111001 11111111 10011010 01011010 10101110
01111001 11011111 10011010 00001010 10101110
01111001 10001111 10011010 00011010 10101110
01111001 01111111 10011010 00101010 10101110
01111001 00101111 10011010 00111010 10101110
Il faudrait faire varier un paramètre en essayant de garder les autres constant pour voir à quoi ils correspondent. Déjà, le dernier est constant, il n'y a donc pas de checksum ou de CRC... Ici, seuls les seconds et quatrième ont varié et on dirait que les bits de poids faible sont transmis en premier... A priori, 3 valeurs sont transmises (état des piles, humidité et température).

En traduisant les bits en octets, je ne parviens pas à les corréler avec la valeur affichée... (température en °C, % humidité, octets)
23.5 20		61 01 66 8D 86 
23.5 20		61 0B 66 85 86 
23.6 20		61 05 66 87 86 
23.7 20		61 06 E6 80 86 
23.8 20		61 0C E6 88 86 
23.9 20		61 09 E6 8C 86 
24.0 20		61 02 E6 8A 86 
24.1 20		61 0D E6 86 86 
24.2 20		61 01 E6 81 86 
24.3 20		61 04 E6 85 86 
24.3 20		61 0E E6 8D 86 
24.4 20		61 0F E6 83 86 
24.5 20		61 05 E6 8B 86 
24.6 20		61 00 E6 8F 86 
24.6 20		61 03 16 80 86 
24.6 20		61 03 16 80 86 
24.7 20		61 09 16 88 86 
...Il doit y avoir une erreur quelque part.


mercredi 15 avril 2026

Table ecliptique

L'original est en .SVG, il peut être découpé et gravé avec une découpeuse laser.. Le fichier a été produit par un programme en JavaScript dans un fichier HTML (mais Blogger ne semble pas aimer les .svg...).

Le but est de faire tourner le disque incliné de 23.5° (inclinaison de l'écliptique) sur un axe incliné de 50° (la latitude de Liège). Pour cela on réalise deux pièces à imprimer en 3D (prévoir des 'supports' pour les dévers) : une première à coller sur le disque (côté tronqué). On peut facilement générer l'objet 3D avec openSCAD :
d_goulot=21;
h_eclipt=25;
d_axe=11;

difference()
  {
  difference()
    {
    cylinder(d=d_goulot, h=h_eclipt);
    cylinder(d=d_axe, h=h_eclipt);
    }
  rotate([23.5,0,0])
    translate([0,0,45])
    cube(60,center=true);
  }
Et le second, à poser sur le goulot (standard) d'une bouteille de boisson gazeuse.
d_goulot=21.5;
h_goulot=15;
d_axe=10.5;
union()
{
  difference()
    {
    union()
      {
      cylinder(d=d_goulot, h=h_goulot);
      translate([0,0,h_goulot])
        cylinder(d=d_goulot+2, h=2*h_goulot);
      }
    rotate([40,0,0])
      translate([0,0,60])
      cube(80,center=true);
    }
    translate([0,0,24])
      rotate([40,0,0])
        cylinder(d=d_axe,h=13);

  }
Quand on enfiche la première pièce dans la seconde, on peut faire tourner le disque incliné de 23.5° sur l'axe incliné à 50° et visualiser la position du Soleil dans le ciel tout au long de l'année. C'est une version simplifiée de sphère armillaire.

vendredi 3 avril 2026

LoRa

Signal LoRa d'un court message (Hello#) avec un SF de 12 et une bande passante de 7.8 kHz donnant le débit binaire le plus lent afin de visualiser le signal avec 'RF Analyzer' sur un smartphone connecté à une clé RL-SDR. On voit bien la répétition (8, par défaut dans LoRaSender.ino) dans le préambule et les deux chirps de sens contraire qui suivent, avant le message proprement dit.

L'équation de base pour LoRa est :

La durée d'un symbole Ts est égale à 2 exposant le facteur d'étalement SF divisé par la bande passante B. Avec SF, le 'Spreading Factor', le nombre de bits contenus dans le symbole.

De là, on peut déduire le débit binaire, SF/Ts et, en tenant compte du préambule et du code correcteur d'erreur, le temps d'émission d'un message et donc la consommation électrique.

Avec une bande passante de 250 kHz, toujours avec un SF de 12, quand on observe la répétition de ce message avec un 'Power Profiler Kit II', on a l'écran suivant.


On observe que cela consomme pas mal, 30 mA, quand on laisse la puissance par défaut du sketch Arduino LoRaSender.ino. Beaucoup trop que pour l'alimenter par le 3.3 volts de l'arduino nano. Quand on augmente le facteur d'étalement SF, ou que l'on diminue la bande passante B, on doit fournir ces 30 mA plus longtemps.

samedi 14 mars 2026

GNU Radio

L'application RF Analyzer sur Androïd permet d'enregistrer des fichiers IQ captés avec un dongle RTL-SDR (entre autres). Les 60 premières minutes sont gratuites, ensuite, on peut acquérir la license pleine pour environ 8 euros. Il suffit de relier la clé USB au smartphone avec un adaptateur OTG USB-A//USB-C. Il est alors facile d'aller capter les signaux où c'est possible. Par exemple, ci-dessus, le VOR-DME de Sprimont, dont on distingue le callsign 'SPI' (... .--. ..) sur 113.1 MHz, capté au sommet du terril Sainte-Barbe et Tonne à Liège.

C'est amusant mais le but est d'avoir de la matière pour jouer avec GNU Radio. GNU Radio permet de faire un tas de choses mais la prise en main n'est pas spécialement facile. Certaines choses sont particulièrement difficiles à faire et le tout est très mal documenté. À ma connaissance, il n'existe qu'un seul livre sur la question, 'Communication Systems Engineering with GNU Radio: A Hands-on Approach' où les auteurs n'ont pas pu s'empêcher de traiter de sujets plus complexes les uns que les autres avec GNU Radio après une introduction trop brève du B-A-BA de quelques modules.

Par exemple, ce qui, à ma connaissance, n'a pas de solution simple, c'est de lire un fichier IQ de RTL-SDR, composé de bytes pour générer un flux de complexes float, généralememnt utilisés par les modules GNU Radio. Alors qu'il est trivial d'utiliser une source RTL-SDR 'live' avec le module osmocom, lire un fichier capturé par rtl_sdr(1) est incroyablement complexe (ou je n'ai pas trouvé...). Ensuite, si je veux extraire un signal hors de ma capture sur une bande de 2.5 MHz, je peux utiliser le module 'Frequency Xlating FIR Filter' ...dont la documentation est incompéhensible. Heureusement, il existe un exemple (peu commenté) dans le bouquin, page 72, 'POCSAG Multichannel Decoding' où l'on comprend que le champ 'taps' du module est simplememnt un filtre passe bas. Et donc, avec le workflow grc
On obtient le résultat suivant :


Le fichier source contient 5 secondes d'enregistrement à 2500000 échantillons par secondes. On le lit en boucle (repeat=yes). Cela produit le 'waterflow' du milieu avec une bande passante de 2.5 MHz, [111.85..114.35] MHz (113.1 - (2.5/2) .. 113.1 + (2.5/2)). Dont on extrait le VOR de Sprimont à 113.1 MHz (center frequency=0) et celui de Olne à 112.8 MHz (center frequency=-300) avec une bande passante de 2 * 25 Khz. On en profite pour réduire la cadence d'échantillonnage d'un facteur 20 (decim=20), ce qui fait que le 'waterfall' n'a plus que 125 KHz [-65..+65] de bande passante. Si les deux signaux sinusoïdaux donnant la direction sont à 30 Hertz comme indiqué dans Wikipédia, on doit y avoir un phénomène d'aliasing... (?). C'est un peu bizarre d'avoir quelque chose qui fasse 30 tours par seconde... Sur les waterfalls, on devrait pouvoir deviner les callsigns en morse des deux balises : 'SPI'(... .---. ..) et 'LNO' (.-.. -. ---) mais l'enregistrement est trop court et la répétition n'aide pas.

Dans le cas d'un enregistrement avec un HackRF/Portapack.Mayhem, on part de shorts signés, la lecture est plus simple.