mardi 27 août 2019

XSLT - Garmin GPX - gnuplot

Un Garmin donne la trace GPS suivante : AiguillesRouges.gpx
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="MapSource 6.16.3" version="1.1"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
  
  <metadata>
    <link href="http://www.garmin.com">   
      <text>Garmin International</text>
    </link>
    <time>2019-07-28T08:08:05Z</time>
    <bounds maxlat="46.024869801476598" maxlon="6.926982309669256" minlat="45.935957757756114" minlon="6.771008670330048"/>
  </metadata>
  
  <trk>
    <name>Tracé actuel: 23 JUIL 2019 07:39</name>
    <extensions>
      <gpxx:TrackExtension xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
        <gpxx:DisplayColor>Black</gpxx:DisplayColor>
      </gpxx:TrackExtension>
    </extensions>
    <trkseg>
      <trkpt lat="45.936855375766754" lon="6.771008670330048">
        <ele>872.52999999999997</ele>
        <time>2019-07-23T05:39:31Z</time>
      </trkpt>
      <trkpt lat="45.936975907534361" lon="6.77103029564023">
        <ele>873.98000000000002</ele>
        <time>2019-07-23T05:39:42Z</time>
      </trkpt>
      ...etc...
gpx.xsl, un petit bout de code XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:gpx="http://www.topografix.com/GPX/1/1">
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:for-each select="gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt">
        <xsl:value-of select="@lon"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="@lat"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="gpx:ele"/>
        <xsl:text>
</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Et sur Linux,
$ xsltproc gpx.xsl AiguillesRouges.gpx > AigRou.xyz
donne les coordonnées X, Y et Z en 3 colonnes :
6.771008670330048 45.936855375766754 872.52999999999997
6.77103029564023 45.936975907534361 873.98000000000002
6.771165663376451 45.937128961086273 876.38
6.771242022514343 45.937253851443529 877.34000000000003
6.771263061091304 45.93731545843184 877.34000000000003
6.771297678351402 45.937489299103618 879.25999999999999
etc...
Qu'il suffit de traiter avec le script gnuplot suivant :
gnuplot << END
set term png size 1200,900
set grid xtics ytics ztics
set output 'AigRouXYZ.png'
splot "AigRou.xyz" with lines
set output 'AigRouXY.png'
plot "AigRou.xyz" using 1:2 with lines
set output 'AigRouZ.png'
plot "AigRou.xyz" using 3 with lines
END
pour obtenir les graphes suivants :

samedi 27 avril 2019

ADS-B avec cantenna

Ayant trouvé un bidon d'huile d'olive de 10 litres, j'envisage d'en faire une 'cantenna' pour l'ADS-B... À l'image des 'antennes Ricoré' pour le WiFi.
Le bidon fait environ 15x24 cm² avec 30 cm de profondeur. L'ADS-B, à 1090 MHz, a une longueur d'onde d'environ 27.5 cm. Le bidon n'est pas très loin d'avoir une hauteur de lambda/2 et en mettant un bout de fil de cuivre de lambda/4 (~7cm) à lambda/4 du fond, ça devrait être bon. Aussitôt dit, aussitôt fait.
Je pars faire des tests dans un endroit relativement élevé, un terril au dessus de Liège. Et j'en registre les avions avec dump1090 sur un OrangePiZero alimenté par un powerbank. Trois fois pendant une demi-heure dans des directions différentes en comparant avec une antenne 'PCB' trouvée sur eBay pendant une autre demi-heure.
Le résultat est assez bon. La cantenna capte les avions beaucoup plus loin que l'antenne PCB (mais dans une direction privilégiée). J'ignore si c'est l'amplification du signal par l'antenne ou si c'est parce que la réception est moins dérangée par d'autres émissions proches venant d'autres directions. Il faudrait mesurer le nombre de messages par seconde pour voir s'il y a beaucoup de collisions. On se rapproche de l'horizon radar théorique (D_miles = 2.2 * sqrt(altitude_m)).
De Liège, je capte des avions au delà de Paris et presque jusque Londres.

dimanche 17 février 2019

AIS again

Petite analyse d'une captation d'une minute avec un Orange Pi Zero et une clé RTL-SDR V3 autour de 162 MHz de 16000000 échantillons à 262144 échantillons par seconde (environ une minute donne un fichier de 32 MB).
/usr/bin/rtl_sdr -f 162000000 -s 262144 -n 16000000 core.iq
Je prends juste le quart du fichier pour accélérer le traitement dans GNU Octave (dd). Pour lire les données IQ 8 bits fournies par rtl_sdr, j'utilise une fonction dans 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);
Avec plotspec.m,
% plotspec(x,Ts) plots the spectrum of the signal x
% Ts = time (in seconds) between adjacent samples in x
function plotspec(x,Ts)
N=length(x);                               % length of the signal x
t=Ts*(1:N);                                % define a time vector
ssf=(ceil(-N/2):ceil(N/2)-1)/(Ts*N);       % frequency vector
fx=fft(x(1:N));                            % do DFT/FFT
fxs=fftshift(fx);                          % shift it for plotting
subplot(2,1,1), plot(t,x)                  % plot the waveform
xlabel('seconds'); ylabel('amplitude')     % label the axes
subplot(2,1,2), plot(ssf,abs(fxs))         % plot magnitude spectrum
xlabel('frequency'); ylabel('magnitude')   % label the axes
je peux observer que j'ai bien enregistré des messages et qu'ils se situent bien à -25 KHz et + 25 KHz autour de 162 MHz.
Je vais maintenant tacher d'isoler un message à +25 KHz (up.iq8) et un autre à -25 KHz (down.iq8). Pour ce faire, je vais visualiser la magnitude du signal.
Zoomons...
Zoomons encore...
On peut maintenant extraire juste les messages du fichier core.iq8. Sachant qu'il y a deux bytes par échantillon et que le graphe nous donne les offsets absolus.
$ # 134000..141000  & 274000..281000
$ dd if=core.iq8 of=up.iq8 bs=2000 skip=134 count=7
$ dd if=core.iq8 of=down.iq8 bs=2000 skip=274 count=7
En cherchant un peu, on trouve un message à +25 Khz dont on s'intéresse à l'évolution de la phase :
En regardant la phase et en zommant :
Et la même chose pour un message à -25 KHz :
qui donne une évolution de la phase descendante :
On voit que, dans les deux cas, on a des sauts quand la phase passe au dessus de 360° ou en dessous de 0°. On va rendre tout cela continu pour, ensuite, soustraire/ajouter le changement de phase dû au +/- 25 KHz.
%  y = contzup(phi)
%
% rend la phase continue
%
function y = contzup(phi)
N=length(phi);                               % length of the signal x
phi=phi+(pi/2);
y=phi;
t=0;
for i = 1:N-1
        if ( phi(i) > phi(i+1) )
                        t = t + 2*pi;
        endif
        y(i+1) = (phi(i+1) + t)-(((2*pi)*25000*i)/262144);
%       y(i+1) = (phi(i+1) + t);
endfor


Détail, le début avec le préambule et les premiers octets.


avec le grid à 9600 samples/sec :



Comme je ne parviens pas vraiment à écrire un programme me permettant d'obtenir les trames NMEA à partir des IQ sortant de la clé RTL-SDR en bouquinant sur la théorie. J'envisage de partir d'un programme qui fonctionne et de l'analyser... Par exemple, rtl_ais donne d'assez bons résultats. D'un terril au dessus de Liège avec une antenne dipôle, je capte des bateaux sur la Meuse jusque Tihange (Huy) dans un sens et au delà de Maastricht dans l'autre. Et même quelques message provenant du côté de Genk, sur le canal Albert. Le code n'est pas très long et est assez lisible mais, c'est vraiment de la sorcellerie. Il va falloir du temps pour s'en imprégner et comprendre son fonctionnement.

À suivre...

samedi 23 juin 2018

GPSDO

Deux petits GPSDO trouvés sur eBay (~120.00 euros à gauche et ~80.00 euros à droite). Les antennes sont sur la terrasse derrière. Vont-ils se synchroniser?

Oui. Au départ, les deux fréquences sont différentes :
Après cinq, dix minutes, il y a moins d'un Hertz entre les deux signaux. L'un glisse encore lentement par rapport à l'autre.
Après une demi-heure, le glissement devient très (très) lent. Il faut plusieurs minutes pour que cela glisse d'une période et cela continue à ralentir.

Je semble donc bien avoir du 10 MHz à mieux qu'un centième de Hertz près (10E-09, 1 ppb).

dimanche 6 mai 2018

MiniVNA Tiny

Un joli 'gadget'...
Un petit 'vector analyzer' USB et une vieille antenne Uda-Yagy pour le WiFi 2.4 GHz faite avec un peu de fils de laiton et un bâtonnet de crème glacée.
Par chance, ce n'est pas trop loin du but.
Sur Ubuntu 18.04, le .jar n'a pas fonctionné de suite; je n'ai pas trouvé ce qui manquait exactement et j'ai fini par installer le JRE d'Oracle.
$ sudo add-apt-repository -y ppa:webupd8team/java && sudo apt-get update && sudo apt-get install -y oracle-java8-installer

samedi 18 novembre 2017

DCF77

Un petit module DCF77, trouvé sur eBay, fait par des Canadiens (Universal Solder)... : page du constructeur.
Il y a longtemps que ce bidule me faisait envie mais, habitué aux trucs chinois à un euro, je le trouvait cher, 12 euros avec le port (alors qu'on peut trouver des modules GPS chinois à moins de 4 euros port compris). Mais là, j'ai craqué... Et je ne le regrette pas. C'est arrivé bien emballé dans une éprouvette, c'est bien documenté sur leur site (le chip est une radio spécialisée MAF6180C).

Le montage le plus simple, c'est de l'alimenter par deux piles de 1.5 volts, de relier la pin qui contrôle la mise sous tension à la masse et de mettre une led avec résistance entre le signal et la masse. La LED s'allume au départ et si le signal est bien reçu (et je ne suis qu'à 250 km de l'émetteur de Mainflingen qui émet avec une puissance de 30 kW sur des antennes tirées entre des pylônes de 200 mètres de haut).

Ce qui est amusant, c'est la synchronisation entre le tic-tac de ma pendule murale radio-pilotée (aussi DCF77) et la LED qui émet un flash de 100 ou 200 millisecondes toute les secondes (sauf la 59-ième). C'est magique. Il faudrait regarder le signal de plus près, voir si, dans les conditions de réception locales, on peut être beaucoup plus précis que la seconde et que je compare ce signal avec le signal d'un module GPS. Peut-être qu'on peut voir que le DCF77, ici, a près d'une milliseconde de retard sur le temps local vrai (250 km ~ 300 km à la vitesse de la lumière). À supposer que le top horloge du module GPS soit correct.

Ce qui m'intéresserait aussi, c'est de capter/visualiser le signal à 77.5 kilohertz, d'en étudier la phase, etc... J-M Friedt expliquait lors d'une présentation au FOSDEM.2017/SDR qu'ils avaient étudié les variations d'altitude de l'ionosphère avec une carte son de PC en écoutant le DCF77 à Besançon... Bref, il y a moyen de s'amuser.

dimanche 22 octobre 2017

Reference de tension

Un petit 'break-out' sur eBay à moins de trois euros avec un AD584 (signalé par Cyrob). Le composant est un peu oxydé mais on peut lire AD584JH. Sur le site d'Analog Device, neuf, il vaut 10 USD. En principe, il donne des tensions de référence de 10, 7.5, 5 et 2.5 à 3/1000 (avec 30 ppm/° Celsius et 30 ppm pour 1000 heures de fonctionnement avec un Vin de 15 volts. Le bidule est livré avec une espèce de certificat avec des mesures encore plus précises faites avec un Agilent AG24401 ...Et, je n'ai bien sûr aucun moyen de le vérifier.

Premier test. En fait, cela ne fonctionne pas. La LED témoin ne s'allume pas et je n'ai aucune tension en sortie en mettant de 15 volts en entrée... Me serais-je fait arnaquer? Bizarre que la LED ne s'allume pas. Le circuit est trivial : Vin->diode de protection (alim de l'AD584)-> LED -> résistance -> 'terre'. Ni la diode, ni la led ne semblent être à l'envers; mon ANENG AN8002 me dit qu'elle sont correcte. Tiens, c'est une résistance de 220 k! Ça, ce n'est pas normal, c'est beaucoup trop. Il n'y a pas assez de courant pour allumer la LED et même probablement pas assez pour rendre les diodes conductrices. Je remplace la résistance par une 2.2 k et cela va tout de suite beaucoup mieux : la LED s'allume et j'ai les tensions de référence en sortie.

Maintenant, puis-je faire confiance au certificat? Mystère... C'est possible qu'ils aient testé le composant avant de le souder sur la plaquette. Mais s'ils étaient vraiment sérieux, ils se seraient peut-être rendu compte qu'il y avait un problème. Maintenant, pour 2.50 euros, puisque cela fonctionne, je ne vais pas me plaindre. J'irai la mesurer sur un Rigol DM3058E un de ces jours.