tag:blogger.com,1999:blog-48116257695907985862024-03-05T11:18:53.330+01:00Chipotonsxofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.comBlogger47125tag:blogger.com,1999:blog-4811625769590798586.post-42145378992125475992023-09-10T16:29:00.073+02:002023-10-01T16:17:31.669+02:00Teledistribution<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHs7eXxjUKsN4nTDOqRFE0azO5-5l5xFUmRDZe36m21A9bSck9jjKByVr9SDS-OrcZqlhECDhIhho2G_BeKtR_ZhrZ6-fZSkwTw6NNmVlQv26Cz4AgHtn5IuUStfCIutxSN-gAGTg-lj1uXVtnUPjXnDQK_vK9eofAdfCOo9yqPVMg3qhBPkl2-V8Ol7E/s1296/_DSC02607.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="972" data-original-width="1296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHs7eXxjUKsN4nTDOqRFE0azO5-5l5xFUmRDZe36m21A9bSck9jjKByVr9SDS-OrcZqlhECDhIhho2G_BeKtR_ZhrZ6-fZSkwTw6NNmVlQv26Cz4AgHtn5IuUStfCIutxSN-gAGTg-lj1uXVtnUPjXnDQK_vK9eofAdfCOo9yqPVMg3qhBPkl2-V8Ol7E/s320/_DSC02607.JPG"/></a></div>
Ayant connu quelques problèmes de réception de chaînes TV sur le câble, je me suis un peu intéressé à ce qui s'y passait... <br/>
La première idée a été de regarder le spectre avec un analyseur de spectre <a href="https://www.tinysa.org/wiki/">TinySA</a>, un étonnant bidule à quelques dizaines d'euros qui affiche des spectres de 0 à quasi 1 GHz. Par défaut, il affiche le spectre de 0 à 350 MHz. On voit quelque chose du côté de 100 MHz, probablement la FM puis les signaux numériques commencent un peu avant 300 MHz. Si l'on zoome du côté de 330 MHz (la fréquence recommandée pour un scan rapide lors de l'installation d'un nouveau téléviseur), on voit bien les bandes de signaux de 8 MHz propres au <a href="https://fr.wikipedia.org/wiki/DVB-C">DVB-C</a>.
<br/><br/>
Le TinySA permet également d'obtenir les mesures via l'USB. Sur Linux, avec Minicom,
<pre>
$ minicom -D /dev/ttyACM0
scan 333M 343M 290 3
</pre>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0BtCbOhKS69DxrbGM3ySCJ6PxtTo91a7FGE2WDd8_3cPbTfObOeDoG6x5sEIRCOcu6meP9bBcj_gFpsDK0aNhgPOtgp2W5n2-ClfPMyPvXRKU4oj5-do3nnIIBJkfNFftbK9vFbQgmLY7KP2O6_aTx2-UMhHS3JnV_1QpL-DilrNy6u3FV2ptcsJDB2I/s640/333-343.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="480" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0BtCbOhKS69DxrbGM3ySCJ6PxtTo91a7FGE2WDd8_3cPbTfObOeDoG6x5sEIRCOcu6meP9bBcj_gFpsDK0aNhgPOtgp2W5n2-ClfPMyPvXRKU4oj5-do3nnIIBJkfNFftbK9vFbQgmLY7KP2O6_aTx2-UMhHS3JnV_1QpL-DilrNy6u3FV2ptcsJDB2I/s320/333-343.png"/></a></div>
<br/><br/>
Tout cela c'est très bien. En regardant vers les fréquences plus hautes, on pouvait constater une baisse de la puissance du signal dûe à la qualité du câble coaxial à l'intérieur du bâtiment. Mais cela n'expliquait pas pourquoi le signal était bon à certains moments et insuffisant à d'autres moments. Une fonction de la <a href="https://www.samsung.com/be_fr/support/model/LT24D390EW/XU/">T24D390EW/EN</a> permet d'afficher les caractéristiques d'un signal (fréquence, qualité du signal,...).
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_ky8QcAd__4kkReqJ6nmT5ojK6M093Wh7gY2NXxNG1OMXwl3Vdeev4QT41xWeJbMOScSAydPQH2pQE2Xd78Sigusugy1eU4Jb84NqiSyJMHGYycr9ex3zSRuair3rUKr27SL7ve8743UeixhBUXvnKON8dIKbgcQ2DzMAkVZ9hooYYtDqD-NJvEYuyqg/s1296/_DSC02507.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="972" data-original-width="1296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_ky8QcAd__4kkReqJ6nmT5ojK6M093Wh7gY2NXxNG1OMXwl3Vdeev4QT41xWeJbMOScSAydPQH2pQE2Xd78Sigusugy1eU4Jb84NqiSyJMHGYycr9ex3zSRuair3rUKr27SL7ve8743UeixhBUXvnKON8dIKbgcQ2DzMAkVZ9hooYYtDqD-NJvEYuyqg/s320/_DSC02507.JPG"/></a></div>
Un technicien est venu remplacer quelques connecteurs et a fini par me laisser un amplificateur. Cela a peut-être un peu boosté le signal et je n'ai plus eu d'images avec des blocs mais la veille de sa venue, je n'ai subitement plus eu de programme du tout, sauf sur <a href="https://www.rtbf.be/la-trois">La Trois</a>, ...seule chaîne non cryptée dans le bouquet standard. Et cela, c'était un autre problème, sûrement un problème de <a href="https://en.wikipedia.org/wiki/Conditional-access_module">module CAM</a> ou de <a href="https://en.wikipedia.org/wiki/Common_Interface">carte CI</a>... et le technicien m'a invité à aller dans une boutique du téléopérateur. Là, on me donne une 'nouvelle carte' (usagée) et on m'invite à téléphoner au support technique pour l'activer. Là, chipotage, seconde ligne, blabla... Je dois contacter le service technique de Samsung, faire une mise à jour du firmware de la TV,... Je fais la mise à jour avec un mystérieux T-NT14LDEUCM_1013.0.exe trouvé sur le site de Samsung. En fait un .rar autoextractible sur lequel je peux faire un <a href="https://manpages.ubuntu.com/manpages/jammy/man1/unrar-nonfree.1.html">unrar(1)</a> et je passe donc ma TV de la version 1005 à la version 1013 (tout en constantant qu'il y a du Linux à l'intérieur...). Mais rien n'y fait. Comme l'opérateur s'entête à m'encourager à contacter Samsung, je finis par le faire et la personne suspecte qu'ils sont passé de CI+ 1.3 à CI+ 1.4 que ma TV ne peux malheureusement pas traiter... Hum... L'opérateur finit par me re-contacter pour savoir comment s'est passé <i>le changement de signal</i>... C'est la première fois qu'ils me parlent d'un 'changement de signal'. J'avais donc raison de ne pas croire au hasard, ils ont bien changé quelque chose. Curieusement, la solution ne semble pas consister à me remettre en CI+ 1.3 (ou je ne sais quoi d'autre) mais à changer ma formule d'abonnement, d'acquérir un décodeur et de prendre Internet et le téléphone chez eux... Il y en a qui ne manquent pas d'air.
<br/><br/>
Là-dessus, je me suis demandé comment fonctionnait exactement cette histoire de bouquets cryptés sur DVB-C et j'ai acquis un bidule USB, <a href="http://www.hauppauge.fr/site/products/data_solohd.html">Hauppauge SoloHD</a> qui permet de capter les chaînes non cryptées et est bien supporté sous Linux (j'ai d'abord tenté un dongle bon marché DVBT2 qui promettait le DVB-C mais la démodulation <a href="https://en.wikipedia.org/wiki/64-QAM">64-QAM</a> semble se faire sur le PC à partir des signaux IQ bruts et ce n'est pas supporté par Linux). Hauppauge fournit de la <a href="https://www.hauppauge.com/pages/support/support_linux.html#pi">documentation pour installer sous Linux</a> (notamment pour Raspberry Pi). En gros, c'est supporté par défaut, il faut juste télécharger et installer le firmware (deux fichiers à copier dans /lib/firmware/).
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwSI1o0u-9t2M8LBdRms8QDADx0LqGQYSF3gQ6Aoj4vTktX0jqkQ_GdGzCIDP6tLiYXer18mqxGnSr_IoKa_8sw8J3JzQFQ4kWbJdfiFUTjLVMOqyc0o372vs6k_IpbsV9g6934F-sL_gVl9UiylAngWr1cOEf4ANBf3SDjStu54qX2-Svfm4ItoDQKkM/s1200/dvb-c_tools.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1082" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwSI1o0u-9t2M8LBdRms8QDADx0LqGQYSF3gQ6Aoj4vTktX0jqkQ_GdGzCIDP6tLiYXer18mqxGnSr_IoKa_8sw8J3JzQFQ4kWbJdfiFUTjLVMOqyc0o372vs6k_IpbsV9g6934F-sL_gVl9UiylAngWr1cOEf4ANBf3SDjStu54qX2-Svfm4ItoDQKkM/s320/dvb-c_tools.jpg"/></a></div>
<br/><br/>
Ensuite, il reste à trouver les utilitaires qui vont bien. Par exemple, <a href="https://manpages.debian.org/testing/w-scan/w_scan.1.en.html">w_scan(1)</a> (...qui se trouve dans le package w-scan)
<pre>
$ sudo apt-get install w-scan
...
$ w_scan -fc # pour scanner toutes les fréquences DVB-C
</pre>
<br/><br/>
Ce qui est étonnant, c'est le nombre de chaînes que l'on parvient à passer en haute définition dans un seul <a href="https://fr.wikipedia.org/wiki/MPEG_Transport_Stream">MPEG-TS</a> en 64QAM de 8 MHz. Il semble y avoir 18 chaînes en clair sur le canal de 8 MHz à 314 MHz! (6875 kilo-symboles par seconde avec les 6 bits par symbole du 64QAM, cela fait environ 41 Mbits/seconde).
<br/><br/>
J'aimerais bien comprendre la structure de tout cela. À 330 MHz, il y a des informations qui renseignent les chaînes disponibles sur différentes fréquences, par exemple.
Et j'aimerais bien extraire le guide électronique des programmes (<a href="https://fr.wikipedia.org/wiki/Guide_%C3%A9lectronique_des_programmes">EPG</a>)...
<br/><br/>
à suivre...
<br/><br/>
En tout cas, rien de tel qu'une panne de télédistribution pour se rendre compte à quel point la télévision est une drogue dure et prendre la mesure du temps que l'on perd à regarder des programmes sans aucun intérêt.
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-88179102494547681022023-05-06T16:37:00.005+02:002023-05-06T16:37:56.123+02:00Triomphe de la Lune<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpF-yge9Z3RrFasnW2fEDOHhMEKaEDWUhUjTiTCNVxJe83PlNNBKWpTw3HLH589_3-0BfSd9srtgeXfrLy9vsNQY57Ry1SE0Ppeecdy7iAb5BdKN-YxGWKt0_4RGV3ZkWwml0fQuCWTzILkR6iy1wA2yR5nB2pgbXNKvkaSnKBbxOlSyq-LvaNx9RI/s1844/ArcMoon.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="1844" data-original-width="1800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpF-yge9Z3RrFasnW2fEDOHhMEKaEDWUhUjTiTCNVxJe83PlNNBKWpTw3HLH589_3-0BfSd9srtgeXfrLy9vsNQY57Ry1SE0Ppeecdy7iAb5BdKN-YxGWKt0_4RGV3ZkWwml0fQuCWTzILkR6iy1wA2yR5nB2pgbXNKvkaSnKBbxOlSyq-LvaNx9RI/s320/ArcMoon.jpg"/></a></div>
Le 26 avril 2023, la Nasa publiait une <a href="https://apod.nasa.gov/apod/ap230426.html">photo de la Lune</a> occupant presque toute la voûte de l'<a href="https://fr.wikipedia.org/wiki/Arc_de_triomphe_de_l%27%C3%89toile">Arc de Tromphe de l'Étoile</a> comme <i><a href="https://fr.wikipedia.org/wiki/Astronomy_Picture_of_the_Day">photo du jour</a></i>.
<br/><br/>
Une occasion d'utiliser <a href="https://en.wikipedia.org/wiki/PyEphem">PyEphem</a> pour vérifier tout ça...
<br/><br/>
C'est simple, amusant et vraisemblablement très précis.
On a un observateur positionné dans l'espace et le temps et un astre dont la position dans un repère géographique nous intéresse...
<br/><br/>
Pour le calcul de l'azimut entre la <a href="https://fr.wikipedia.org/wiki/Porte_Maillot">Porte Maillot</a> et l'Arc, <a href="https://fr.wikipedia.org/wiki/ChatGPT">ChatGPT</a> me proposait 'geopy' mais le code qu'il proposait n'était pas correct...
Google m'a proposé geographiclib...
<pre>
pip install pyephem
pip install geographiclib
</pre>
(avec ces modules, le code Python est compact et lisible)
Pour les coordonnées GPS des points d'intérêt, j'utilise <a href="https://wikimapia.org">wikimapia</a> qui a un curseur au centre et affiche sa position dans l'URL.
<br/><br/>
On positionne le programme en début de soirée (<a href="Temps%20universel%20coordonné">UTC</a>!), <a href="https://fr.wikipedia.org/wiki/Porte_Maillot">Porte Maillot</a> et on demande à pyephem quand a lieu le lever suivant. On y positionne l'observateur pour obtenir la position de la Lune sur l'horizon à ce moment-là.
<br/><br/>
Le programme ci-dessous donne les résultats suivants :
<pre>
(https://apod.nasa.gov/apod/ap230426.html - EXIF 'Fr, 07 April 2023 22:21:14')
----
Lever Lune : 2023/4/7 20:16:01 112.160414663
Maillot->Etoile : distance = 1065.04410143 ; azimut = 115.71367909
distance * sin(0.5 deg) = 9.29414515847 m
----
https://fr.wikipedia.org/wiki/Arc_de_Triomphe_de_Paris
http://wikimapia.org/#lang=en&lat=48.873776&lon=2.295027&z=16&m=o
</pre>
<br/>
Remarquez que la Porte Maillot, à un peu plus d'un kilomètre, c'est un peu juste. La Lune ne fait que 9.3 mètres à l'Arc alors que la voûte en fait 14.6.
<br/><br/>
Je ne suis ni photographe ni observateur. J'ignore si on peut obtenir quelque chose d'aussi net à cette distance-là. Ni si on peut voir la Lune aussi nette si près de l'horizon en ville. Mais, sinon, c'est tout-à-fait plausible. La Lune, levée depuis quelques minutes, a parcouru quelques degrés pour se trouver dans le bon azimut légèrement au dessus de l'horizon.
<br/><br/>
Après, on peut refaire l'exercice pour le Cinquantenaire à Bruxelles en faisant une boucle sur 365 jours et en alternant next_rising(moon) et next_setting(moon). Comme le comportement de la Lune est un peu erratique, il vaut peut-être mieux s'exercer avec le Soleil... (sun).
<br/><br/>
Dans le 'Hacker's Dictionary', vers 1980, pour désigner un programme dont les résultats étaient incertains, on trouvait :
<br/><br/>
> POM n. Phase of the moon (q.v.).<br/>
> Usage: usually used in the phrase "POM dependent"<br/>
> which means flakey (q.v.).<br/>
<br/>
( <a href="https://www.dourish.com/goodies/jargon.html">https://www.dourish.com/goodies/jargon.html</a> )
<pre>
#!/usr/bin/python
import math
import ephem
from geographiclib.geodesic import Geodesic
moon = ephem.Moon()
#
# Porte Maillot (48.877938, 2.281962)
# Arc de Triomphe (48.873782, 2.295043)
# altitude : 59m
# https://commons.wikimedia.org/wiki/File:Rep%C3%A8re_d%27altitude_sur_l%27Arc_de_Triomphe.jpg
#
x = Geodesic.WGS84.Inverse(48.877938, 2.281962, 48.873782, 2.295043)
azimut = x['azi1']
distance = x['s12']
Pt_Maillot = ephem.Observer()
Pt_Maillot.lat = '48.877938'
Pt_Maillot.lon = '2.281962'
Pt_Maillot.elevation = 55 # ?
Pt_Maillot.date = ephem.Date('2023/04/07 18:00')
Pt_Maillot.date = Pt_Maillot.next_rising(moon)
print "(https://apod.nasa.gov/apod/ap230426.html - EXIF 'Fr, 07 April 2023 22:21:14')"
print "----"
print "Lever Lune : ", Pt_Maillot.date, moon.az * 180 / math.pi
print "Maillot->Etoile : distance = ", distance, "; azimut = ", azimut
print "distance * sin(0.5 deg) = ", distance * math.sin(.5 * math.pi/180), "m"
print "----"
print "https://fr.wikipedia.org/wiki/Arc_de_Triomphe_de_Paris"
print "http://wikimapia.org/#lang=en&lat=48.873776&lon=2.2950&z=16&m=o"
</pre>
<br/>
Pour une doc rapide, voir :
<ul>
<li><a href="https://rhodesmill.org/pyephem/quick.html">https://rhodesmill.org/pyephem/quick.html</a> (PyEphem Quick Reference)
<li><a href="https://geographiclib.sourceforge.io/html/python/code.html">https://geographiclib.sourceforge.io/html/python/code.html</a>
</ul>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.comParis, France48.856614 2.352221920.546380163821155 -32.8040281 77.166847836178846 37.5084719tag:blogger.com,1999:blog-4811625769590798586.post-60486661212260626832023-01-08T17:01:00.013+01:002023-06-06T16:51:06.710+02:00Beid<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIfMaFlb9rJFrvljo9vOml-O21QK5WnY_Qwc6yVfqSLKz78GjXXJ0CH33cYDHTWnskS1tYFhgNEO0XkTAGir_T1OANLmmhwpiNOJGPEdSKdO46FtUxtsyEdyd6tYYc3daEVT_UjIv3E0FSGgvW3jxskSc9P7Ej0oSpUR6PM_wpSjc8brLiwyidH0RB/s1799/beid-20230108.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="1799" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIfMaFlb9rJFrvljo9vOml-O21QK5WnY_Qwc6yVfqSLKz78GjXXJ0CH33cYDHTWnskS1tYFhgNEO0XkTAGir_T1OANLmmhwpiNOJGPEdSKdO46FtUxtsyEdyd6tYYc3daEVT_UjIv3E0FSGgvW3jxskSc9P7Ej0oSpUR6PM_wpSjc8brLiwyidH0RB/s320/beid-20230108.jpg"/></a></div>
<br/><br/>
En 2007, j'avais fait quelques expériences de lecture de <a href="https://fr.wikipedia.org/wiki/Carte_d%27identit%C3%A9_belge">cartes d'identité belges</a> avec un lecteur de cartes utilisant un ACR38 : <a href="http://myacr38.blogspot.com/">myACR38.blogspot.com</a>... J'avais écrit un <a href="https://github.com/xofc/Beid2html">petit programme en 'C'</a> d'un peu plus de 300 lignes n'utilisant que la librairie usb pour extraire les données d'identité et la photo sous Linux. Aujourd'hui, je ne l'ai plus mais je peux utiliser le <a href="https://www.onespan.com/products/card-readers/digipass-870">Digipass 870</a> de <a href="https://www.vasco.com">Vasco</a> fourni par la banque Belfius pour effectuer des opérations bancaires. Les opérations bancaires <i>ne nécessitent pas</i> que le lecteur soit connecté à un ordinateur mais le lecteur est équipé d'un port USB qui permet cette connexion (contrairement au lecteur de carte <a href="https://www.onespan.com/products/card-readers/digipass-810">Digipass 810</a> fourni par <a href="https://www.bpostbanque.be/">Bpostbanque</a>).
<br/><br/>
Curieusement, il n'est pas possible de se connecter à une administration belge sans que le lecteur de carte ne soit connecté à un ordinateur équipé d'un logiciel qui ne fonctionne qu'avec certains logiciels particuliers sur une sélection particulières de systèmes d'exploitation (<a href="https://eid.belgium.be/en/linux-eid-software-installation">compatibilité Linux</a>)... Par exemple, il n'est pas possible d'utiliser un vieil Ubuntu, un Ubuntu <a href="https://eid.belgium.be/en/faq/why-it-not-possible-use-eid-software-snap-andor-flatpak#7636">trop récent</a> ou un Raspberry Pi. On vous invite alors à partir des sources, <a href="https://eid.belgium.be/sites/default/files/software/eid-mw-5.1.4-v5.1.4.tar.gz">eid-mw-5.1.4-v5.1.4.tar.gz</a> qui, bien sûr, nécessite un tas de dépendances qui en rendent la compilation fort hasardeuse.
<br/><br/>
Était-ce bien nécessaire? Je ne pense pas. Je ne suis pas un spécialiste en cryptographie mais c'est l'occasion de regarder d'un peu plus près ce qui se passe exactement avec cette carte d'identité électronique. On trouve assez bien d'informations. Par exemple, sur un <a href="https://wiki.yobi.be/index.php/Belgian_eID">wiki de Philippe Teuwen</a> qui réference une <a href="">présentation de Danny De Cock (pdf)</a> contenant des informations techniques. On trouve également des choses sur <a href="https://github.com/Fedict">github.com/Fedict</a>. Par exemple, le contenu de la carte : <a href="https://github.com/Fedict/eid-mw/blob/master/doc/sdk/documentation/Applet%201.8%20eID%20Cards/Belgian%20Electronic%20Identity%20Card%20content%20v5_4.pdf">Belgian Electronic Identity Card content v5_4.pdf</a>. On voit que la carte respecte la norme de cartes électroniques <a href="https://fr.wikipedia.org/wiki/ISO_7816">ISO-7816</a> et le standard de cryptographie <a href="https://fr.wikipedia.org/wiki/Public_Key_Cryptographic_Standards">PKCS#15</a>.
<br/><br>
Sur Linux, on peut utiliser le package opensc pour lire le contenu de la carte (<a href="https://github.com/OpenSC/OpenSC">sources sur github</a>). Il y a deux 'applications'. L'une reprenant des données d'identité sous 'DF01' et l'autre, 'BELPIC' ('DF00'), la partie cryptographique. Dans chacune, il y a plusieurs fichiers. Parfois respectant un format 'BER' (<a href="https://fr.wikipedia.org/wiki/Basic_Encoding_Rules">Basic Encoding Rules</a> d'<a href="https://fr.wikipedia.org/wiki/ASN.1">ASN.1</a>), parfois transparent comme, par exemple, pour la photo qui est un fichier <a href="https://fr.wikipedia.org/wiki/JPEG">JPEG</a> d'environ 4 kilo-octets (3?) d'une <a href="Définition%20d%27écran">définition</a> de 140x200 pixels avec 16 <a href="https://fr.wikipedia.org/wiki/Niveau_de_gris">niveaux de gris</a>.
<br/><br/>
<pre>
$ sudo apt-get install opensc
$ opensc-explorer <<END
cd df01
get 4031 4031-id_rn.bin
get 4032 4032-sgn_rn.bin
get 4033 4033-id_address.bin
get 4034 4034-sgn_rn.bin
get 4035 4035-id_photo.jpg
get 4038 4038-puk_7_ca.bin
get 4039 4039-pref.bin
cd ..
cd df00
get 5031 5031-odf.bin
get 5032 5032-token_info.bin
get 5034 5034-aodf.bin
get 5035 5035-pr_kdf.bin
get 5037 5037-cdf.bin
get 5038 5038-cert_2_auth.der
get 5039 5039-cert_3_sign.der
get 503a 503a-cert_4_ca.der
get 503b 503b-cert_6_root.der
get 503c 503c-cert_8_rn.der
END
</pre>
<br/><br/>
Les certificats, en format DER, peuvent être affichés ou transformés en base64 avec <a href="https://fr.wikipedia.org/wiki/OpenSSL">openssl(1)</a> :
<pre>
$ # display beid certificate
$ openssl x509 -in 5038-cert_2_auth.der -inform DER -text
$ # convert
$ openssl x509 -inform der -in cert.der -outform pem -out cert.pem
</pre>
<br/><br/>
<!-- Voir aussi <a href="http://repository.eid.belgium.be/certificates.php?cert=Root&lang=fr">Root CA : Certificats & listes de révocation</a> -->
Avec opensc-explorer, on peut aussi effectuer l'opération MVP:VERIFY. C'est le clavier du lecteur de carte qui est utilisé:
<pre>
$ opensc-explorer
OpenSC [3F00]> verify CHV1
Please enter PIN on the reader's pin pad.
Code correct.
</pre>
Bizarrement, le code source de opensc-explorer:do_verify est complexe. Cela passe par sc_pin_cmd() et part10_build_verify_pin_block() pour utiliser l'API du lecteur de carte (...qui doit correspondre à un standard documenté quelque part) qui ne semble pas être piqué des vers. Et même pour un lecteur de carte sans clavier, ce n'est pas évident. <a href="https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/sec.c">OpenSC/src/libopensc/sec.c</a> nous apprend, à la ligne 269, fonction sc_build_pin(), que les 8 octets de data de l'apdu sont 24:nn:nn:ff:ff:ff:ff:ff:ff (!) pour un PIN de 4 chiffres. Par exemple, pour '1234', on aura 'apdu 00:20:00:01:08:24:12:34:ff:ff:ff:ff:ff'.
<br/><br/>
Avec un lecteur muni d'un clavier, je ne peux pas utiliser l'apdu MVP:VERIFY dans opensc-explorer apdu (ni en 'C' avec libpcsclite), le code de retour est 6985 et non 9000. Je peux néanmoins utiliser 'apdu' pour tester d'autres commandes après avoir utilisé la commande 'verify' de opensc-explorer.
<pre>
OpenSC [3F00]> apdu 00:20:00:01:00 # MVP:VERIFY with 'lc' = 0
Sending: 00 20 00 01 00
Received (SW1=0x69, SW2=0x85)
Failure: Not allowed
OpenSC [3F00]> apdu 80:E6:00:00 # LOG OFF
Sending: 80 E6 00 00
Received (SW1=0x90, SW2=0x00)
Success!
OpenSC [3F00]> apdu 80:E4:00:00:1C # GET CARD DATA
Sending: 80 E4 00 00 1C
Received (SW1=0x90, SW2=0x00):
53 4C 47 90 61 28 00 00 2E CD 12 BF 12 92 61 54 SLG.a(........aT
F3 36 01 25 01 17 00 03 00 21 01 0F .6.%.....!..
Success!
</pre>
Le fin du GET CARD DATA donne 17 (Applet Version 1.7), 0003 (Belpic V-1.7), 00 (interface version), 21 (PKCS#1 version 2.1), 0F (Personalized state). SW1=0x90 et SW2=0x00 signifient que la commande s'est terminée normalement... (On se demande bien ce que les gars qui développent ce genre de standard ont dans la tête...)
<br/><br/>
Préparons un petit copion pour effectuer des opérations avec opensc-explorer... D'abord, sélectionner la paire de clé et l'algorithme de signature. Il n'y a pas 36 possibilités : on peut exécuter 6 algorithme avec deux clés privées (la clé d'authentification et la clé de non-répudiation (signature)). Ensuite, appliquer l'algorithme sur un 'hash' dont la longueur dépend de l'algorithme (16, 20, 32 octets pour MD5, SHA1, SHA256). Ces 'hashes' peuvent être obtenus au moyen des commandes Linux md5sum(1), sha1sum(1) et sha256sum(1).
<pre>
# MSE:SET Manage Security Environment : Set
# le dernier :82 ou :83 sélectionne la clé (Auth ou Sign)
# l'avant-pénultième octet sélectionne l'algorithme (en fait, la longueur des données à signer)
apdu 00:22:41:B6:05:04:80:01:84:82 # MSE:SET Auth - RSASSA-PKCS1
apdu 00:22:41:B6:05:04:80:02:84:82 # MSE:SET Auth - RSASSA-PKCS1-v1.5 SHA1
apdu 00:22:41:B6:05:04:80:04:84:82 # MSE:SET Auth - RSASSA-PKCS1-v1.5 MD5
apdu 00:22:41:B6:05:04:80:08:84:82 # MSE:SET Auth - RSASSA-PKCS1-v1.5 SHA256
apdu 00:22:41:B6:05:04:80:10:84:82 # MSE:SET Auth - RSASSA-PSS PKCS1-v2.1 SHA1
apdu 00:22:41:B6:05:04:80:20:84:82 # MSE:SET Auth - RSASSA-PSS PKCS1-v2.1 SHA256
apdu 00:22:41:B6:05:04:80:01:84:83 # MSE:SET Sign - RSASSA-PKCS1
apdu 00:22:41:B6:05:04:80:02:84:83 # MSE:SET Sign - RSASSA-PKCS1-v1.5 SHA1
apdu 00:22:41:B6:05:04:80:04:84:83 # MSE:SET Sign - RSASSA-PKCS1-v1.5 MD5
apdu 00:22:41:B6:05:04:80:08:84:83 # MSE:SET Sign - RSASSA-PKCS1-v1.5 SHA256
apdu 00:22:41:B6:05:04:80:10:84:83 # MSE:SET Sign - RSASSA-PSS PKCS1-v2.1 SHA1
apdu 00:22:41:B6:05:04:80:20:84:83 # MSE:SET Sign - RSASSA-PSS PKCS1-v2.1 SHA256
# PSO:CDS Perform Security Operation : Compute Digital Signature
apdu 00:2A:9E:9A:LL:<data>:00 # LL(MD5)=16; LL(SHA1)=20; LL(SHA256)=32
# test
apdu 00:22:41:B6:05:04:80:04:84:82 # MSE:SET Auth - RSASSA-PKCS1-v1.5 MD5
verify CHV1
apdu 00:2A:9E:9A:10:ed:9e:7e:69:f8:da:f8:8d:44:ef:78:30:41:42:1d:b6:00 # cal 2023 |md5sum|sed 's/../&:/g' -> ed:9e:7e...
# verify PIN=1234
apdu 00:20:00:01:08:24:12:34:ff:ff:ff:ff:ff
</pre>
Utilisons maintenant ce copion avec la carte insérée dans le lecteur : choix de l'algorithme, introduction du PIN, demande de calcul de la <a href="https://fr.wikipedia.org/wiki/Signature_num%C3%A9rique">signature</a> :
<pre>
$ opensc-explorer
OpenSC Explorer version 0.17.0
Using reader with a card: VASCO DIGIPASS 870 [CCID] 00 00
OpenSC [3F00]> apdu 00:22:41:B6:05:04:80:04:84:82
Sending: 00 22 41 B6 05 04 80 04 84 82
Received (SW1=0x90, SW2=0x00)
Success!
OpenSC [3F00]> verify CHV1
Please enter PIN on the reader's pin pad.
Code correct.
OpenSC [3F00]> apdu 00:2A:9E:9A:10:ed:9e:7e:69:f8:da:f8:8d:44:ef:78:30:41:42:1d:b6:00
Sending: 00 2A 9E 9A 10 ED 9E 7E 69 F8 DA F8 8D 44 EF 78 30 41 42 1D B6 00
Received (SW1=0x90, SW2=0x00):
18 CA 07 F8 78 3C 12 37 DB 15 CB D9 30 2F 0E A4 ....x<.7....0/..
BB 59 AA 7B 1E 42 DA A3 B2 91 7F CE 2D 3F 3F 41 .Y.{.B......-??A
7D 13 2F 24 D9 58 43 E0 E1 30 99 44 D6 AD 4D C5 }./$.XC..0.D..M.
08 B9 66 BA 31 75 29 8E 9B 75 7A 4A CA 36 0A BB ..f.1u)..uzJ.6..
E3 C9 12 31 78 12 7E F9 4D BA 34 27 82 8E 12 E3 ...1x.~.M.4'....
D8 BD 21 1A F6 3D 38 D2 F0 35 C0 C6 B6 7C AD B2 ..!..=8..5...|..
DE 6E 87 1A DB 78 E7 85 84 BF D1 9F 65 31 7E 68 .n...x......e1~h
1B F9 34 A1 7F 2E 9F A3 9E 9D B1 A2 F1 31 8E E3 ..4..........1..
45 D6 4E 71 7F E2 26 9A 7B F7 C4 2A 04 5E 7E EB E.Nq..&.{..*.^~.
E7 EA 50 76 C1 C0 AF C9 52 AC A2 9F AD 9F D4 5D ..Pv....R......]
C5 0D 52 20 77 BD 2B 5D 22 52 57 91 73 D0 8A 96 ..R w.+]"RW.s...
F1 38 A3 B7 6D 49 7B A0 91 91 A9 8C 20 43 83 69 .8..mI{..... C.i
18 B4 3B 8A AA 85 33 D4 50 09 6A 1F 3D 16 6B 33 ..;...3.P.j.=.k3
61 9A F0 A3 98 4F C7 FC 73 91 6C 66 08 1A B6 FF a....O..s.lf....
5C E2 F1 06 5B FE 32 F9 61 DF F9 1B 3E 85 53 7C \...[.2.a...>.S|
08 89 CF 65 58 75 BD C5 09 7A 6E 26 48 51 D7 36 ...eXu...zn&HQ.6
Success!
OpenSC [3F00]>
</pre>
Bingo! Cela fonctionne comme prévu. Donc, concrètement, rien de bien compliqué. On peut se demander pourquoi il faut triturer la documentation dans tous les sens pour obtenir ce résultat. Cela ressemble fort à de l'<a href="https://fr.wikipedia.org/wiki/Offuscation">offuscation</a>...
<br/><br/>
Reste à vérifier que l'on peut confirmer avec le certificat contenant la clé publique correspondante que le 'hash' a bien été signé par la clé privée...
<br/><br/>
D'abord, transformer le certificat de non-repudiation .der en .pem
<pre>
$ openssl x509 -inform der -in 5039-cert_3_sign.der \
-outform pem -out 5039-cert_3_sign.pem
</pre>
En extraire la clé publique
<pre>
$ openssl x509 -noout -pubkey -in 5039-cert_3_sign.pem \
-out cert_3_sign-pubkey.pem
</pre>
Enfin, vérifier la signature
<pre>
$ openssl pkeyutl -verify \
-in cal2023.sha256 \
-inkey cert_3_sign-pubkey.pem \
-sigfile cal2023-sha256.sig \
-pubin \
-pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha256
Signature Verified Successfully
</pre>
<b>cal2023.sha256</b> est un fichier binaire contenant le résultat de 'cal 2023 | sha256sum'.<br/>
<b>cal2023-sha256.sig</b> est la signature avec l'algorithme 0x20 du hash sha256 sous forme de fichier binaire de 256 octets.<br/>
<b>cert_3_sign-pubkey.pem</b> est la clé publique extraite du certificat.<br/><br/>
Les fichiers binaires ont été obtenu par un petit programme en 'C' interagissant avec la carte en utilisant la libpcsclite (voir <a href="https://github.com/xofc/my_beid">https://github.com/xofc/my_beid</a>).
<br/><br/>
<br/><br/>
À suivre...
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.comBruxelles, Belgique50.8476424 4.357169622.537408563821153 -30.7990804 79.157876236178851 39.5134196tag:blogger.com,1999:blog-4811625769590798586.post-41552600594852740672022-11-02T12:04:00.108+01:002022-11-11T11:10:09.654+01:00Tensiometre Bluetooth sur Linux<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn0o4cWUbaxgM_TkWLcrDkz1jB5XlevnVuAzBQqfFDDT-i4hO2O1Ty3DKgmXuKXc9Tdqf51dV3YrgQtmtxXSEBUw7ZRiAbXPcQuO_8afniZNnqxDCKB_RTCVrJlF8zXbrNs-h6sRGhrwYmLNe-13RMe-2XNxWfVWBzldYEoyksHUfxLzYCnyCMB2rd/s1800/BU546+Ubertooth+Rpi.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1522" data-original-width="1800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn0o4cWUbaxgM_TkWLcrDkz1jB5XlevnVuAzBQqfFDDT-i4hO2O1Ty3DKgmXuKXc9Tdqf51dV3YrgQtmtxXSEBUw7ZRiAbXPcQuO_8afniZNnqxDCKB_RTCVrJlF8zXbrNs-h6sRGhrwYmLNe-13RMe-2XNxWfVWBzldYEoyksHUfxLzYCnyCMB2rd/s320/BU546+Ubertooth+Rpi.jpg"/></a></div>
Suite à une visite médicale, on m'a conseillé de suivre ma tension... J'avais bien un <a href="https://fr.wikipedia.org/wiki/Tensiom%C3%A8tre">tensiomètre</a> de poignet qui traînait dans un tiroir depuis des années mais il paraît que c'est mieux d'en utiliser un avec un brassard... Petit tour dans une grande surface de trucs électroniques, je repère un <a href="https://www.medisana.com/fr/produit/bu-542-connect/">Medisana BU-546 Connect</a> (542~546; ~50.00 euros) qui a une connexion Bluetooth. Petit tour sur Internet. Cela n'a pas l'air trop mauvais, c'est une société allemande de l'ouest qui semble avoir bonne réputation. Rien sur Linux en lien avec le bidule, ça va être l'occasion de découvrir Bluetooth et d'expérimenter. Bref, c'est irrésistible...
<br/><br/>
Le tensiomètre fontionne avec une application (gratuite) pour smartphone, <a href="https://www.medisana.com/en/VitaDock-App-2-0.html">Vitadock+</a> ...qui demande d'activer la géolocalisation et envoie toutes les données (somme toute assez confidentielles) dans le cloud. Ça, ce n'est pas une bonne idée. En fait, c'est un peu scandaleux, c'est pire que le driver d'imprimante dont <a href="https://fr.wikipedia.org/wiki/Richard_Stallman">Richard Stallman</a> voulait les sources. Pour dispositif médical, je dois pouvoir contrôler l'utilisation des données.
<br/><br/>
D'abord, découvrir <a href="https://fr.wikipedia.org/wiki/Bluetooth">Bluetooth</a> sous Linux. Les outils et le b-a-ba de la communication. La première idée était de trouver un autre gadget compatible Linux et d'observer son fonctionnement. En fait, je pouvais déjà commencer à essayer de communiquer entre mon laptop et un Raspberry Pi. Mettons que je prenne le RPi comme 'device' (serveur) :
<pre>
$ sudo btmgmt le on # pour activer le <a href="https://fr.wikipedia.org/wiki/Bluetooth_%C3%A0_basse_consommation">Low Energy</a>
$ sudo <a href="https://manpages.org/hciconfig">hciconfig</a> hci0 piscan # pour se laisser scanner (?)
$ <a href="https://manpages.org/bluetoothctl">bluetoothctl</a> # pour le rendre découvrable et activer l'annonce (advertising)
> help
> discoverable on
> advertise on
> show
</pre>
Du côté du laptop (client), je peux utiliser <a href="https://manpages.org/gatttool">gatttool(1)</a> pour me connecter et interroger le Rpi :
<pre>
$ gatttool -I
> connect 11:22:33:44:55:66
> help
> primary
> characteristics
> char-desc
> char-read-hdn 0x0001
> char-read-uuid 0x2a01
...
</pre>
C'est très bien. Maintenant, il faut essayer de faire la même chose avec le tensiomètre... D'abord, connaître sa mac-address. Ce n'est évidemment marqué nulle part. Après une mesure de la tension, il active le Bluetooth et s'annonce (advertising) pendant une minute. En principe, je devrais pouvoir le détecter avec hcitool(1)
<pre>
$ sudo <a href="https://manpages.org/hcitool">hcitool</a> lescan
</pre>
Mais pour une raison qui m'échappe, le lescan me renvoie un tas de mac-addresses dont quelques unes seulement sont associées à un nom d'appareil (la TV des voisins, une voiture qui passe, mon smartphone si j'active le Bluetooth,...) mais rien qui ressemble à Medisana ou Transtek, la société chinoise qui fabrique le bidule. Pas plus que le <a href="https://maclookup.app/vendors/guangdong-transtek-medical-electronics-co-ltd">manufacturer-id du constructeur chinois</a> (Medisana n'en a pas). En utilisant le smartphone (Samsung A40), les parasites sont absents et un BS1490 apparaît mystérieusement à la fin d'une mesure de tension. C'était donc ça! <a href="https://maclookup.app/search/result?mac=7A%3A42%3A09">Maclookup</a> m'apprend que c'est une 'Localy Administred Address' (adresse aléatoire utilisée par discrétion pour éviter le repérage). Et, de fait, on retrouve TMB-190-BS dans le <a href="https://manuals.plus/fr/medisana/bu-542-connect-blood-pressure-monitor-manual">manuel du tensiomètre</a> et une recherche Internet mène à <a href="https://www.transtekcorp.com/products/medical-grade-blood-pressure-meter-tmb-1775-transtek/">la page du constructeur chinois</a>. En plus, il y a moyen de trouver des <a href="https://fcc.report/FCC-ID/OU9TMB1490BS/">documents</a> concernant la demande d'autorisation au <a href="https://fr.wikipedia.org/wiki/Commission_f%C3%A9d%C3%A9rale_des_communications">FCC</a> américain.
<br/><br/>
Avec la <a href="https://fr.wikipedia.org/wiki/Adresse_MAC">MAC-address</a>, je peux maintenant me connecter sur le tensiomètre et lire différentes choses mais rien ne semble correspondre à une tension. Tout est quasi constant d'une mesure à l'autre. La seule chose qui varie (une horloge?) varie même à l'intérieur d'une seule session. Là, ça va être difficile... Si il faut écrire quelque chose quelque part et lire le résultat ailleurs, il va falloir capturer ue session entre le tensiomètre et l'application du smartphone. Sniffer une communication Bluetooth n'est pas aussi simple que de capturer du traffic Ethernet avec <a href="https://manpages.org/tcpdump/8">tcpdump(8)</a>. Bluetooth fait du saut de fréquence (frequency hopping) et il est difficile de capturer toute la bande ISM 2.4 GHz. Heureusement, il existe un bidule génial de <a href="https://greatscottgadgets.com/">Great Scott Gadgets</a> dont Michael Ossmann décrit la genèse dans une <a href="https://hackaday.com/2011/02/09/ossmann-talks-about-ubertooth-at-schmoocon/">conférence</a> au <a href="https://en.wikipedia.org/wiki/ShmooCon">Shmoocon</a> de 2011 le <a href="https://greatscottgadgets.com/ubertoothone/">Ubertooth One</a>. Radin, comme d'habitude, je commence par commander un clone chinois qui se révélera fort capricieux. Je fais des tests entre le laptop et le Raspberry Pi et cela ne fonctionne correctement que très rarement. Un forum finit par me convaincre que cela fonctionne mieux avec la version officielle. Au diable l'avarice, j'en commande un vrai (aux Pays-Bas) que je reçois deux jours plus tard. Et cela fonctionne du premier coup entre le tensiomètre et le laptop (j'utilise l'Ubertooth One sur le Raspberry Pi pour avoir une version plus récente des outils (sur le laptop, je suis toujours en Ubuntu 18.04...). J'ai juste dû faire une mise à jour avec <a href="https://manpages.org/ubertooth-dfu">ubertooth-dfu</a>(1) du dernier firmware. Quelques messages d'erreurs, mais cela fonctionne.
<br/><br/>
<pre>
$ sudo ubertooth-btle -f -t 11:22:33:44:55:66 -r tensio.pcapng
</pre>
Et là, surprise! <a href="https://www.wireshark.org/">Wireshark(1)</a> décode les packets contenant la tension.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfcOvGj4sFRoXfoJDoMiWpw-Dsja4-XHasGTPqobCtblUOzy6Vt-CUsOxvr8WHsAymqGssQu1WJQ__U252Gm2Ib-Ln6Mvxn6f2aON_nEtny_gJc3yiZKq97WsHJclxiIQWX2IJlx93AkWpXWYyy4XDJQWbP69D8cJcz3y53zQR5j4MVR5jCvX4YiCk/s1869/bu546-wireshark.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="975" data-original-width="1869" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfcOvGj4sFRoXfoJDoMiWpw-Dsja4-XHasGTPqobCtblUOzy6Vt-CUsOxvr8WHsAymqGssQu1WJQ__U252Gm2Ib-Ln6Mvxn6f2aON_nEtny_gJc3yiZKq97WsHJclxiIQWX2IJlx93AkWpXWYyy4XDJQWbP69D8cJcz3y53zQR5j4MVR5jCvX4YiCk/s320/bu546-wireshark.jpg"/></a></div>
On peut aussi utiliser tshark(1) pour produire un fichier JSON que l'on peut imprimer, traiter avec grep(1), jq(1),... :
<pre>
$ tshark -r tensio.pcapng -T json > tensio.json
</pre>
À noter que le fichier JSON est un peu foireux, il n'y a pas de racine unique, il faut encadrer le contenu par quelque chose comme '{ "results": [' et ']}' pour pouvoir utiliser <a href="https://manpages.org/jq">jq(1)</a> et, dans jq, il faut utiliser des '"' (double quotes) parce qu'il y a des '.' dans les identifiants. Par exemple,
<pre>
$ cat medisana.json |jq '.results[]._source.layers.frame."frame.protocols"' |less
$ cat medisana.json |jq '.results[]._source.layers.btatt."btatt.blood_pressure_measurement.compound_value.systolic.mmhg"' |less
</pre>
Mais sinon, par exemple, dans une indication contenant une mesure, on peut lire:
<pre>
"btatt": {
"btatt.opcode": "0x0000001d",
"btatt.opcode_tree": {
"btatt.opcode.authentication_signature": "0",
"btatt.opcode.command": "0",
"btatt.opcode.method": "0x0000001d"
},
"btatt.handle": "0x0000000b",
"btatt.handle_tree": {
"btatt.service_uuid16": "6160",
"btatt.uuid16": "10805"
},
"btatt.blood_pressure_measurement.flags": "0x0000001e",
"btatt.blood_pressure_measurement.flags_tree": {
"btatt.blood_pressure_measurement.flags.reserved": "0x00000000",
"btatt.blood_pressure_measurement.flags.measurement_status": "1",
"btatt.blood_pressure_measurement.flags.user_id": "1",
"btatt.blood_pressure_measurement.flags.pulse_rate": "1",
"btatt.blood_pressure_measurement.flags.timestamp": "1",
"btatt.blood_pressure_measurement.flags.unit": "0x00000000"
},
"btatt.blood_pressure_measurement.compound_value.systolic.mmhg": "120",
"btatt.blood_pressure_measurement.compound_value.diastolic.mmhg": "62",
"btatt.blood_pressure_measurement.compound_value.arterial_pressure.mmhg": "91",
"btatt.blood_pressure_measurement.compound_value.timestamp": {
"btatt.year": "2022",
"btatt.month": "10",
"btatt.day": "27",
"btatt.hours": "17",
"btatt.minutes": "52",
"btatt.seconds": "0"
},
"btatt.blood_pressure_measurement.pulse_rate": "58",
"btatt.blood_pressure_measurement.user_id": "0x00000001",
"btatt.blood_pressure_measurement.status": "0x00000000",
"btatt.blood_pressure_measurement.status_tree": {
"btatt.blood_pressure_measurement.status.reserved": "0x00000000",
"btatt.blood_pressure_measurement.status.improper_measurement_position": "0",
"btatt.blood_pressure_measurement.status.pulse_rate_range_detection": "0x00000000",
"btatt.blood_pressure_measurement.status.irregular_pulse": "0",
"btatt.blood_pressure_measurement.status.cuff_fit_too_loose": "0",
"btatt.blood_pressure_measurement.status.body_movement": "0"
}
}
</pre>
Ce qui est curieux, c'est que tout ce décodage semble être fait par du code ad-hoc dans <a href="https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-btatt.c">packet-btatt.c</a> Il n'y aurait donc pas de définitions formelles comme les <a href="https://fr.wikipedia.org/wiki/Management_information_base">MIB</a>s du <a href="https://fr.wikipedia.org/wiki/Simple_Network_Management_Protocol">SNMP</a>. Et parmi les UUID-16, on trouve 0x2A35 pour la notification d'une caractéristique concernant la pression sanguine... (voir aussi Bluetooth <a href="https://www.bluetooth.com/specifications/assigned-numbers/">Assigned numbers</a> - <a href="https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Health%20Device%20Profile.pdf">HealthDeviceProfiles.pdf</a>)
Le tensiomètre répond donc bien à un standard : <a href="https://www.bluetooth.com/specifications/specs/blood-pressure-profile-1-1-1/">Blood-pressure-profile-1-1-1</a>. Ce n'est pas très compréhensible. C'est comme le bouquin '<i><a href="https://www.amazon.com/Bluetooth-Low-Energy-Developers-Handbook/dp/013288836X">Bluetooth Low Energy: The Developer's Handbook</a></i>' de Robin Heydon. C'est intéressant, très détaillé mais pas très pratique. Il faut le lire plusieurs fois, expérimenter avec les outils Linux et Wireshark, parcourir des blogs et des forums pour finir par avoir une idée de quoi il est question. Et, il n'y a, curieusement pas de références (ou de guide pour s'orienter dans la documention étendue de <a href="https://www.bluetooth.com/">bluetooth.com</a>)
<br/><br/>
Ainsi, avec Wireshark (en éliminant les packets sans intérêt avec le filtre '<a href="https://ubertooth.readthedocs.io/en/latest/capturing_BLE_Wireshark.html">btle.data_header.length > 0 || btle.advertising_header.pdu_type == 0x05</a>', après une découverte du tensiomètre par l'application Vitadock+, elle active les 'indications' en écrivant 0200 dans un canal particulier. Les mesures non encore transmises sont alors envoyées une par une, avec un timestamp comme 'indication'. On peut reproduire le mécanisme avec gatttool(1)
On reçoit alors des listes de 19 caractères en hexadécimal contenant la pression systolique, diatolique, la pression, le temps de la mesure (année, mois, jour, heure, minute, seconde) et le nombre de pulsations par minute) qu'il est facile de décoder en regardant la correspondance sur Wireshark(1).
<pre>
$ gatttool -b 11:22:33:44:55:66 -t random -I
[11:22:33:44:55:66][LE]> connect
Attempting to connect to 11:22:33:44:55:66
Connection successful
[11:22:33:44:55:66][LE]> char-write-req 0x000c 0200
Characteristic value was written successfully
Indication handle = 0x000b value: 1e 71 00 42 00 59 00 e6 07 0a 1c 0b 2b 00 3f 00 01 00 00
Indication handle = 0x000b value: 1e 85 00 49 00 67 00 e6 07 0a 1c 0c 1d 00 51 00 01 00 00
...
XX SS SS DD DD PP PP YY YY MM dd HH MM SS pp pp id
(SSSS=Systolic mmhg, DDDD=Diatolic, PPPP pressure, YYYY=year, MM=month, dd=day, HH=hour, MM=minute, SS=seconds, id=person)
</pre>
Vers le milieu, on retrouve l'année 2022 (0x07E6), octobre (0x0A), 28 (0x1C), etc...
<br/><br/>
Reste maintenant à écrire une petite application qui fait juste ça : connect, write(0200) et accepte/affiche les indications reçues. Ce qui n'est pas spécialement trivial parce que la documentation de l'API Bluetooth sur Linux est inexistante. La stratégie la plus simple serait de partir des sources de gatttool(1) mais il y a une masse de dépendances... On trouve beaucoup de choses en Python aussi mais Python est infernal au niveau des versions et des dépendances.
<br/><br/>
Ce qui serait bien aussi, ce serait de remettre le pointeur de lecture à zéro (ou à une valeur arbitraire) parce que là, le tensiomètre n'envoie que les nouvelles mesures, effectuées <i>après</i> le dernier transfert. Alors qu'il peut contenir jusqu'à 250 mesures par utilisateur. Il semblerait cependant que cela ne soit pas possible parce qu'on ne trouve pas de 'Record Access Control Point' (0x2a52) dans le caractéristiques du tensiomètre (voir ci-dessous) et que la fonctionalité est optionnelle.
<br/><br/>
<h2>Exploration avec gatttool(1)</h2>
(gatttool(1) serait à l'abandon et remplacé par <a href="https://manpages.org/bluetoothctl">bluetoothctl(1)</a> (tellement 'intuitif' que le manuel est virtuellement inexistant... (il faut taper 'menu gatt' pour avoir le sous-menu gatt...)).
<br/><br/>
<h3>Les 'services' du tensiomètre</h3>
<pre>
$ gatttool -b 11:22:33:44:55:66 -t random -I
[11:22:33:44:55:66][LE]> connect
Attempting to connect to 11:22:33:44:55:66
Connection successful
[11:22:33:44:55:66][LE]> primary
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0009, end grp handle: 0x000e uuid: 00001810-0000-1000-8000-00805f9b34fb
attr handle: 0x000f, end grp handle: 0x0012 uuid: 0000180f-0000-1000-8000-00805f9b34fb
attr handle: 0x0013, end grp handle: 0x0021 uuid: 0000180a-0000-1000-8000-00805f9b34fb
attr handle: 0x0022, end grp handle: 0xffff uuid: 00001805-0000-1000-8000-00805f9b34fb
[11:22:33:44:55:66][LE]>
</pre>
La commande 'primary' liste les 'services' disponibles sur le tensiomètre.
La partie variable des UUIDs sont des UUID-16 de 'services' dont on trouve la liste dans <a href="https://www.bluetooth.com/specifications/assigned-numbers/">https://www.bluetooth.com/specifications/assigned-numbers/</a> : <a href="https://www.bluetooth.com/wp-content/uploads/2022/11/assigned_numbers_release.pdf">assigned_numbers_release.pdf</a> :
<pre>
0x1800 Generic Access service
0x1801 Generic Attribute service
0x1810 Blood Pressure service
0x180f Battery service
0x180a Device Information service
0x1805 Current Time service
</pre>
Ce sont des informations que l'on peut aller chercher dans le tensiomètre. Ces 'services' sont décrits dans les documents <a href="https://www.bluetooth.com/specifications/specs/?types=adopted&keyword=service&filter=">Specifications and Tests Documents List/Services</a>. Par exemple, <a href="https://www.bluetooth.com/specifications/specs/blood-pressure-service-1-1-1/">Blood Pressure Service</a> (<a href="https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=531246">blood-pressure-service-1-1-1.pdf</a> et d'autres documents).
<br/><br/>
La manière d'accéder à ces informations est décrite dans des documents 'Profile' : <a href="https://www.bluetooth.com/specifications/specs/?types=adopted&keyword=profile&filter=">Specifications and Tests Documents List/Profiles</a>. Par exemple, <a href="https://www.bluetooth.com/specifications/specs/blood-pressure-profile-1-1-1/">Blood Pressure Profile</a> (<a href="https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=531245">blood-pressure-profile-1-1-1.pdf</a> et d'autres documents).
<br/><br/>
Il faut noter que tous les bidules Bluetooth ne sont pas forcément 'conformes' à un standard accepté. Ceux qui ont passé les tests de conformance se retrouvent dans la base de données cherchable : <a href="https://launchstudio.bluetooth.com/Listings/Search">https://launchstudio.bluetooth.com/Listings/Search</a>. La recherche avancée permet de trouver les bidules qui ont passé les tests avec succès. On peut, par exemple, lister ceux qui implémente le 'Blood Pressure Service' (BLS) et le 'Blood Pressure Profile' (BLP) ou, éventuellement regarder quels bidules d'une marque données ont un profil standard. Dans ce cas-ci, on arrive à une fiche concernant le BU-546 (en fait, un <a href="https://launchstudio.bluetooth.com/ListingDetails/25982">TMB-1490-TS</a> de Transtek) où on ne trouve (bizarrement?) pas de qualification 'blood pressure service/profile'...
<br/><br/>
<h3>Les 'caractéristiques' du tensiomètre</h3>
<pre>
$ gatttool -b 11:22:33:44:55:66 -t random -I
[11:22:33:44:55:66][LE]> connect
Attempting to connect to 11:22:33:44:55:66
Connection successful
[11:22:33:44:55:66][LE]> char-desc
/* 0x1800 Generic Access service */
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
/* 0x1801 Generic Attribute service */
handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
/* 0x1810 Blood Pressure service */
handle: 0x0009, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 00002a35-0000-1000-8000-00805f9b34fb
handle: 0x000c, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x000d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000e, uuid: 00002a49-0000-1000-8000-00805f9b34fb
/* 0x180f Battery service */
handle: 0x000f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0011, uuid: 00002a19-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002902-0000-1000-8000-00805f9b34fb
/* 0x180a Device Information service */
handle: 0x0013, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0015, uuid: 00002a29-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0017, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0018, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0019, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x001a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001b, uuid: 00002a27-0000-1000-8000-00805f9b34fb
handle: 0x001c, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001d, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x001e, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001f, uuid: 00002a28-0000-1000-8000-00805f9b34fb
handle: 0x0020, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0021, uuid: 00002a23-0000-1000-8000-00805f9b34fb
/* 0x1805 Current Time service */
handle: 0x0022, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0023, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0024, uuid: 00002a2b-0000-1000-8000-00805f9b34fb
handle: 0x0025, uuid: 00002902-0000-1000-8000-00805f9b34fb
[11:22:33:44:55:66][LE]>
</pre>
De nouveau, on retrouve les UUID-16 dans <a href="https://www.bluetooth.com/wp-content/uploads/2022/11/assigned_numbers_release.pdf">assigned_numbers_release.pdf</a> :
<pre>
0x2800 Primary Service
0x2803 Characteristic
0x2902 Client Characteristic Configuration
0x2a00 Device Name
0x2a01 Appearance
0x2a04 Peripheral Preferred Connection Parameters
0x2a19 Battery Level
0x2a23 System ID
0x2a24 Model Number String
0x2a25 Serial Number String
0x2a26 Firmware Revision String
0x2a27 Hardware Revision String
0x2a28 Software Revision String
0x2a29 Manufacturer Name String
0x2a2b Current Time
0x2a35 Blood Pressure Measurement
0x2a49 Blood Pressure Feature
</pre>
Bref, un peu de tout... On notera cependant qu'on écrit 0200 dans le 'Client Characteristic Configuration' (0x2902, handle 0x000c) du 'Blood Pressure service' (0x1810) pour activer les indications 'Blood Pressure Measurement' (0x2a35, handle 0x000b).
<br/><br/>
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-40330779865837140392022-08-15T19:40:00.001+02:002022-08-15T19:40:35.406+02:00Ais : ESARLe 28 juin 2022, rtl-sdr.com a présenté un article <a href="https://www.rtl-sdr.com/esar-extraordinarily-simple-ais-receiver-written-in-c/">ESAR – Extraordinarily Simple AIS Receiver written in C</a> avec un lien vers le code que l'on trouve <a href="https://gist.github.com/Dygear/23aa7b9027e6c14036150b57c034cdad">aussi sur github</a>.
<br/><br/>
Une partie radio de juste une centaine de lignes (lignes 307 à 402) nettoie le signal
<ul>
<li> Downsampling par 3 (340-344) parce que le rtl-sdr ne peut faire 100 kps, on utilise 300 kps; I1/Q1 est ré-utilisé.</li>
<li> Shift de 25 kHz (sample rate/4). Le signal est à 162 MHz +/- 25 kHz; cela le ramène à 0 en I1/Q1 et shift de 50 kHz pour avoir l'autre canal (346-364) en I2/Q2</li>
<li> Filtrage et décimation par deux sur charque canal (avec recyclage de I1/Q1 et I2/Q2) (371-377)</li>
<li> Démodulation AM & FM (379-387)</li>
<li> Pour chaque canal, recherche des trames</li>
</ul>
La recherche des trames consiste en :
<ul>
<li> Recherche de signal basé sur l'amplitude (161-171)</li>
<li> Recherche du maximum de corrélation du préambule (197-237)</li>
<li> Échantillonnage de la fréquence et transformation en bits (NRZI & bit stuffing) (251-289)</li>
</ul>
<br/><br/>
À suivre...
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-31784158551814177752022-03-26T18:38:00.004+01:002022-04-02T17:43:16.978+02:00Mesure CO2 avec Raspberry Pi et SCD30Après la mésaventure précédente, j'ai craqué pour un module <a href="https://sensirion.com/products/catalog/SCD30/">SCD30</a> de <a href="https://sensirion.com/">Sensirion</a>. Là, il ne suffit pas de l'allumer et de regarder l'affichage, il faut souder un connecteur, le raccorder à quelque chose et trouver un programme qui interagit avec. J'avais dans l'idée d'utiliser le I2C d'un Raspberry Pi mais j'ai eu un peu de mal à trouver quelque chose qui fonctionne et les outils de base i2c ne fonctionne pas parce que le module nécessite du clock stretching. Du coup, j'ai opté pour le protocole <a href="https://fr.wikipedia.org/wiki/Modbus">Modbus</a> sur la liaison <a href="https://fr.wikipedia.org/wiki/RS-232">RS-232</a>. Et là, c'est relativement trivial. Cinq fils à connecter et un petit programme en 'C' et c'est parti. Voir <a href="https://github.com/xofc/my_scd30">my_scd30</a> sur GitHub.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY2_dmg9xJqH5ZCBCMdXiKTi2RCMVaMbqGr8kRjru7VxKjXvQn33UdSRt4Zfw-mMKetM-y2xK_MrpEf00Elw3vDNz6iyAzLP9Hs_Pi_8FLbQlOCyRHvV3NsTmmwudU_A1sG-uGdWNihhx9DsvXkoFCbe2X9X4HAPS4dyjm2kYJhhA6W-3imTZ-nQjB/s1200/Rpi+scd30.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY2_dmg9xJqH5ZCBCMdXiKTi2RCMVaMbqGr8kRjru7VxKjXvQn33UdSRt4Zfw-mMKetM-y2xK_MrpEf00Elw3vDNz6iyAzLP9Hs_Pi_8FLbQlOCyRHvV3NsTmmwudU_A1sG-uGdWNihhx9DsvXkoFCbe2X9X4HAPS4dyjm2kYJhhA6W-3imTZ-nQjB/s320/Rpi+scd30.jpg"/></a></div>
Il est assez facile d'injecter les données dans une 'timeseries database' <a href="https://fr.wikipedia.org/wiki/InfluxDB">Influxdb</a> et d'afficher les mesures avec <a href="https://fr.wikipedia.org/wiki/Grafana">Grafana</a>:
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwKTiKzHugmuqnln6CKpZaAfR5ipZ4yUjr4WwaCSlu9DqmJs4fm7_ia5ramKaZGGx66XXF4jf6fUlVFTZNCFB1NMYvWWynCjgzj19WEm49S_i3H_OfIoxoz1NnPNHfLLEcolQn1R-w7K6y5x9lFKfy5jrwY_cqo5yUm1sJ-bLde3wqDo8-W3j_6z2Z/s1517/my_scd30.grafana.20220326.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="1517" data-original-width="1204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwKTiKzHugmuqnln6CKpZaAfR5ipZ4yUjr4WwaCSlu9DqmJs4fm7_ia5ramKaZGGx66XXF4jf6fUlVFTZNCFB1NMYvWWynCjgzj19WEm49S_i3H_OfIoxoz1NnPNHfLLEcolQn1R-w7K6y5x9lFKfy5jrwY_cqo5yUm1sJ-bLde3wqDo8-W3j_6z2Z/s320/my_scd30.grafana.20220326.jpg"/></a></div>
Il y a eu une coupure de courant et j'ai oublié de rallumer le Raspberry Pi...
Je ne suis pas très sûr de la calibration. J'ignore quel est le niveau de base en ville. J'imagine que si <a href="https://gml.noaa.gov/ccgg/trends/">la référence planétaire</a> se trouve à <a href="https://fr.wikipedia.org/wiki/Hawa%C3%AF">Hawaï</a>, il doit y avoir une raison.
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-71709700070449661112022-03-25T05:18:00.000+01:002022-03-25T05:18:01.204+01:00CO2 Mesaventure chinoiseLors de l'épidémie de <a href="https://fr.wikipedia.org/wiki/Maladie_%C3%A0_coronavirus_2019">covid-19</a>, les <a href="https://fr.wikipedia.org/wiki/Capteur_de_dioxyde_de_carbone">capteurs de CO2</a> sont devenus à la mode...
<br/>
Tous ne se valent pas. De petits margoulins se sont précipités pour proposer des appareils en ayant l'apparence mais pas la fonctionalité. Ainsi, un joli capteur acheté pas trop cher sur AliExpress affiche un taux de ppm qui varie en fonction du temps mais un petit test simple introduit un gros doute sur son fonctionnement. Si je mets le bidule dans un sac en plastique et que je souffle dedans, je devrais dépasser de loin la limite supérieure du capteur, 5000 ppm parce que j'expire 4% de CO2, soit 40000 ppm et... il ne se passe rien. J'ouvre la fenêtre, la mesure monte en flèche et génère une alarme. Tout cela est hautement suspect et je ne peux résister à regarder ce que contient ce bidule...
<br/><br/>
C'est difficile à ouvrir, c'est collé/vissé ou thermosoudé. Cela fait un peu mal au coeur de charcuter un joli gadget tout neuf mais là, il y a visiblement quelque chose qui ne va pas. Et, de fait, le bidule ne contient aucun composant capable de mesurer le CO2. Il y a juste un DHT11 qui mesure l'humidité et la température. C'est vraiment curieux et incompréhensible.
<br/><br/>
Ce bidule est soigné, cela a demandé des gens intelligents et capables pour concevoir le boîtier, l'affichage, la carte électronique, le programme,... et le tout est complètement factice. En fait, à la base, cela probablement été un instrument fonctionnel. Quelque margoulin a dû se l'approprier, faire l'économie d'un capteur coûteux et soudoyer un programmeur de seconde zone pour faire un programme qui simule le fonctionnement. À moins qu'ils aient eu l'intention de faire un vrai capteur et qu'ils n'y soient jamais parvenus; qu'ils aient développé un truc factice pour obtenir des capitaux et aient laissé l'affaire en l'état, laissant l'investisseur avec un truc inutilisable.
<br/>
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjdzdjBrFfEIHAoV8x2-Q19BPbOlqTaL4eDoV36lsxvFvxPS5WEQkT0VytexAPzobXDeaivxvqI9DVK31n6HIAo4gqGXCiFmjopJ3i_nZZ63_eVw0cE-NWMMFjaFTWgiO86nTLiHaVQsHfvzc2zpYwcjp7IcmNq_tk-e8KoFdAzcrYBRck00FUMYpC/s2592/_DSC02025.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1944" data-original-width="2592" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjdzdjBrFfEIHAoV8x2-Q19BPbOlqTaL4eDoV36lsxvFvxPS5WEQkT0VytexAPzobXDeaivxvqI9DVK31n6HIAo4gqGXCiFmjopJ3i_nZZ63_eVw0cE-NWMMFjaFTWgiO86nTLiHaVQsHfvzc2zpYwcjp7IcmNq_tk-e8KoFdAzcrYBRck00FUMYpC/s320/_DSC02025.JPG"/></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyN2g3k181rwlGtra8KRGlB-GFQMZQYqyHJGuSN05haCfkGvvv9U6KR7MuMJHD5Lns3wjZZxeQ03R4vSUoDJQDINctxrLpUvDrgeMQc72WtCofQRlhQnFYFqkXamrbvBC9bCnJciNgYwCA33tl0BCJvJBo8-Xpnu6dZc8wjJs3p2FeRLHIAdqk3Ql8/s2592/_DSC02021.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1944" data-original-width="2592" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyN2g3k181rwlGtra8KRGlB-GFQMZQYqyHJGuSN05haCfkGvvv9U6KR7MuMJHD5Lns3wjZZxeQ03R4vSUoDJQDINctxrLpUvDrgeMQc72WtCofQRlhQnFYFqkXamrbvBC9bCnJciNgYwCA33tl0BCJvJBo8-Xpnu6dZc8wjJs3p2FeRLHIAdqk3Ql8/s320/_DSC02021.JPG"/></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwDzvIsQzBICnceb9qcMQg8vbPUx2lodyUXoKcos3RqMBW2f3pmurp7RCTr2h43bIiGZO4sPZ_YCXDfsh65Cv2lPHxk7yIrkIu7itx0cOor880r7MrCdrV1nORqg3J1z3pzmzbK8q1ILrtf_LoZaQBbDQ9WWNaq1L4ZjWGe3byup8b_WlemR5aHIQf/s2592/_DSC02022.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1944" data-original-width="2592" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwDzvIsQzBICnceb9qcMQg8vbPUx2lodyUXoKcos3RqMBW2f3pmurp7RCTr2h43bIiGZO4sPZ_YCXDfsh65Cv2lPHxk7yIrkIu7itx0cOor880r7MrCdrV1nORqg3J1z3pzmzbK8q1ILrtf_LoZaQBbDQ9WWNaq1L4ZjWGe3byup8b_WlemR5aHIQf/s320/_DSC02022.JPG"/></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNmzHXzVYBUso3pG5vcj8CYftjc323ixnk7sBOrX001ppCD3tmejuTZ6nyZ90LoCFm6m8tP2j8ULpc4p_do63SC826mE4r3lXLAQfJ1yZ0yFdbUXa-NPRpDShsrwutpFgdUrv-ua0bilmvGH-K4ODk7EXTntX4ok4uJvwQcSqc9GUoFTwQ4I-zGXGa/s2592/_DSC02023.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1944" data-original-width="2592" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNmzHXzVYBUso3pG5vcj8CYftjc323ixnk7sBOrX001ppCD3tmejuTZ6nyZ90LoCFm6m8tP2j8ULpc4p_do63SC826mE4r3lXLAQfJ1yZ0yFdbUXa-NPRpDShsrwutpFgdUrv-ua0bilmvGH-K4ODk7EXTntX4ok4uJvwQcSqc9GUoFTwQ4I-zGXGa/s320/_DSC02023.JPG"/></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1erkBlRUXrWUXWSdFldNIRv-o3g-xrBZMMBbjVRElDODGwKTBdcbjTtYV78Bp552eyqZjr5rQMfLegPpAOF-g82D3eFATIZg6j0RosiI6bwSXUGTCjXOQ5S_Tzt25qUqMCzLRD51cVdk9bBPwYFD_GuRB9jV6hBuY4zbVazrUSFpY1XB3wZQLpi3f/s2592/_DSC02024.JPG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1944" data-original-width="2592" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1erkBlRUXrWUXWSdFldNIRv-o3g-xrBZMMBbjVRElDODGwKTBdcbjTtYV78Bp552eyqZjr5rQMfLegPpAOF-g82D3eFATIZg6j0RosiI6bwSXUGTCjXOQ5S_Tzt25qUqMCzLRD51cVdk9bBPwYFD_GuRB9jV6hBuY4zbVazrUSFpY1XB3wZQLpi3f/s320/_DSC02024.JPG"/></a></div>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-72483368302451941732021-12-12T18:15:00.045+01:002021-12-30T15:57:46.237+01:00HC-12<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjna6wu8nKAQHxDWQd2OAyxNExndMAMCrptjC-W6hFDOgUX8xuwIAIA6eQbT380uoMwk6d2WuF88A2cp67il-8TdZ6Jox04dSxEwKAzEuCClXwsqixclHNaGV9-FZxXzy0uPQNVykCxIjeaEYrRh9KENvYUKu7deN2f27QuVAT1EWCl20RbRhby9O8C=s1200" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/a/AVvXsEjna6wu8nKAQHxDWQd2OAyxNExndMAMCrptjC-W6hFDOgUX8xuwIAIA6eQbT380uoMwk6d2WuF88A2cp67il-8TdZ6Jox04dSxEwKAzEuCClXwsqixclHNaGV9-FZxXzy0uPQNVykCxIjeaEYrRh9KENvYUKu7deN2f27QuVAT1EWCl20RbRhby9O8C=s320"/></a></div>
Le <a href="https://statics3.seeedstudio.com/assets/file/bazaar/product/HC-12_english_datasheets.pdf">HC-12</a> 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 <a href="https://www.silabs.com/documents/public/data-sheets/Si4463-61-60-C.pdf">Si4463</a> de Silicon Labs piloté par un microcontrôleur <a href="https://www.st.com/en/microcontrollers-microprocessors/stm8s003f3.html">STM8S</a> avec un code non public (<a href="https://github.com/al177/hc12pj">ici</a>, il se propose d'en modifier le firmware...).
<h1> Raspberry Pi</h1>
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
<pre>
$ minicom -b 9600 -D /dev/ttyS0
</pre>
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 <a href="https://en.wikipedia.org/wiki/Getty_%28Unix%29">getty</a> 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).
<br/><br/>
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).
<pre>
$ while sleep .005; do echo -n "U" > /dev/ttyS0; done
</pre>
<h1>GnuRadio</h1>
Pour voir si le module émet quelque chose, j'utilise <a href="https://www.gnuradio.org/">GnuRadio</a> avec un <a href="https://www.rtl-sdr.com/buy-rtl-sdr-dvb-t-dongles/">RTL-SDR</a> (ou équivalent à quelques euros).
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgK0GnAtHbg8-SXLUCkR96TBPv6i947tYZbVO3FlYx7mczmpI4BtWLM0KKOAkKXQIvmw4yC4jNkNE_CRlmcZSi2XZLiLFIm7_un9X6Hc-QGYnxIaROpyIXT5OguMhRZN3pTKQtTM8faTWvRyKrAoKe4hTZq3VUggNGOp9Pf-ZRuXncuUk0E5sVeROUf=s718" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="292" data-original-width="718" src="https://blogger.googleusercontent.com/img/a/AVvXsEgK0GnAtHbg8-SXLUCkR96TBPv6i947tYZbVO3FlYx7mczmpI4BtWLM0KKOAkKXQIvmw4yC4jNkNE_CRlmcZSi2XZLiLFIm7_un9X6Hc-QGYnxIaROpyIXT5OguMhRZN3pTKQtTM8faTWvRyKrAoKe4hTZq3VUggNGOp9Pf-ZRuXncuUk0E5sVeROUf=s320"/></a></div>
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.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgnLXQiaCNVVIe54iHfzI7aiAlZQ3-2VqzWGU34hQs8-QRr-03hTe-A0smhXsaVOnKynu09tBRZyz2lG3fQczTjlO8Db8_e0UxbR9kP6aHfQjiYqrbQp0FCdtQymhlWhXBlmLXY3LoBYKpNLKnhkV4YJ0y92LXLqXGQj8N4tsN8MIzqFo3zFuLvmsjK=s1238" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="732" data-original-width="1238" src="https://blogger.googleusercontent.com/img/a/AVvXsEgnLXQiaCNVVIe54iHfzI7aiAlZQ3-2VqzWGU34hQs8-QRr-03hTe-A0smhXsaVOnKynu09tBRZyz2lG3fQczTjlO8Db8_e0UxbR9kP6aHfQjiYqrbQp0FCdtQymhlWhXBlmLXY3LoBYKpNLKnhkV4YJ0y92LXLqXGQj8N4tsN8MIzqFo3zFuLvmsjK=s320"/></a></div>
Donc le module fonctionne et je peux générer du signal à volonté.
<br/><br/>
<h1> rtl-sdr et GNU Octave</h1>
Maintenant, enregistrons une courte séquence avec l'utilitaire '<a href="https://manpages.ubuntu.com/manpages/trusty/man1/rtl_sdr.1.html">rtl-sdr</a>' sur le portable :
<pre>
$ rtl_sdr -f 433400000 -s 512000 -n 64000 U.iq8
</pre>
et utilisons <a href="https://www.gnu.org/software/octave/index">GNU Octave</a> 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é.
<pre>
$ cat print_phase.m
s=loadFile("U.iq8");
au=unwrap(arg(s));
plot(au(10000:14100));
print -dpng "signal.png"
</pre>
Et nous obtenons :
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEieaBT6c5vDVCewyr4CUikmQQWnQeJ07uBgm3nqVdgkVd7UPOQ7qjJ9ZM5WiszDZo53LDrTg1N33Ulc2gfpe3L0YpVOBKcn1jcxD2CfVFKbzjf5Cf9VZ2c6j8hKKMr6VX0h5jevIHgKNkzamajr3iv2EI7tynvg8P_N-KL5RQg9nN6hTorcPfVKznKN=s1200" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/a/AVvXsEieaBT6c5vDVCewyr4CUikmQQWnQeJ07uBgm3nqVdgkVd7UPOQ7qjJ9ZM5WiszDZo53LDrTg1N33Ulc2gfpe3L0YpVOBKcn1jcxD2CfVFKbzjf5Cf9VZ2c6j8hKKMr6VX0h5jevIHgKNkzamajr3iv2EI7tynvg8P_N-KL5RQg9nN6hTorcPfVKznKN=s320"/></a></div>
NB: loadFile() lit un fichier IQ 8 bits de rtl-sdr pour en faire un vecteur complexe flottant.
<pre>
$ 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);
</pre>
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) :
<pre>
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
</pre>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjSUiIS2ZzF0mXPgFhARU-mBt0_pUovXFWatknGhLyTE11z29PsFj6KGGgI7wzaWn9qjh3i-tmPiuRJgIqKJ4CFA4h9NXaPTZk3hXSlwN-3wdJYmpWtp3g0fr4XK5n1KDNrinf8Q1DKIbMHpixjvezBkTubigFoKQ_vv9_rb0kkX-5vmIwWQYVOLMoq=s1144" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="711" data-original-width="1144" src="https://blogger.googleusercontent.com/img/a/AVvXsEjSUiIS2ZzF0mXPgFhARU-mBt0_pUovXFWatknGhLyTE11z29PsFj6KGGgI7wzaWn9qjh3i-tmPiuRJgIqKJ4CFA4h9NXaPTZk3hXSlwN-3wdJYmpWtp3g0fr4XK5n1KDNrinf8Q1DKIbMHpixjvezBkTubigFoKQ_vv9_rb0kkX-5vmIwWQYVOLMoq=s320"/></a></div>
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.xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-67367908673373025512021-11-21T18:02:00.004+01:002021-11-21T18:02:48.698+01:00Gravier luminescent 2Le TSL230R n'ayant pas donné de très bon résultats, j'ai commandé un kit <a href="https://www.adafruit.com/product/1980">TSL2591 d'Adafruit</a>...
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzpMcgZ7pnaFGZ9hceGVFYcIRTxh6uWeCTDc_NUDKLLxlDv_XZsS_VIz_FOXPubGiYebu3Xg0F7Qy6nKw5qaz9xa9qqH_GkbfCgNHYL0iz4wHNObxJadnfKvjGwrbC5WQmkt2BRH0wOkU/s1200/tsl2591.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzpMcgZ7pnaFGZ9hceGVFYcIRTxh6uWeCTDc_NUDKLLxlDv_XZsS_VIz_FOXPubGiYebu3Xg0F7Qy6nKw5qaz9xa9qqH_GkbfCgNHYL0iz4wHNObxJadnfKvjGwrbC5WQmkt2BRH0wOkU/s320/tsl2591.jpg"/></a></div>
Le composant TSL2591, plus sophistiqué, communique en i2c et donc, je dois utiliser autre chose que le clone Saleae... Deux possibilités faciles : utiliser un Arduino ou un Raspberry Pi. Va pour le Raspberry. J'ai justement un Pi 4 dans un boîtier <a href="https://www.argon40.com/argon-one-m-2-case-for-raspberry-pi-4.html">Argon One</a> qui ne demande qu'à servir.
<br/><br/>
Première étape, télécharger et installer le <a href="https://www.raspberrypi.com/software/operating-systems/">Raspberry Pi OS</a>. Dans le temps, l'installation se faisait avec dd (ou en copiant les fichiers sur une FAT32?). Ce temps-là, semble révolu. Pas moyen de trouver la moindre information technique sur le processus de démarrage, tous les chemins mènent au <a href="https://www.raspberrypi.org/downloads.../">Pi imager</a> qui, malheureusement, refuse de s'installer sur mon vieil Ubuntu pour une question de dépendance (libc, qt,...) et donc, ce sera une alternative : <a href="https://www.balena.io/etcher/">BalenaEtcher</a>... 90 MB pour remplacer dd... Il est bien loin le temps où tout un environnement Linux tournait sur une <a href="https://fr.wikipedia.org/wiki/Disquette#La_disquette_3_pouces_et_demi">disquette 3.5'</a> de 1.6 MB. Enfin, c'est vrai que si on fait confiance au programme, cela fonctionne et on ne se fait pas trop peur à choisir entre les /dev/sdb, /dev/sdc,... On met la carte SD dans le lecteur de carte SD du portable, on clique, on confirme et ça flashe.
<br/><br/>
Maintenant, le Raspberry, c'est bien mais si il faut rajouter une souris, un clavier et écran, un câble Ethernet, ça fait vite beaucoup de fils. Donc, la route à suivre est l'option <a href="https://letscodepare.com/blog/how-to-setup-raspberry-pi-4-in-headless-mode">headless</a>. On ré-insère la carte SD dans le portable et on met deux fichiers dans /media/moi/boot/ : un fichier 'ssh' vide et un fichier 'wpa_supplicant.conf' qui contient :
<pre>
country=BE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
scan_ssid=1
ssid="mon-réseau-wifi"
psk="mon-mot-de-passe-wifi"
}
</pre>
À partir de là, quand on allume le Raspberry Pi avec le bouton de l'Argon One, il va chercher une adresse IP par DHCP sur le bidule WiFi (sur ma b-Box 3 de Proximus). Reste à connaître son adresse IP... Soit en allant voir sur http://mymodem (http://192.168.1.1) soit en scannant le subnet avec <a href="https://duckduckgo.com/?q=nmap">nmap</a>, puis en se connectant avec l'utilisateur 'pi' (mot de passe, à changer 'raspberry'). Par je ne sais plus quel mécanisme, le RPi parvient à faire connaître son nom et il n'est pas nécessaire de faire le ssh sur une adresse IP (mais le scan de nmap semble quand même nécessaire).
<pre>
$ nmap -sP 192.168.1.*
...
$ ssh pi@raspberripy # or ssh pi@192.168.1.47
pi@raspberrypi:~ $
</pre>
Tant qu'à faire, installons le script de shutdown lié au bouton de l'Argon One. On pourra ainsi l'arrêter proprement en maintenant le bouton appuyé quelques secondes.
<pre>
$ curl https://download.argon40.com/argon1.sh | bash
</pre>
Reste maintenant à configurer le Rpi pour pouvoir utiliser l'interface i2c. Cela se passe du côté de 'raspi-config' avec des menus texte.
<pre>
$ sudo raspi-config
</pre>
Le branchement est trivial : on connecte le fil vert sur le bouton vert,... (3.3 Volt, GND, SCL, SDA) Il est préférable de le faire avec le Rpi éteint. Il faut maintenant charger les utilitaires et librairies pour le faire fonctionner...
<pre>
$ sudo apt-get install wiringpi
$ sudo apt-get install i2ctools
$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
</pre>
Le TSL2591 est bien détecté en 0x29.
<br/><br/>
Il ne reste plus qu'à lire la <a href="https://cdn-shop.adafruit.com/datasheets/TSL25911_Datasheet_EN_v1.pdf">datasheet</a> et à trouver quelques exemples de programmes (i2c et tsl2591) pour (la facilité) et en faire une version minimaliste (pour la compréhension) :
<pre>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wiringPiI2C.h>
#define DEVICE_ID 0x29
int main (int argc, char **argv)
{
int fd;
int i, id, status;
int gain, itime;
if (argc != 3)
{
fprintf(stderr, "%s: usage is %s <gain> <itime>\n", argv[0], argv[0]);
fprintf(stderr, "\tgain : 0-3 (low/medium/high/max)\n");
fprintf(stderr, "\titime : 0-5 (100/200/300/400/500/600 ms)\n");
exit(-1);
}
// setbuf(stdout, NULL);
gain = atoi(argv[1]);
itime = atoi(argv[2]);
if ((fd = wiringPiI2CSetup(DEVICE_ID)) < 0)
{
printf("Failed to init I2C communication.\n");
return -1;
}
id = wiringPiI2CReadReg8(fd, 0xA0 | 0x12);
fprintf(stderr, "tsl2591 id=0x%02x gain=%d itime=%d\n", id, gain, itime);
wiringPiI2CWriteReg8(fd, 0xA0 | 0x00, 0x93); // ENABLE_REG = POWERON | AEN | AIEN | NPIEN
wiringPiI2CWriteReg8(fd, 0xA0 | 0x01, ((gain & 0x03) << 4) | (itime & 0x07)); // CONTROL_REG = GAIN | TIME
wiringPiI2CWriteReg8(fd, 0xA0 | 0x0C, 0x00); // PERSIST_REG = 0
// status = wiringPiI2CReadReg8(fd, 0xA0 | 0x13);
// fprintf(stderr, "status=0x%02x\n", status);
while (1)
{
int x = wiringPiI2CReadReg16(fd, 0xA0 | 0x14);
fprintf(stdout, "%d\n", x);
sleep(1);
}
return 0;
}
</pre>
Et compiler le tout avec un Makefile naïf :
<pre>
tsl2591: tsl2591.c
gcc -o tsl2591 tsl2591.c -lwiringPi
</pre>
Pour mesurer des intensités lumineuses faibles, la LED verte est assez génante... Mais bon... Plutôt que de la désouder, je décide de la masquer tant bien que mal.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV3aKp4lVG9bSjriK7NAnMG98tdrDkorNzAm8qCekhLxX5akfr500WnczJSqHaSLMME0Ctj6jL8iMlPZEKoVDe0tHcvS0uio3WyykqULdDVtv3dPQB0Smpxq164bewL73RjXVJq_IP7WY/s1200/tsl2591-up.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV3aKp4lVG9bSjriK7NAnMG98tdrDkorNzAm8qCekhLxX5akfr500WnczJSqHaSLMME0Ctj6jL8iMlPZEKoVDe0tHcvS0uio3WyykqULdDVtv3dPQB0Smpxq164bewL73RjXVJq_IP7WY/s320/tsl2591-up.jpg"/></a></div>
Avec un gravier bleu, cela donne :
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIhunKAS1X_8ZGemUtZ0D6Ntxzj-mIgPfdjIfEox-OVQvYzkIv5EH3afG-yA2k8NDSZ6Q4KWNNeJncx2qb9K4sa5hoMylot_CVN7jWac0CezlnkI3IMmDSNE3Vt2m1Ub_J5se6-Nuup3A/s1200/blue.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="400" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIhunKAS1X_8ZGemUtZ0D6Ntxzj-mIgPfdjIfEox-OVQvYzkIv5EH3afG-yA2k8NDSZ6Q4KWNNeJncx2qb9K4sa5hoMylot_CVN7jWac0CezlnkI3IMmDSNE3Vt2m1Ub_J5se6-Nuup3A/s320/blue.png"/></a></div>
Pour bien faire, il faudrait convertir les comptages en unités lumineuses... (Ici, c'est avec le gain maximum intégré sur le temps prédéfini maximum (600 ms))
<br/><br/>
Puis, il faudrait bien sûr refaire l'expériences de nombreuses fois pour en maîtriser tous les paramètres...
<br/><br/>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-22000266622063213522021-09-13T18:36:00.197+02:002021-10-18T07:30:07.234+02:00Gravier luminescentLors de la nuit des étoiles à l'Euro Space Center de Transinne, le 12 août 2021, nous avons visité leur nouveau chemin des planètes.
On a appris que cela avait été réalisé par la société Interblocs de Libramont. Il s'agit d'un chemin bétonné dans lequel sont incrustés des graviers luminescents.
Il s'agit, en fait, d'<a href="https://fr.wikipedia.org/wiki/Aluminate_de_strontium">aluminate de strontium</a> dopé avec des terres rares du genre <a href="https://fr.wikipedia.org/wiki/Europium">europium</a>. Bien après minuit, c'était encore très lumineux et on pouvait se balader en plein champ par une nuit sans Lune sans le moindre problème. C'est magique. Ayant observé à côté du chemin ce qui ressemblait à des lucioles, j'ai rapporté chez moi un gravier de quelques millimètres pour faire des tests. La rémanence est étonante. Cela reste phosphorescent pendant des heures. C'est en partie dû à la sensibilité de l'oeil humain dans le vert.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk8by0T94KqFwz0G78pvYVQth6d-EVlH0DX-q_ZyDLND_atcT9vMtMoMl5vGwOxgQlwkRwPbU86fLwfv8gsEpCBf0MM7hJhTx4mmvpnU-tjEuSs_q-9vHuyKIhUPwfkcbkvRAb71AaIVE/s1200/StrontiumAluminate.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk8by0T94KqFwz0G78pvYVQth6d-EVlH0DX-q_ZyDLND_atcT9vMtMoMl5vGwOxgQlwkRwPbU86fLwfv8gsEpCBf0MM7hJhTx4mmvpnU-tjEuSs_q-9vHuyKIhUPwfkcbkvRAb71AaIVE/s320/StrontiumAluminate.jpg"/></a></div>
<br/><br/>
Constater, c'est bien, mesurer, c'est mieux. Je dois avoir quelque part le capteur utilisé dans les <a href="http://unihedron.com/projects/darksky/">Sky Quality Meter</a> mais impossible de remettre la main dessus. J'ai donc commandé sur eBay quelque chose de plus ou moins équivanet, un <a href="https://www.sparkfun.com/datasheets/Sensors/TSL230R-LF-e3.pdf">TSL230R</a> qui convertit lui-aussi le flux lumineux en fréquence. Le premier composant avait 3 pattes, celui-ci 8 mais cela reste raisonnable et il suffit simplement de connecter toutes les pattes (sauf une) à VDD ou à la terre pour obtenir un signal plus ou moins carré en sortie. Je dis plus ou moins parce qu'en fait, ce n'est a priori pas très stable. Il y a, comme qui dirait, un 'jitter' important. Je ne sais pas si c'est dû à l'approximation de mon montage sur une plaquette d'expérimentation (breadboard), si c'est une propriété de ce composant en particulier ou à ce type de composant en général. D'abord observé à l'oscillo, j'ai bien un signal dont la fréquence varie avec le flux lumineux. Bien.
<br/><br/>
Maintenant, ce qui m'intéresse, c'est de voir comment cela évolue dans le temps.
Pour cela, j'ai utilisé un clone <a href="https://sigrok.org/wiki/Saleae_Logic">Saleae Logic</a> avec <a href="https://sigrok.org/wiki/PulseView">PulseView</a> de <a href="https://sigrok.org/wiki/Main_Page">sigrok</a> (ici, à la lumière du jour). Un petit bidule génial de quelques euros qui échantillonne jusqu'à 24 MHz. En fait, c'est juste un microcontrolleur Cypress EZ-USB FX2LP qui envoie l'état des portes sur l'USB.
<br/><br/>
Mais, pour pouvoir suivre l'évolution dans le temps, rien ne vaut la ligne de commande.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7lZ-_nGpscZAGjeVtOgFp4WTXK0h0XuPmufcuzwGcYLc9X7_HSUrqKfKlYo-uScK57EYJaGuiU5EiUptj6xoR2-9utJi6zyONGoHcfFYMUVthCmjsHqt9u5Pdd-AyXMYRvlUahvHSQg0/s1200/setup.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7lZ-_nGpscZAGjeVtOgFp4WTXK0h0XuPmufcuzwGcYLc9X7_HSUrqKfKlYo-uScK57EYJaGuiU5EiUptj6xoR2-9utJi6zyONGoHcfFYMUVthCmjsHqt9u5Pdd-AyXMYRvlUahvHSQg0/s320/setup.jpg"/></a></div>
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLK1-E35bVpgWiseKn5L1-yGXZDtinQQz51WxjbFoKBF_QHYD9xSXwM4vJOJAI3UfYSCEwSwWuAjJKgbBHxTXp06vWuOJVcpsNJvVB1G1jayh3FwCk4n2uZkT-YRFkrdIUpUGIPRhMeDc/s1046/sigrok.pulsview.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="768" data-original-width="1046" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLK1-E35bVpgWiseKn5L1-yGXZDtinQQz51WxjbFoKBF_QHYD9xSXwM4vJOJAI3UfYSCEwSwWuAjJKgbBHxTXp06vWuOJVcpsNJvVB1G1jayh3FwCk4n2uZkT-YRFkrdIUpUGIPRhMeDc/s320/sigrok.pulsview.png"/></a></div>
<br/><br/>
<pre>
while true
do
sigrok-cli --driver fx2lafw --samples 1m --config samplerate=1m --channels D0=x --output-format bits \
|./count01 > AlSr.`now`.txt; sleep 9; done
</pre>
<br/><br/>
À la lumière du jour, sigrok-cli donne :
<br/><br/>
<pre>
$ sigrok-cli --driver fx2lafw --samples 1m --config samplerate=1m --channels D0=x --output-format bits
libsigrok 0.5.0
Acquisition with 1/9 channels at 1 MHz
x:11100001 11111000 00011111 00000111 11000000 11110000 00111111 00001111
x:11000011 11110000 00111111 00001111 11000011 11110000 00111110 00001111
x:10000001 11110000 01111110 00001111 10000001 11100000 01111110 00011111
x:10000001 11100000 01111110 00011111 10000011 11110000 01111100 00001111
x:10000011 11110000 01111100 00001111 10000011 11110000 01111100 00001111
x:10000011 11110000 01111100 00001111 10000011 11110000 01111110 00001111
...
</pre>
On compte 5 '1' suivis de 5 '0'. Avec un millionième de seconde par échantillon, cela donne une période de 10 millionnième de seconde, soit une fréquence de 100 kHz.
<br/><br/>
Maintenant, plaçons le gravier sur le TSL230R, mettons le tout dans le noir le plus total (un couvercle noir sous un T-shirt noir) et observons l'évolution.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi9n1lJYXbqrLqKa2SZ0R6f29UAK7n9xgaYgEofG7FViA01LvQ9lJsS-ADRenewp0aHZ2AlHVIKD_3fqipwdh4hbuV2QHgsxHVOGLfg6aIh5vSnLc7pLxz8ACeCzE4EvLMESKsbnnT1VQ/s1200/glow.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi9n1lJYXbqrLqKa2SZ0R6f29UAK7n9xgaYgEofG7FViA01LvQ9lJsS-ADRenewp0aHZ2AlHVIKD_3fqipwdh4hbuV2QHgsxHVOGLfg6aIh5vSnLc7pLxz8ACeCzE4EvLMESKsbnnT1VQ/s320/glow.jpg"/></a></div>
Et nous obtenons, comme attendu, une belle décroissance exponentielle.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJJPVXgI-219AeSoQGsC4bjPqDKp_Njbm-z06G5mvblCXKfEkKC432UICgVNm4vtY3Z3WVNIUzNuVALoNwQDLiT7UNEeDX5VH6varb5528GVvenQpOSRLYAkG_vpqT-g_7j15-N1s7laY/s3547/evol.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="887" data-original-width="3547" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJJPVXgI-219AeSoQGsC4bjPqDKp_Njbm-z06G5mvblCXKfEkKC432UICgVNm4vtY3Z3WVNIUzNuVALoNwQDLiT7UNEeDX5VH6varb5528GVvenQpOSRLYAkG_vpqT-g_7j15-N1s7laY/s320/evol.png"/></a></div>
<br/><br/>
Ce qui est amusant, c'est ma configuration avec le petit programme 'count01' ne fonctionne plus quand la fréquence s'approche du herz. En fait, je demande au Cypress fx2lafw de me fournir un million d'échantillons de D0 à un million d'échantillons par seconde et 'count01' compte les nombres de '0' et de '1' consécutifs. Quand la fréquence approche du herz, il n'y a plus de transition '0' vers '1' et '1' vers '0' et je n'arrive donc plus à mesurer la demi-période. Cependant, dans le noir, on distingue encore une faible phosphorescence.
<br/><br/>
Il faudrait adapter le programme pour mesurer les (très) faibles intensités. Après tout, si ce genre de composant est capable de mesurer la noirceur d'un ciel astronomique, il doit toujours fonctionner bien en dessous du herz.
<br/><br/>
À noter que le temps de chargement ne semble pas affecter le temps de rémanence. 'core.freq' est obtenu après avoir éclairé le caillou pendant 10 secondes avec un lampe de poche LED pas très puissante. 'core2.freq', c'est environ une minute avec un spot LED beaucoup plus puissant. Le résultat semble quasi identique.
<br/><br/>
On trouve une thèse, <a href="https://tel.archives-ouvertes.fr/tel-00471254/document">Phosphorescence : mécanismes et nouveaux matériaux</a> de Frédéric Clabau (Nantes, 2005), sur ce type de matériau.
<br/><br/>
Ci-dessous, l'évolution sur plusieurs recharges. D'abord une dizaine de seconde sur le caillou qui a pris la lumière toute la journée. Une courte recharge de quelques secondes et une recharge de près d'une minute et une dizaine de seconde après une longue décharge d'environ 9 heures (5 heures retirées du graphe).
Chaque tic vaut 10 secondes.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzV58I4Vazl6uqyKGnzpvKeKSMD2YrxM_GRaHBFZPOXUMfRuoM_CT5C5kPN12AxcPhphNXIceuzB-fBqwpeg5U9UcfnqP16UFJzkTArYhtfzssdcIon3ECNbmfySy4Kbq-p9kKlEH3EVk/s1200/evol2.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="400" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzV58I4Vazl6uqyKGnzpvKeKSMD2YrxM_GRaHBFZPOXUMfRuoM_CT5C5kPN12AxcPhphNXIceuzB-fBqwpeg5U9UcfnqP16UFJzkTArYhtfzssdcIon3ECNbmfySy4Kbq-p9kKlEH3EVk/s320/evol2.png"/></a></div>
<br/><br/>
En principe, toutes les 10 secondes, on perd x % de luminosité. Comme la fréquence est proportionnelle au flux lumineux, f(t)/f(t-10sec) devrait être constant.
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeAAFvrddovpy6tnW5cqf0GS_uQbCNTeKXkPzrnRtkgc6w1h16gTcc_v28yWyTbadfHEui5KlaW2zVYsttzuCIo3acuUaXL_bBhePTDlEE_ssJBjJyjFa_AWLe2atyJbcHfr2hvFutC4E/s1200/decay.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="400" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeAAFvrddovpy6tnW5cqf0GS_uQbCNTeKXkPzrnRtkgc6w1h16gTcc_v28yWyTbadfHEui5KlaW2zVYsttzuCIo3acuUaXL_bBhePTDlEE_ssJBjJyjFa_AWLe2atyJbcHfr2hvFutC4E/s320/decay.png"/></a></div>
<br/><br/>
Et ce n'est pas tout-à-fait le cas... C'est dû au manque de stabilité du signal (dont j'ignore toujours la source) et à la méthode de mesure : je calcule la moyenne des périodes pendant une seconde toutes les 10 secondes. Au début, j'ai beaucoup de mesures courtes mais cela n'a pas beaucoup de sens de calculer une moyenne sur une exponentielle et à la fin, je n'ai plus assez de mesures pour pouvoir faire une moyenne convenable et la dispersion correspond à l'instabilité du signal... Je viens de commander un <a href="https://www.adafruit.com/product/1980">Adafruit TSL2591</a>, ce sera peut-être meilleur...
<br/><br/>
À suivre...xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.comtag:blogger.com,1999:blog-4811625769590798586.post-2535747093499729162021-05-18T18:52:00.003+02:002021-05-23T16:21:01.255+02:00Portapack GNU OctaveLe <a href="https://www.sharebrained.com/">Portapack</a> permet d'enregistrer un signal radio capté par un <a href="https://en.wikipedia.org/wiki/HackRF_One">HackRF One</a> sur une carte micro-SD sans trimbaler un PC portable. En fait, j'ai un clone -H2 avec le logiciel <a href="https://github.com/eried/portapack-mayhem">Mayhem</a>.
<a href="https://en.wikipedia.org/wiki/GNU_Octave">Gnu Octave</a> permet de traiter le signal sans trop d'effort (logiciel libre quasi compatible avec MATLAB). En fait, ici, je joue plus avec le signal que je le traite mais bon...
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLFXaS_UbVEyJNu8wc4dUUZH1-rUXpMgFc4bxasx1K1SVQhIKvxZIL2o2BDhZCYx7UrtSLCgFtegsUwYkfVf47BeZ0vPRyOFyGaMKGM43vPw1Vh0zN2vm4NJfGfl1HwStWWrfRutn6wEw/s320/SCR_0008.PNG" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="320" data-original-width="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLFXaS_UbVEyJNu8wc4dUUZH1-rUXpMgFc4bxasx1K1SVQhIKvxZIL2o2BDhZCYx7UrtSLCgFtegsUwYkfVf47BeZ0vPRyOFyGaMKGM43vPw1Vh0zN2vm4NJfGfl1HwStWWrfRutn6wEw/s320/SCR_0008.PNG"/></a></div>
Pas sûr que le screenshot corresponde au signal traité ci-dessous, mais c'est l'idée. L'écran permet de repérer un signal qui semble intéressant, les boutons permettent la configuration de la réception et de lancer/stopper l'enregistrement sur la carte micro-SD.
<br/>
En fait, le signal capté semble être quelque chose comme du <a href="https://en.wikipedia.org/wiki/Digital_private_mobile_radio">dPMR</a> (?). À mon souvenir, il était plus 'propre' et je ne suis même pas sûr que le filtre était indispensable.
<pre>
$ dd if=BBD_0001.C16 of=_1.c16 bs=1M count=1
</pre>
Histoire d'avoir un fichier de taille raisonnable (à 500ksamples/sec, cela fait 2MB/sec). On peut ensuite charger le fichier composé alternativement de I et de Q 16 bits signés dans un vecteur de nombres complexes en virgule flottante.
<pre>
function y = loadC16File(filename)
% y = loadC16File(filename)
%
% reads complex samples from the portapack file
%
fid = fopen(filename,'rb');
y = fread(fid,'int16=>double');
y = y(1:2:end) + i*y(2:2:end);
</pre>
Ensuite, traiter le signal... Dans ce cas-ci, le filtre est trop large, la bande passante du signal est beaucoup plus étroite mais cela permet déjà d'y voir plus clair.
<pre>
x0=loadC16File("_1.c16");
Ts=1/500000;
freqs=[0 0.2 0.21 1];
amps=[1 1 0 0];
b=remez(100, freqs, amps);
x=filter(b, 1, x0);
a=abs(x);
p=arg(x);
pp=unwrap(p);
fig=figure();
subplot(2,1,1);
plot(a);
title("abs(x) - magnitude");
subplot(2,1,2);
plot(pp);
title("unwrap(arg(x)) - argument/phase");
print(fig, "plot011.png", "-S800,800");
return;
</pre>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBDi8kb_WZn1H4RvVuGVLITmBJJCNXBP8CgpAfWjDTm9M8DfGTTieuXDXiyvEslnBQ_UoHSMZlQQOeVccvyCIwVu-h35MbCXARSMZmIKAwJrMf-LlU04nYuaU-GDsqxj51Pj-4xsnPGDM/s800/plot011.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="800" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBDi8kb_WZn1H4RvVuGVLITmBJJCNXBP8CgpAfWjDTm9M8DfGTTieuXDXiyvEslnBQ_UoHSMZlQQOeVccvyCIwVu-h35MbCXARSMZmIKAwJrMf-LlU04nYuaU-GDsqxj51Pj-4xsnPGDM/s320/plot011.png"/></a></div>
On prend une partie utile du signal (entre 5001 et 24500), on corrige légèrement la fréquence : ajout de 50 pi-radians sur 20000 échantillons pour redresser le graphe (je l'avais fait manuellement an ajoutant un linspace(), mais detrend() est fait pour cela) et on obtient :
<pre>
ppp=pp(5001:24500);
pppdt = detrend(ppp,1);
fig=figure();
plot(pppdt);
axis([0 1 -50 50], "autox");
title("detrend(unwrap(arg(filter(x)))(5001:24500))");
print(fig, "coresigdt.png", "-dpng", "-S1280,360");
</pre>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZet8yLY4cy0VkiAbeTpZbPTGXTigFvlv49_O12GXY9e43m5eCy7LIPdcjIbkI-h2ukQsV-F-zD0Oki3jaI9jCQXcoLKB-zwVLDnsVMvHVB9dhXUMzftpc9wWSjdHwYnhgP-0Jm_jx-EQ/s1280/coresigdt.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="360" data-original-width="1280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZet8yLY4cy0VkiAbeTpZbPTGXTigFvlv49_O12GXY9e43m5eCy7LIPdcjIbkI-h2ukQsV-F-zD0Oki3jaI9jCQXcoLKB-zwVLDnsVMvHVB9dhXUMzftpc9wWSjdHwYnhgP-0Jm_jx-EQ/s320/coresigdt.png"/></a></div>
Tadaah... Il ne reste plus qu'à traduire ça en bits et bytes... (hum...; Ce n'est pas vraiment comme ça qu'il faut faire, mais bon...)xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-7432236834938018162021-02-12T18:26:00.003+01:002022-06-20T11:27:25.789+02:00MysondyGOChaque jours des <a href="https://fr.wikipedia.org/wiki/Ballon-sonde">ballons-sondes</a> sont lancés un peu partout dans le monde (en principe à midi/minuit). Ils émettent de la télémétrie que l'on peut capter. Ayant vu <a href="https://www.rtl-sdr.com/andreas-spiess-tracks-weather-balloons-with-a-ttgo-lora-board-and-rtl-sdr/">une vidéo</a> de <a href="https://www.youtube.com/channel/UCu7_D0o48KbfhpEohoP7YSQ">Andreas Spiess</a>, je n'ai pas pu résister à l'achat d'un récepteur TTGO pour lequels des radioamateurs italiens ont réalisé un logiciel de réception (<a href="http://mysondy.altervista.org/mysondygo.php">mysondyGO</a>). Sur AliExpress, c'était un '<a href="https://www.aliexpress.com/item/32915894264.html">LILYGO® TTGO ESP32-Paxcounter LoRa32 V2.1 1.6 Version 433/868/915MHZ LoRa ESP-32 OLED 0.96 Inch SD Card Bluetooth WIFI Module</a>' pour une petite vingtaine d'euros (si je me souviens bien.
<br/><br/>
J'ai dû un peu chercher avant de trouver le moyen facile de flasher le logiciel italien. Je ne trouvais que des SDK de développement complexes pour ESP-32 alors que je voulais juste flasher un .bin. Et j'ai finalement trouvé exactement ce qu'il me fallait dans <a href="http://www.f5kee.fr/MySondyGo/radioref_2020_07-08-01.pdf">cet article</a> de Anthony Le Cren F4GOH – KB1GOH.
<br/>
<pre>
2024 ls -l ./MySondyGO_1_40/MySondyGO.bin
2025 ls -l
2026 git clone https://github.com/espressif/esptool.git
2027 cd esptool/
2028 ls -l
2029 ./esptool.py
2030 ./esptool.py --port /dev/ttyUSB0 read_flash_status
2031 ./esptool.py --port /dev/ttyUSB0 erase_flash
2032 ./esptool.py --port /dev/ttyUSB0 write_flash -z 0x0000 ../MySondyGO_1_40/MySondyGO.bin
</pre>
<br/><br/>
Ne restait plus qu'à guêter sur <a href="https://s1.radiosondy.info/">radiosondy.info</a> le passage d'un ballon dans le coin... C'est ennuyeux que le bidule ne semble configurable qu'en BlueTooth avec un smartphone mais bon... Je le configure sur une sonde RS41 sur 403.5 MHz comme celles qui sont lancées vers midi à l'<a href="https://fr.wikipedia.org/wiki/Observatoire_royal_de_Belgique">observatoire de Uccle</a>.
<br/><br/>
Comme l'antenne d'origine, mesurée avec <a href="https://github.com/ttrftech/NanoVNA">nanoVNA</a> clone, ne me paraîssait pas trop bonne, j'ai bricolé un dipôle coupé pour 403.5 Mhz et ça y est, aujourd'hui, un ballon est passé dans les parages.
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPwI_Hk74GIQv8JMGwjHgQ6V-zQxzi84Da3kFSK9ssXRtjfDfcw5HTBxsT895uNCBMhtx8iwO1xlLfVw5bUTPYjcNTQTo9JvJCtVeJ26zkSZ9W_sNYdp6SJ6UjM-XubkgiSWInmRQoe_4/s1578/radiosondy.20210212-1.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="618" data-original-width="1578" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPwI_Hk74GIQv8JMGwjHgQ6V-zQxzi84Da3kFSK9ssXRtjfDfcw5HTBxsT895uNCBMhtx8iwO1xlLfVw5bUTPYjcNTQTo9JvJCtVeJ26zkSZ9W_sNYdp6SJ6UjM-XubkgiSWInmRQoe_4/s320/radiosondy.20210212-1.jpg"/></a></div>
<br/>
Dans une rue est-ouest, j'ai bien capté le ballon du côté sud.
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNGFau8PgfHjONRoYcvuzL3vutKIvev0b-ckLAImANVRA7J5xOSisReXA_cqV7UU-DSdL7tECBHJ_Omzu9KnjpOKIuN3ChSXwdixU3AYkMH56NoZ_jO1w4Tb9mbFcfGyZdXll6oKH-My8/s1200/R3420743-20210212.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNGFau8PgfHjONRoYcvuzL3vutKIvev0b-ckLAImANVRA7J5xOSisReXA_cqV7UU-DSdL7tECBHJ_Omzu9KnjpOKIuN3ChSXwdixU3AYkMH56NoZ_jO1w4Tb9mbFcfGyZdXll6oKH-My8/s320/R3420743-20210212.jpg"/></a></div>
<br/>
R3420743 a été suivie sur Radiosondy et on peut retrouver la télémétrie captée <a href="https://s1.radiosondy.info/sonde_archive.php?sondenumber=R3420743">ici</a>. À l'heure de la photo, elle était à environ 25 kilomètres et 28.002 mètres d'altitude. Elle a été retrouvée du côté de Malmedy.
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9-vlEkBePUW6RGgORTaHb2_HycN67XnFqIzyLOGDVPZui2W9aeT4wITAf2TIzElbxrf-QXrVzUKWEXK4tG9ZoMT8mxAsTxfVJ-aqFzn9riMa-tySAqwQeRXGN_5jeHX_VuvX5wO0dMMA/s1200/R3420743-dipole-20210212.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="1200" data-original-width="900" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9-vlEkBePUW6RGgORTaHb2_HycN67XnFqIzyLOGDVPZui2W9aeT4wITAf2TIzElbxrf-QXrVzUKWEXK4tG9ZoMT8mxAsTxfVJ-aqFzn9riMa-tySAqwQeRXGN_5jeHX_VuvX5wO0dMMA/s320/R3420743-dipole-20210212.jpg"/></a></div>
<br/><br/>
La prochaine fois, il faudra essayer de la capter avec un RTL-SDR. Éventuellement avec <a href="https://www.rtl-sdr.com/tutorial-on-using-rs-to-decode-and-plot-radiosondes/">RS</a> ou, essayer d'extraire les messages moi-même (avec ou sans <a href="https://en.wikipedia.org/wiki/GNU_Radio">GNUradio</a>), c'est du <a href="https://en.wikipedia.org/wiki/Frequency-shift_keying">BFSK</a>; cela ne devrait pas être trop sorcier (?).
<br/><br/>
Quelqu'un m'a invité à remplacer le lien <a href="https://www.nanovna.com">nanovna.com</a> (qui vendrait des clones de mauvaise qualité) par <a href="https://nanorfe.com/nanovna-v2.html">nanorfe.com</a> qui vend une version V2, utiliserait des composants de meilleure qualité et serait plus 'officiel'. Il existe donc une controverse... Là, j'ai utilisé un clone V1, je ne sais pas d'où il vient ni quelle est sa qualité.
<br/><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-20016791116803587732020-12-13T11:01:00.003+01:002020-12-14T17:19:07.037+01:00TinySAUn petit 'spectrum analyser' étonant, le <a href="https://www.tinysa.org/wiki/">tinySA</a>. Une cinquantaine d'euros, il permet de se faire une idée du spectre électromagnétique jusqu'à 960 MHz.
<br/><br>
Une première captation autour de 162 MHz, avec l'option 'Max hold', où l'on voit les deux canaux de l'<a href="https://fr.wikipedia.org/wiki/Syst%C3%A8me_d%27identification_automatique">AIS</a> à 161.975 et 162.025 MHz. C'est capté du côté de la Citadelle de Liège et c'est émis par des bateaux, en contrebas sur la Meuse. Il faut noter que le scan sur 100 kHz dure 514 mS et que donc, on loupe des paquets. Ceux-ci, émis à 9600 bauds ne font que 168 ou 440 bits et ne sont donc présent que 20 ou 40 mS. Il arrive aussi que le TinySA ne voie que le début ou la fin du paquet et on n'a donc qu'une partie du spectre. La partie qu'il était en train de scanner pendant sa transmission. D'où l'utilisation de 'Max hold' pour cumuler les spectre.
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHha6JlZh-6WQFMcNjlcxzyUR-jcV-MFZE_UtbWEKBB2shZ_zs8-hSqhyphenhyphenjO9CDdAvuht4YpOnh6HPWsJpNx-1r6Py8KFgSpWa4NVUYdfw-o3AwQz2cBbpHf35XtxU_t0KrBzJ5kaCs0Is/s1200/TinySA-AIS-20201129.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="900" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHha6JlZh-6WQFMcNjlcxzyUR-jcV-MFZE_UtbWEKBB2shZ_zs8-hSqhyphenhyphenjO9CDdAvuht4YpOnh6HPWsJpNx-1r6Py8KFgSpWa4NVUYdfw-o3AwQz2cBbpHf35XtxU_t0KrBzJ5kaCs0Is/s320/TinySA-AIS-20201129.jpg"/></a></div>
<br/><br/>
Spectre UHF, jusqu'à 500 MHz, du côté de la Place Saint-Lambert à Liège. Pas de 'Max hold' ici, pour différencier les émissions continues des émissions par paquets.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrL6QtMwYtthyphenhyphendEZLQI8fixs1TQg59ZQ4bjIIuymj9U0gEL8AVjl-1GrVOWOTBTYOhIH4lUtVaVXDz3JAN40PDjJDddeJD1m647pRhO-zbxguuQCd4bE_j1k2PjUgEp5lsKOM68KRz3UQ/s800/TinySA-SaintLambert-240.500.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="600" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrL6QtMwYtthyphenhyphendEZLQI8fixs1TQg59ZQ4bjIIuymj9U0gEL8AVjl-1GrVOWOTBTYOhIH4lUtVaVXDz3JAN40PDjJDddeJD1m647pRhO-zbxguuQCd4bE_j1k2PjUgEp5lsKOM68KRz3UQ/s320/TinySA-SaintLambert-240.500.jpg"/></a></div>
<br/><br/>
En allant jusqu'à 960MHz, on voit des bandes GSM (?).
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJS3QgD03vJnQxTYYDX-FirdYutBNbgHHS0i7Kov5tPAz5BS2TiEPIGiEeU9gmYUl8-RBbux24PpOPaPGcbyjZrxM18lU35uZHgM9VBA7dMsjhq9Bhgdzn4p8YdX2R7rtvC8Mehg7mgfA/s800/TinySA-SaintLambert-700.960.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="600" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJS3QgD03vJnQxTYYDX-FirdYutBNbgHHS0i7Kov5tPAz5BS2TiEPIGiEeU9gmYUl8-RBbux24PpOPaPGcbyjZrxM18lU35uZHgM9VBA7dMsjhq9Bhgdzn4p8YdX2R7rtvC8Mehg7mgfA/s320/TinySA-SaintLambert-700.960.jpg"/></a></div>
<br/><br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUoWwX1yFasT1reB-LAuDXJ7vOwiSOBsGD-J83sLDL6Pz-hsKjcGCZOKT-4kQWLSnMfnE8e5kG5zSQOmCDxBjTw-ta2gw_AblCBxoelc1i5mYgOGSEsbIQ7qLu4I0FlGhn_WIiX12Aotw/s800/TinySA-SaintLambert-920.960.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="600" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUoWwX1yFasT1reB-LAuDXJ7vOwiSOBsGD-J83sLDL6Pz-hsKjcGCZOKT-4kQWLSnMfnE8e5kG5zSQOmCDxBjTw-ta2gw_AblCBxoelc1i5mYgOGSEsbIQ7qLu4I0FlGhn_WIiX12Aotw/s320/TinySA-SaintLambert-920.960.jpg"/></a></div>
<br/><br/>
Bizarre, bizarre, le <a href="https://www.ibpt.be/operateurs/plan-des-frequences">plan des fréquences</a> de l'<a href="https://fr.wikipedia.org/wiki/Institut_belge_des_services_postaux_et_des_t%C3%A9l%C3%A9communications">IBPT</a> ne semble pas aider beaucoup à l'identification des signaux.
<br/><br/>
Un bout de la bande FM avec 'Max hold'. Le petit pic à droite du curseur est Bel-RTL sur 103.6.
<br/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguWIyAoSGRGoVFhZV-T4D6xFpxrxo4EXliQxLjfl6r0no3Pz5e4ZzpdK3N4AfleJSjdzlDKx_ctDgEIZDJSF9wqS8uj1TUCIOC17Ygcz0sRqnJ17tjmXO_xSuj3jHagSxuITL3Zks7trU/s800/fm-lg-20201213.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="600" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguWIyAoSGRGoVFhZV-T4D6xFpxrxo4EXliQxLjfl6r0no3Pz5e4ZzpdK3N4AfleJSjdzlDKx_ctDgEIZDJSF9wqS8uj1TUCIOC17Ygcz0sRqnJ17tjmXO_xSuj3jHagSxuITL3Zks7trU/s320/fm-lg-20201213.jpg"/></a></div>
<br/><br/>
Sur Linux,
<pre>
$ sudo minicom -D /dev/ttyACM0 -b 115200
ch> help
Commands: version reset freq dac saveconfig clearconfig data frequencies scan scanraw sweep test touchcal
touchtest pause resume caloutput save recall trace trigger marker usart capture vbat vbat_offset help info
color if attenuate level sweeptime leveloffset levelchange modulation rbw mode spur load offset output
deviceid selftest correction threads
</pre>
permet de contrôler le <a href="https://tinysa.org/wiki/pmwiki.php?n=Main.USBInterface">TinySA en mode terminal</a>
<br/><br/>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-34740489596180512332020-06-01T10:30:00.001+02:002020-06-01T16:10:51.776+02:00Simple ad hoc SNMPSNMP est l'acronyme de '<a href="https://fr.wikipedia.org/wiki/Simple_Network_Management_Protocol">Simple Network Management Protocol</a>' et, comme tout ce qui est simple, cela fini par devenir compliqué...
<br/><br/>
Ci-dessous un petit programme en '<a href="https://fr.wikipedia.org/wiki/C_(langage)">C</a>', utilisant la librairie <a href="https://fr.wikipedia.org/wiki/Net-SNMP">Net-snmp</a> pour extraire quelques valeurs de la <a href="http://oidref.com/1.3.6.1.4.1.2021.9.1">dskTable</a> en SNMP version 2c.
<br/><br/>
Le programme fait une peu plus d'une centaine de lignes. On passe en paramètre la cible, la 'community string' et un index. Une session est ouverte vers la machine cible avec sa 'community string', un <a href="https://fr.wikipedia.org/wiki/Protocol_Data_Unit">PDU</a> est construit pour interroger 4 variables. Les 4 OIDs sont construites à partir de l'<a href="https://fr.wikipedia.org/wiki/OID">OID</a> de base et un index passé en paramètre au programme. Le programme envoie la requête et reçoit la réponse. On suppose que la réponse reflète la requête et que l'on reçoit, dans l'ordre, les chaînes de caractères dskPath, dskDevice et les entiers dskUsed et dskTotal. Il ne reste plus qu'à les imprimer. Tous les problèmes possibles ne sont pas traités en profondeur mais il y a quand même un minimum de 'sanity checks'.
<br/><br/>
<pre>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#define DSK_PATH 2
#define DSK_DEVICE 3
#define DSK_TOTAL 6
#define DSK_USED 8
unsigned char oid_str[128];
char *oid_template = ".1.3.6.1.4.1.2021.9.1.%d.%d"; /* What, idx */
void build_part_req(netsnmp_pdu *pdu, int idx, int what)
{
oid oid_buf[128];
size_t oid_len;
sprintf(oid_str, oid_template, what, idx);
if (!snmp_parse_oid(oid_str, oid_buf, &oid_len))
{
fprintf(stderr, "error snmp_parse_oid()\n");
exit(-1);
}
snmp_add_null_var(pdu, oid_buf, oid_len);
}
netsnmp_pdu *build_req(int idx)
{
netsnmp_pdu *pdu;
pdu = snmp_pdu_create(SNMP_MSG_GET);
build_part_req(pdu, idx, DSK_PATH);
build_part_req(pdu, idx, DSK_DEVICE);
build_part_req(pdu, idx, DSK_USED);
build_part_req(pdu, idx, DSK_TOTAL);
return(pdu);
}
void use_it(struct snmp_pdu *response)
{
char buf[1024];
struct variable_list *vp;
char dskPath[1024];
char dskDevice[1024];
long dskUsed;
long dskTotal;
if (response->errstat == SNMP_ERR_NOERROR)
{ /* vp->type (4=str; 2=int), vp->val.string, *vp->val.integer ; snprint_variable(), snprint_value() */
vp = response->variables;
strcpy(dskPath, vp->val.string); /* DSK_PATH */
vp = vp->next_variable;
strcpy(dskDevice, vp->val.string); /* DSK_DEVICE */
vp = vp->next_variable;
dskUsed = *vp->val.integer; /* DSK_USED */
vp = vp->next_variable;
dskTotal = *vp->val.integer; /* DSK_TOTAL */
printf("%ld/%ld for %s on %s\n", dskUsed, dskTotal, dskPath, dskDevice);
}
else {
printf("Uhm... : response->errstat = 0x%lx\n", response->errstat);
}
}
struct snmp_session *open_session(char *host, char *community)
{
struct snmp_session ss, *sp;
init_snmp("get_snmp_fs");
snmp_sess_init(&ss);
ss.version = SNMP_VERSION_2c;
ss.peername = strdup(host);
ss.community = strdup(community);
ss.community_len = strlen(community);
if ((sp = snmp_open(&ss)) == NULL)
{
snmp_perror("snmp_open");
exit(-1);
}
return(sp);
}
void main (int argc, char **argv)
{
struct snmp_session *sp;
netsnmp_pdu *req, *resp;
char *host, *community;
int index, status;
if (argc != 4)
{
fprintf(stderr, "usage is '%s <host> <community> <index>\n", argv[0]);
exit(-1);
}
host = argv[1];
community = argv[2];
index = atoi(argv[3]);
sp = open_session(host, community);
req = build_req(index);
if ((status = snmp_synch_response(sp, req, &resp)) == STAT_SUCCESS)
use_it(resp);
else fprintf(stderr, "snmp_synch_response() returns %d\n", status);
snmp_free_pdu(resp);
snmp_close(sp);
exit(0);
}
</pre>
<br/><br/>
Le Makefile, lui aussi, réduit à sa plus simple expression est :
<br/><br/>
<pre>
CFLAGS=-I. `net-snmp-config --cflags`
BUILDLIBS=`net-snmp-config --libs`
get_snmp_fs: get_snmp_fs.o
gcc -o get_snmp_fs get_snmp_fs.o $(BUILDLIBS)</pre>
<br/><br/>
<br/><br/>
<h1>Et maintenant, le test...</h1>
<br/><br>
On regarde d'abord un disque avec df(1). On retrouve son indice en faisant un snmpwalk(1). On peut retrouver plusieurs valeurs avec snmpget(1) et les comparer avec ce que le programme ci-dessus donne.
<br/><br>
<pre>
$ df -h |grep sda1
/dev/sda1 916G 159G 711G 19% /
$ snmpwalk localhost -Os -m /usr/share/snmp/mibs/UCD-SNMP-MIB.txt -v 2c -c public dskPath
dskPath.1 = STRING: /
dskPath.2 = STRING: /var
dskPath.3 = STRING: /
dskPath.4 = STRING: /run
dskPath.5 = STRING: /dev/shm
dskPath.6 = STRING: /run/lock
dskPath.7 = STRING: /sys/fs/cgroup
$ snmpget localhost -Os -m /usr/share/snmp/mibs/UCD-SNMP-MIB.txt -v 2c -c public dskPath.1 dskDevice.1 dskUsed.1 dskTotal.1
dskPath.1 = STRING: /
dskDevice.1 = STRING: /dev/sda1
dskUsed.1 = INTEGER: 166654692
dskTotal.1 = INTEGER: 960379920
$ ./get_snmp_fs localhost public 1
166654708/960379920 for / on /dev/sda1
</pre>
<br/><br/>
Les machines actuelles sont tellement rapides qu'il est difficile de mesurer la différence entre un programme ne faisant qu'un échange de PDUs et un programme qui doit, en plus, analyser une MIB (sinon plusieurs)... J'avais été motivé par le fait que Nagios utilise souvent des scripts shell lançant des tas de processus pour exécuter des fonctions élémentaires.xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-49828288352093099952020-04-17T06:11:00.002+02:002020-04-17T20:58:52.234+02:00De grand matin...<a href="https://www.flightradar24.com/data/airports/lgg/departures">Activité aéroportuaire</a>, ce jeudi 16 avril 2020, entre 04h13 et 05h13 captée avec un stick RTL-SDR (NewGen/RTL2832SDR alu TCXO .5 ppm) et <a href="https://github.com/antirez/dump1090">dump1090</a> de la <a href="http://wikimapia.org/#lang=en&lat=50.650022&lon=5.577182&z=18&m=o">Citadelle de Liège</a>... De la Citadelle de Liège, on capte l'<a href="https://fr.wikipedia.org/wiki/Automatic_dependent_surveillance-broadcast">ADS-B</a> jusque Nancy.
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC00twNqJXQ4vbYj63gnM8DV3oukREQ3zogs8RKAJz8HRAQbvDITETton1V1gqGzENmqASyN4E9EN84CPgE2uBK9X6Ve8FO2KTC_0QevZrBELzJB38RvMiVj-FGSiDUKHsc0vw83lw1ME/s1600/lgg-20200416.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC00twNqJXQ4vbYj63gnM8DV3oukREQ3zogs8RKAJz8HRAQbvDITETton1V1gqGzENmqASyN4E9EN84CPgE2uBK9X6Ve8FO2KTC_0QevZrBELzJB38RvMiVj-FGSiDUKHsc0vw83lw1ME/s320/lgg-20200416.png" width="320" height="180" data-original-width="1600" data-original-height="900" /></a></div>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-26683915261766732622020-01-02T18:11:00.000+01:002020-02-08T16:11:20.134+01:00SigInt ISM433Petite captation sur la bande ISM 433 MHz avec un stick RTL-SDR v3, centrée sur 433.500 MHz avec 2048000 échantillons par seconde.<br/><br/>En regardant avec <a href="https://github.com/f4exb/sdrangel">SDRAngel</a> (ou sdrangelove)
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZlOf3tGHzWpyP3ONRwHYb4FZTmtiT8kM5Z2O7X3C5hyphenhyphen84S4cdQBa87PW7nqT0BvMRN3l_qbS3P5-K1H8NbHUFjkvkV3vavsYtZtzv8ecZtiAg6WKjOCIAGGsrnB8dN1Ipks6iOvLkglM/s1600/sdrangel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZlOf3tGHzWpyP3ONRwHYb4FZTmtiT8kM5Z2O7X3C5hyphenhyphen84S4cdQBa87PW7nqT0BvMRN3l_qbS3P5-K1H8NbHUFjkvkV3vavsYtZtzv8ecZtiAg6WKjOCIAGGsrnB8dN1Ipks6iOvLkglM/s320/sdrangel.jpg" width="320" height="180" data-original-width="1200" data-original-height="675" /></a></div>
En regardant avec gnuradio, on remarque de courtes trames centrées vers 433.922 MHz.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSP5inK8eiW2V7pA2Id7_ibgYqJIwxGzmB-qpp3bMSvOGUzToztom1ix6qi1ZffwoaIs8wF8we_hlkpK2gFewuz2OzfCB6FA6NHmHgMjW4VlSfCXThgChFyVnkHkWZL_Ma9QzyBzyckHc/s1600/grc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSP5inK8eiW2V7pA2Id7_ibgYqJIwxGzmB-qpp3bMSvOGUzToztom1ix6qi1ZffwoaIs8wF8we_hlkpK2gFewuz2OzfCB6FA6NHmHgMjW4VlSfCXThgChFyVnkHkWZL_Ma9QzyBzyckHc/s320/grc.jpg" width="320" height="90" data-original-width="1200" data-original-height="336" /></a></div>
En important les données dans <a href="https://www.gnu.org/software/octave/">GNUoctave</a> et en s'intéressant à la magnitude du signal, on observe :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgawgA1F-I-JI2Imu3Vg9Ojk3IOtwsNmMucm6hgaRtfNZDhBujDRsr2p6Oc15bPvRoFRHEZOi3cjDGo1QpACl8fRcmMjSusBHeTAGrEW_ecbzde2NfrT9Nqnh7lucJtjdUCkJJh5DWjWFQ/s1600/octave-mag.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgawgA1F-I-JI2Imu3Vg9Ojk3IOtwsNmMucm6hgaRtfNZDhBujDRsr2p6Oc15bPvRoFRHEZOi3cjDGo1QpACl8fRcmMjSusBHeTAGrEW_ecbzde2NfrT9Nqnh7lucJtjdUCkJJh5DWjWFQ/s320/octave-mag.png" width="320" height="104" data-original-width="1223" data-original-height="396" /></a></div>
En regardant de plus près, cela ressemble à du codage Manchester modulé en amplitude (ASK/OOK). Ce qui ne semble pas très économe en bande passante(?).
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh7AfRIR40K1Ad8tk9RQmIGj3irnc7aoBsfDidBSP9Wrawxivb4nLI_rEvX1C-mWQLwmikO348KkhalvcBDByQjWdzYRCKfSkAiqjajZ7fMpUS-EPkqjnGIZwaOTm-7FBKskLsA1ltORI/s1600/octave-mag-zoom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh7AfRIR40K1Ad8tk9RQmIGj3irnc7aoBsfDidBSP9Wrawxivb4nLI_rEvX1C-mWQLwmikO348KkhalvcBDByQjWdzYRCKfSkAiqjajZ7fMpUS-EPkqjnGIZwaOTm-7FBKskLsA1ltORI/s320/octave-mag-zoom.png" width="320" height="120" data-original-width="1061" data-original-height="399" /></a></div>
En s'intéressant à quelques bits seulement, on devrait pouvoir déduire le 'baud rate'...
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj67W7GzpJknPTgsy1PuHRcJyyxTfTeIv2JYkp7z6uak9psjNj-WPvllm9FbN2nsJs89_AlK7a77s7zwngh8OK7Um8B0V4tz5J9Nkk1AsiPoJQGd3HdHuaxFuPdgXqkmoHNJ3VItHMDq8E/s1600/octave-mag-zoom2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj67W7GzpJknPTgsy1PuHRcJyyxTfTeIv2JYkp7z6uak9psjNj-WPvllm9FbN2nsJs89_AlK7a77s7zwngh8OK7Um8B0V4tz5J9Nkk1AsiPoJQGd3HdHuaxFuPdgXqkmoHNJ3VItHMDq8E/s320/octave-mag-zoom2.png" width="320" height="106" data-original-width="1230" data-original-height="407" /></a></div>
En principe, on a tout pour créer un système pour décoder les trames avec <a href="https://wiki.gnuradio.org/index.php/GNURadioCompanion">gnuradio-companion</a>...
<br/><br/>
<h1>Avec <a href="https://gnuradio.org">GnuRadio</a></h1>
(je ne maîtrise pas GnuRadio...) La première chose à faire est d'isoler le signal intéressant avec le '<a href="https://wiki.gnuradio.org/index.php/Frequency_Xlating_FIR_Filter">Frequency Xlating FIR filter</a> bloc'.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT72P4PHtcaxUNBP-5QdLR866TmVq9OeH7qkAwmunUR8FQqeP5MZRdZa5v6wSz_XAD5_EYsNfz5ie-Uv_gSXgabVDeeSZ3IW06MDH5PFS_Cef92G6rVv7enhnm-5QPuVnZQzlhNqCYHCc/s1600/freq_xlating_fir_filter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT72P4PHtcaxUNBP-5QdLR866TmVq9OeH7qkAwmunUR8FQqeP5MZRdZa5v6wSz_XAD5_EYsNfz5ie-Uv_gSXgabVDeeSZ3IW06MDH5PFS_Cef92G6rVv7enhnm-5QPuVnZQzlhNqCYHCc/s320/freq_xlating_fir_filter.png" width="320" height="110" data-original-width="721" data-original-height="247" /></a></div>
En envoyant ça dans '<a href="https://wiki.gnuradio.org/index.php/Complex_to_Mag">Complex to Mag</a>', puis dans un fichier qu'on analyse avec Octave, on obtient :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe9MchGhWIM6-pK3RuTTzuJqlUdfbcyvh8QZSMh0QHs09pblrDdrn43_F89Cc-k3qknwJ2TkTHmK_AvEDaZXD-gGscLNCFyhlgfU-6ozO9yvtU0MqDowIMp92aJSf6foURGYeQA4qtsJA/s1600/ask.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe9MchGhWIM6-pK3RuTTzuJqlUdfbcyvh8QZSMh0QHs09pblrDdrn43_F89Cc-k3qknwJ2TkTHmK_AvEDaZXD-gGscLNCFyhlgfU-6ozO9yvtU0MqDowIMp92aJSf6foURGYeQA4qtsJA/s320/ask.png" width="320" height="109" data-original-width="1164" data-original-height="397" /></a></div>
<br/><br/>
<h1>Autre signal, un FSK très soutenu</h1>
Si on s'intéresse au signal en FSK un peu à gauche, avec le bloc, '<a href="https://wiki.gnuradio.org/index.php/Quadrature_Demod">Quadrature demod</a>', le signal ressemble à :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixmnMatikhnhdx-v5pMP_fL0f8T6gluj2Tuglb1d-t3imF59g7NNJCuxEqHYiqbUP-hUcU1yHb12Z4Qp2IFAjd0SUYZ-VHqeXPKjQvsBVEPIuymIYsZ1RglWYwjxi7GXWOJCwXQhT7DhA/s1600/fsk.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixmnMatikhnhdx-v5pMP_fL0f8T6gluj2Tuglb1d-t3imF59g7NNJCuxEqHYiqbUP-hUcU1yHb12Z4Qp2IFAjd0SUYZ-VHqeXPKjQvsBVEPIuymIYsZ1RglWYwjxi7GXWOJCwXQhT7DhA/s320/fsk.png" width="320" height="108" data-original-width="1192" data-original-height="402" /></a></div>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-23700664319335929192019-12-01T06:39:00.002+01:002019-12-08T16:36:43.907+01:00BeSt - XSLT - mySQLIl est possible de télécharger des listes de rues et de communes belges sur le <a href="https://opendata.bosa.be/index.fr.html">site Open Data</a> de BoSa (SPF Stratégie et Appui) : <a href="https://opendata.bosa.be/download/best/best-full-latest.zip">best-full-latest.zip</a> (BeSt = Belgian Street).
<br/><br/>
Ce .zip contient des fichiers XML avec diverses informations concernant les rues et les communes de Belgique. C'est la référence officielle. Ces données sont aussi accessibles via un webservice (REST).
<br/><br/>
En ne prenant que la Wallonie, on a un peu plus que 61.000 rues et 263 communes. Ce qui va permettre de jouer un peu avec SQL.
<br/>
J'ignore quelle est la meilleure manière d'injecter ces données XML dans une base de données mySQL. Alors, je le fais à ma manière... J'utilise un fichier de <a href="https://fr.wikipedia.org/wiki/Extensible_Stylesheet_Language_Transformations">transformation XSL</a> pour extraire les données qui m'intéressent et les mettre sous une forme facilement injectable dans une DB mySQL. Je crée une nouvelle base de données, <i>best_street</i>, Je crée deux tables (et comme je n'y connais rien, je leur donne de mauvais noms... : <i>street_table</i> et <i>municipality_table</i>.
<pre style="color:green">
$ mysql -u root -p
CREATE DATABASE best_street;
GRANT select, show view, lock tables, reload, replication client on *.* to 'bibi'@'localhost';
USE best_street;
CREATE TABLE street_table(
street_id INT,
street_name VARCHAR(100),
municipality_id INT,
PRIMARY KEY (street_id));
CREATE TABLE municipality_table(
municipality_id INT,
municipality_name VARCHAR(100),
PRIMARY KEY (municipality_id));
</pre>
<br/><br/>
Je récupère deux fichiers dans le .zip : <i>WalloniaStreetname20191018.xml</i> et <i>WalloniaMunicipality20191018.xml</i>.
Ils contiennent des trucs du genre (attention, les fichiers des rues sont très grands, Firefox s'engorge) :
<br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6iNbTNTPLLRpf5N8O2WGYeUH_8vcRr95N7CHCK3vt-OZeVydwsv4PMWPJ3GbFBklSga2F3RP6_89xsi8kYI-3p2eDAg0AqS3rM82JxLQrHF8VE8krMs5tLrA0ckVXQcNfYpk-oYe-PyQ/s1600/Streets.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6iNbTNTPLLRpf5N8O2WGYeUH_8vcRr95N7CHCK3vt-OZeVydwsv4PMWPJ3GbFBklSga2F3RP6_89xsi8kYI-3p2eDAg0AqS3rM82JxLQrHF8VE8krMs5tLrA0ckVXQcNfYpk-oYe-PyQ/s320/Streets.png" width="320" height="303" data-original-width="753" data-original-height="714" /></a></div>
<br/>et<br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHQbKvha-wlAp2dP1A6tlaLiMrtm0hlj8s6BXJWxEhlGla3KEx-ppNnBI0703lwgBguR2iuvZ1fl9uAqs2HAlLWlMc10On7SzjyrxmUu18DDmBj1eDToINWyjabyXRdla4AakDc3HaeRg/s1600/Municipality.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHQbKvha-wlAp2dP1A6tlaLiMrtm0hlj8s6BXJWxEhlGla3KEx-ppNnBI0703lwgBguR2iuvZ1fl9uAqs2HAlLWlMc10On7SzjyrxmUu18DDmBj1eDToINWyjabyXRdla4AakDc3HaeRg/s320/Municipality.png" width="320" height="256" data-original-width="750" data-original-height="600" /></a></div>
<pre style="color:blue">
</pre>
<br/>
Que l'on peut traiter (sous Linux) avec
<br/><pre style="color:black">
$ xsltproc x.xls y.xml > z.sql
</pre>
Les fichiers .xsl étant, pour les rues,
<pre style="color:blue">
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:tns="http://fsb.belgium.be/mappingservices/FullDownload/v1_00"
xmlns:com="http://vocab.belgif.be/ns/inspire/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
INSERT INTO street_table VALUES
<xsl:for-each select="tns:StreetResponseBySource/tns:Streetname">
(<xsl:value-of select="com:streetnameCode/com:objectIdentifier"/>,"<xsl:value-of select="com:streetname/com:spelling"/>",<xsl:value-of select="com:isAssignedBy/com:Municipality/com:objectIdentifier"/>),</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
</pre>
<br/>
Et pour les communes,
<br/>
<pre style="color:blue">
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:tns="http://fsb.belgium.be/mappingservices/FullDownload/v1_00"
xmlns:com="http://vocab.belgif.be/ns/inspire/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
INSERT INTO municipality_table VALUES
<xsl:for-each select="tns:MunResponseBySource/tns:Municipality">
(<xsl:value-of select="com:municipalityCode/com:objectIdentifier"/>,"<xsl:value-of select="com:municipalityName/com:spelling"/>"),</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
</pre>
<br/>
Le résultat n'est pas parfait et quelques adaptations cosmétiques sont nécessaires pour en faire de bons fichiers SQL. Il y a aussi des 'streetname' qui contiennent des '"' et le .xsl est trop primitif pour en tenir compte. Et, en fait, ce sont des données incorrectes. Cela donne quelque chose comme :
<br/><pre style="color:green">
INSERT INTO street_table VALUES
(7700015,"Chemin des Prés",25005),
(7700016,"Chemin des Ramiers",25005),
(7700017,"Chemin des Soeurs",25005),
(7700018,"Chemin du Grand Champ",25005),
(7700019,"Chemin du Petit Brou",25005),
...
(7741188,"Rue Jean-Louis Dumont",64074),
(7741189,"Rue Joseph Nicolas",64074),
(7741190,"Rue Joseph Noville",64074),
(7741254,"Rue des Bâtis",64075),
(7736185,"Tribomont",63035),
(7736549,"Route de Manhay",63045);
</pre>
<br/>et<br/>
<pre style="color:green">
INSERT INTO municipality_table VALUES
(52074,"Aiseau-Presles"),
(61003,"Amay"),
(63001,"Amel"),
(92003,"Andenne"),
(56001,"Anderlues"),
(91005,"Anhée"),
...
(25110,"Waterloo"),
(25112,"Wavre"),
(63084,"Welkenraedt"),
(84075,"Wellin"),
(91141,"Yvoir");
</pre>
<br/>
Il faut aussi noter qu'ils n'ont pas été fichus de donner des street_id distincts couvrant les trois régions. Il y a des duplicates du côté des 36000 et 37000 (!).<br/>
Il suffit maintenant d'injecter ces données dans notre DB :
<br/>
<pre style="color:green">
SOURCE insert_streets.sql;
SOURCE insert_municipality.sql;
</pre>
<br/>
Notre DB est prête, on peut commencer à jouer avec...
<br/>
<pre style="color:Olive">
mysql> SELECT * FROM street_table LIMIT 5;
+-----------+------------------------+-----------------+
| street_id | street_name | municipality_id |
+-----------+------------------------+-----------------+
| 7700001 | Aux Tiennes | 25005 |
| 7700002 | Avenue des Bouleaux | 25005 |
| 7700003 | Avenue des Cerisiers | 25005 |
| 7700004 | Avenue des Combattants | 25005 |
| 7700005 | Avenue des Pruniers | 25005 |
+-----------+------------------------+-----------------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM municipality_table ORDER BY municipality_name DESC LIMIT 5;
+-----------------+-------------------+
| municipality_id | municipality_name |
+-----------------+-------------------+
| 91141 | Yvoir |
| 84075 | Wellin |
| 63084 | Welkenraedt |
| 25112 | Wavre |
| 25110 | Waterloo |
+-----------------+-------------------+
5 rows in set (0.00 sec)
mysql>
</pre>
Par exemple, je peux avoir la liste de commune ayant le moins ou le plus de rues :
<pre style="color:Olive">
mysql> SELECT count(*), m.municipality_name from street_table s LEFT JOIN municipality_table m USING (municipality_id) GROUP BY municipality_id ORDER BY count(*) LIMIT 10;
+----------+-------------------+
| count(*) | municipality_name |
+----------+-------------------+
| 54 | Martelange |
| 58 | Hélécine |
| 61 | Stoumont |
| 62 | Gouvy |
| 63 | Lincent |
| 64 | Flobecq |
| 65 | Verlaine |
| 65 | Rumes |
| 66 | Donceel |
| 66 | Oreye |
+----------+-------------------+
10 rows in set (0.38 sec)
mysql> SELECT count(*), m.municipality_name from street_table s LEFT JOIN municipality_table m USING (municipality_id) GROUP BY municipality_id ORDER BY count(*) DESC LIMIT 10;
+----------+----------------------------+
| count(*) | municipality_name |
+----------+----------------------------+
| 2117 | Charleroi |
| 1998 | Liège |
| 1730 | Namur |
| 1280 | Mons |
| 1086 | Tournai |
| 923 | La Louvière |
| 812 | Ottignies-Louvain-la-Neuve |
| 738 | Wavre |
| 677 | Mouscron |
| 649 | Ath |
+----------+----------------------------+
10 rows in set (0.10 sec)
mysql>
</pre><br/>
Cette dernière requête étant :
<br/>
<pre style="color:Olive">
SELECT count(*), m.municipality_name from street_table s
LEFT JOIN municipality_table m USING (municipality_id)
GROUP BY municipality_id
ORDER BY count(*)
DESC LIMIT 10;
</pre>
<br/><br><br/>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-85298578869287483292019-11-18T04:40:00.001+01:002019-11-18T20:13:45.307+01:00ppsJe me demandais à quel point les signaux PPS de deux modules GPS à quelques euros étaient synchronisé...
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0mGp-ioQN-K0vkhskGL2O2vyFUWM3O69eOVETgN56XaVX7tOVLMEXXTlBN1QAl_UZPhzoNy7ET_fWE-0gDEwZA6ublKt1lG-p-WGG7fIR8iB0SRwNPCIbqi4950IwB-YpVtjv3GvCjB4/s1600/modules.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0mGp-ioQN-K0vkhskGL2O2vyFUWM3O69eOVETgN56XaVX7tOVLMEXXTlBN1QAl_UZPhzoNy7ET_fWE-0gDEwZA6ublKt1lG-p-WGG7fIR8iB0SRwNPCIbqi4950IwB-YpVtjv3GvCjB4/s320/modules.jpg" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
Trigger sur le channel-1. Il y a du jitter sur l'autre trace.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCFvmjw-MaAPpHXOVwgW3S1tln924i_OPD0n68eIqI4ezsQ3MSXazCGV7ds8SSwBmGTuYIztHlzcIAJJEBc_jVS5SrTzox7zyzdsoNqXHhsa1tYHIFvtobZevid9jTLqnkgcc5qdC5mvA/s1600/NewFile2.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCFvmjw-MaAPpHXOVwgW3S1tln924i_OPD0n68eIqI4ezsQ3MSXazCGV7ds8SSwBmGTuYIztHlzcIAJJEBc_jVS5SrTzox7zyzdsoNqXHhsa1tYHIFvtobZevid9jTLqnkgcc5qdC5mvA/s320/NewFile2.bmp" width="320" height="234" data-original-width="320" data-original-height="234" /></a></div>
La réception n'est pas idéale à l'endroit où j'ai effectué la mesure, sur une terrasse entre les maisons.
Trigger sur le channel-2. Idem.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP8Mk2DqYXMZ0nnzpHVFWf3zREGTbFcnxkcryhpww-KX7Xgf_pv2aLfZ2eerfxT3MInLIZwl9w_s_vHVih6aLY7dNpkfxVPUdjKFkv-vQ8oEqutNFuMGRdI_sbdJ7yVKFI2OFElqqeW8k/s1600/rigol.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP8Mk2DqYXMZ0nnzpHVFWf3zREGTbFcnxkcryhpww-KX7Xgf_pv2aLfZ2eerfxT3MInLIZwl9w_s_vHVih6aLY7dNpkfxVPUdjKFkv-vQ8oEqutNFuMGRdI_sbdJ7yVKFI2OFElqqeW8k/s320/rigol.jpg" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
Un autre point à noter est que les modules semblent interférer entre eux. J'ai utilisé deux alimentations différentes et j'ai dû en démarrer un avant l'autre...
Une question intéressante serait de savoir si le jitter diminue quand on a une meilleure réception avec plus de satellites visibles en même temps.xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-33695848187820057562019-09-15T18:48:00.003+02:002019-09-28T07:22:37.271+02:00NanoVNAUn '<a href="https://fr.wikipedia.org/wiki/Analyseur_de_r%C3%A9seau">Vector Network Analyzer</a>' à 40.00 euros sur eBay... Ce petit bidule 'stand alone' permet de mesurer la réflexion (S11) et la transmission de signaux entre 50 kHz et 900 MHz.
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicMqEKPELm4NlB89r-RI-B3muTR82cpMUtM9qgz4iRpLJK7KEHkp8M81RbOWOBSjs6D2aVTHekVUMEa0oFRpyeuVVclg_5LNjEtHs1tP9oUS8P6NjrmGDwoWHwQrwZ5uKQyMMUhovRsO0/s1600/nanoVNA-20190915.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicMqEKPELm4NlB89r-RI-B3muTR82cpMUtM9qgz4iRpLJK7KEHkp8M81RbOWOBSjs6D2aVTHekVUMEa0oFRpyeuVVclg_5LNjEtHs1tP9oUS8P6NjrmGDwoWHwQrwZ5uKQyMMUhovRsO0/s320/nanoVNA-20190915.jpg" width="320" height="213" data-original-width="1200" data-original-height="798" /></a></div>
<i>Mesure en transmission d'un filtre '<a href="https://en.wikipedia.org/wiki/SAW_filter">SAW</a>' passe-bande 433 MHz.</i>
<br/><br/>
Le nanoVNA est équipé d'un petit 'touchscreen' mais on peut également communiquer via le port USB (USBc). Sur Linux, on peut utiliser 'minicom -D /dev/ttyACM0', par exemple. Et sur Windows, 'putty'.
<br/><br/>
L'interface est bien conçue. CH0 mesure la réflexion (S11) et CH1, la transmission (S21) en valeur imaginaires. On définit la plage de fréquences (sweep) qui sera divisée en 101 points. On peut afficher 4 traces. Pour chaque trace, on peut choisir le canal, le type d'affichage (logmag, smith, phase), etc...
<br/><br/>
Via le port USB, on a une console série dans laquelle on peut <a href="https://groups.io/g/nanovna-users/files/NanoVNA%20Console%20Commands%208-6-19.pdf">taper des commandes</a> et afficher les résultats. Ainsi, par exemple, on peut facilement obtenir les mesures en transmission entre 400 et 500 MHz.
<pre>
ch> sweep 400000000 500000000 101
ch> data 1
-0.004106074 0.001582601
-0.004401572 0.001613250
-0.004341298 0.001819048
-0.004164417 0.001013602
-0.006044433 0.001735574
...
</pre>
Un petit script PERL vite écrit, convertit les valeurs en dB :
<pre>
#!/usr/bin/perl
$f0 = 400.0; $f1 = 500.0;
$inc = ($f1 - $f0) / 101;
$df = 0;
while ($line = <STDIN>)
{
chomp $line;
($a, $b) = split /\s/,$line;
$mag = sqrt ($a*$a + $b*$b);
if ($mag == 0) {$mag = 0.001;}
printf("%6.2f\t%f\n", $f0 + $df, 20*log($mag)/log(10.0));
$df += $inc;
}
</pre>
et on obtient le même graphe que l'écran du nanoVNA avec gnuplot :
<pre>
gnuplot <<END
set term png size 1200,800
set output 'S21-logmag.png'
set title 'S21-logmag of a "NMRF FBp - 433s" filter'
set xlabel 'Frequency (MHz)'
set ylabel 'S21 dB'
plot 'S21-logmag' with lines
END
</pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN9eJA8mpKq8dbLuapH7j3tXdEyJve5iU-QJ5dzSB1Qzmve3MJxfqvgJack8eynaa593h8xUSpTNxLGrtQ_mgLo8fcEih20gZNcALq3awC_1xyIXBNvfhwIoRck7eNoViuVN0parNtgJs/s1600/S21-logmag.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN9eJA8mpKq8dbLuapH7j3tXdEyJve5iU-QJ5dzSB1Qzmve3MJxfqvgJack8eynaa593h8xUSpTNxLGrtQ_mgLo8fcEih20gZNcALq3awC_1xyIXBNvfhwIoRck7eNoViuVN0parNtgJs/s320/S21-logmag.png" width="320" height="213" data-original-width="1200" data-original-height="800" /></a></div>
<i>Graphe calculé à partir des données obtenues via l'interface série.</i>
<br/><br/>
C'est magique!<br/><br/>
Quelques exemples pour la route :
<pre>
ch>
ch> help
Commands: help exit info echo systime threads reset freq offset time dac saveconfig
clearconfig data dump frequencies port stat sweep test touchcal touchtest pause
resume cal save recall trace marker edelay
ch> info
Kernel: 4.0.0
Compiler: GCC 5.4.1 20160919
Architecture: ARMv6-M
Core Variant: Cortex-M0
Port Info: Preemption through NMI
Platform: STM32F072xB Entry Level Medium Density devices
Board: NanoVNA
Build time: Aug 2 2019 - 16:40:01
ch> trace
0 LOGMAG CH0 1.000000000 7.000000000
1 LOGMAG CH1 1.000000000 7.000000000
2 SMITH CH0 1.000000000 0.000000000
3 PHASE CH1 1.000000000 4.000000000
ch> trace 99
trace {0|1|2|3|all} [logmag|phase|smith|linear|delay|swr|off] [src]
ch> trace 1 phase 0
ch> trace
0 LOGMAG CH0 1.000000000 7.000000000
1 PHASE CH0 1.000000000 4.000000000
2 SMITH CH0 1.000000000 0.000000000
3 PHASE CH1 1.000000000 4.000000000
ch> sweep
400000000 500000000 101
ch> sweep 420000000 440000000 101
ch> sweep
420000000 440000000 101
ch>
ch> data 1
-0.004733881 0.003933506
-0.004605576 0.004513134
-0.004246967 0.003887655
-0.004040227 0.003405604
-0.003938771 0.004323835
-0.004104804 0.004129481
...
</pre>
data0 pour les mesures de réflexion, data 1 pour la transmission. Après, ce sont les données de calibration.
<br/><br/>
<h2>Quelques liens</h2>
<ul>
<li><a href="https://drive.google.com/file/d/1usvmcn4cR8Ltrb6fT05jA6g7O0uhJozL/view">nanoVNA User Guide 2019-07-11</a> (pdf)</li>
<li><a href="https://groups.io/g/nanovna-users/topics">Forum</a> (groups.io/g/nanovna-users) -- <a href="https://groups.io/g/nanovna-users/wiki/home">wiki</a> (accessible aux inscrits)</li>
<li><a href="https://www.youtube.com/watch?v=knfwIKeAnRQ">Vidéo de Electro Bidouilleur</a> (Bertrand)</li>
<li><a href="https://www.youtube.com/watch?v=VFypdpikygM">Vidéo de Cyrob</a> (Philippe Demerliac)</li>
<li><a href="https://www.silabs.com/documents/public/data-sheets/Si5351-B.pdf">Si5351A data sheet</a> (Silicon Labs Clock Generator)</li>
<li><a href="http://www.ti.com/lit/ds/symlink/tlv320aic3204.pdf">TLV320AIC3204 data sheet</a> (TI Audio Codec)</li>
<li><a href="https://www.nxp.com/docs/en/data-sheet/SA612A.pdf">SA612AD datasheet</a> (NXP Mixer)</li>
<li><a href="https://www.st.com/en/microcontrollers-microprocessors/stm32f072cb.html">STM32F072CBT6 data sheet</a> (16KB SRAM, 128 KB FLASH, 48 MHz, USB,...)</li>
<li><a href="https://github.com/ttrftech/NanoVNA">Firmware</a> on GitHub</li>
</ul>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-82148267211581267532019-08-27T18:47:00.001+02:002019-08-27T18:48:17.776+02:00XSLT - Garmin GPX - gnuplotUn Garmin donne la trace GPS suivante : AiguillesRouges.gpx
<pre>
<?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...
</pre>
gpx.xsl, un petit bout de code XSLT
<pre>
<?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>
</pre>
Et sur Linux,
<pre>
$ xsltproc gpx.xsl AiguillesRouges.gpx > AigRou.xyz
</pre>
donne les coordonnées X, Y et Z en 3 colonnes :
<pre>
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...
</pre>
Qu'il suffit de traiter avec le script gnuplot suivant :
<pre>
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
</pre>
pour obtenir les graphes suivants :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUmJUfSZ87U9Gn6aqSZnyqSElxS2G2jfhwgWiNTrqUvn9c9rX_3c3WbsAR6YfHlV8BzP5MCz0cmYFV1rLQnPrEV5jI6613TfMwFPDO4nuphdA5EOlajsFG9IfEP1OEk6TijMVNwEVrL_M/s1600/AigRouXYZ.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUmJUfSZ87U9Gn6aqSZnyqSElxS2G2jfhwgWiNTrqUvn9c9rX_3c3WbsAR6YfHlV8BzP5MCz0cmYFV1rLQnPrEV5jI6613TfMwFPDO4nuphdA5EOlajsFG9IfEP1OEk6TijMVNwEVrL_M/s320/AigRouXYZ.png" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Kq5iYqFPuWvuGpAtcp_arViBjJpCTh27LStzoYOfVgOoMC21BmDt-ZJbcn887OFpKA1m7Lse88v9BO8Y9UmRg39bnTjqFH7asMZnMhcGsG8BE7Aq7ex5RcaEJKJjwytMgeceLjHz99c/s1600/AigRouXY.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Kq5iYqFPuWvuGpAtcp_arViBjJpCTh27LStzoYOfVgOoMC21BmDt-ZJbcn887OFpKA1m7Lse88v9BO8Y9UmRg39bnTjqFH7asMZnMhcGsG8BE7Aq7ex5RcaEJKJjwytMgeceLjHz99c/s320/AigRouXY.png" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhktcD6BveAxZEFWRDzbDxqTqDM4WOQJl-fjoBp6iGVahk7ZsNe55GYcr-WF_KY0BZFU16mxv7h3Pl1IM8mmFrPD2CmdqFRNKLXtuaeX8ZdF2_630sGlmJsE8ZQ91Ib79NAya_Ud4rHMG8/s1600/AigRouZ.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhktcD6BveAxZEFWRDzbDxqTqDM4WOQJl-fjoBp6iGVahk7ZsNe55GYcr-WF_KY0BZFU16mxv7h3Pl1IM8mmFrPD2CmdqFRNKLXtuaeX8ZdF2_630sGlmJsE8ZQ91Ib79NAya_Ud4rHMG8/s320/AigRouZ.png" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.comtag:blogger.com,1999:blog-4811625769590798586.post-17423703459384746902019-04-27T16:34:00.001+02:002019-04-27T16:34:29.581+02:00ADS-B avec cantennaAyant trouvé un bidon d'huile d'olive de 10 litres, j'envisage d'en faire une '<a href="https://en.wikipedia.org/wiki/Cantenna">cantenna</a>' pour l'ADS-B... À l'image des 'antennes Ricoré' pour le WiFi.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAQyItMMtIMWBmA1jMPkCirqIr9S_TMnvQf0DBX9fncMfUu1bP3PnlprD8xcotQJO-46CW-txWIycrDD3hfXttgOvrwZrzF1vDMM5nDjUamto4XEp7vvxQpUd6I8RzGGI0SORQnZGxzPk/s1600/cantenna-setup.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAQyItMMtIMWBmA1jMPkCirqIr9S_TMnvQf0DBX9fncMfUu1bP3PnlprD8xcotQJO-46CW-txWIycrDD3hfXttgOvrwZrzF1vDMM5nDjUamto4XEp7vvxQpUd6I8RzGGI0SORQnZGxzPk/s320/cantenna-setup.jpg" width="308" height="320" data-original-width="885" data-original-height="918" /></a></div>
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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2_W_Y2MNrSnu4hIfNVmcRiYXMlQ4SvOgneSx9FE9CMf2LgweypcYu6S_p7GlV-p41SDgxaNti3q1yFKYEmYUDgXgvGYyqDOiFfmC6ARuKoS_eD56b3oMNekTo1qMCovyuyrQhhT_3ZH0/s1600/cantenna-in.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2_W_Y2MNrSnu4hIfNVmcRiYXMlQ4SvOgneSx9FE9CMf2LgweypcYu6S_p7GlV-p41SDgxaNti3q1yFKYEmYUDgXgvGYyqDOiFfmC6ARuKoS_eD56b3oMNekTo1qMCovyuyrQhhT_3ZH0/s320/cantenna-in.jpg" width="320" height="263" data-original-width="1062" data-original-height="874" /></a></div>
Je pars faire des tests dans un endroit relativement élevé, un terril au dessus de Liège. Et j'en registre les avions avec <a href="https://github.com/antirez/dump1090">dump1090</a> sur un <a href="http://www.orangepi.org/orangepizero/">OrangePiZero</a> 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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh73h9mwb8pT6wuZqfzwbeSf7A8WTFjItVICwxIWLOR6UpVgiICHGw6YgJDbCx6pg6V8mEe8anuMnq8SkZ5cQa4faZcqltjWZMGUqig-KvmFBnoAcwduT4Ly-j_aiO5TeXiiw63Qfe19oE/s1600/BidonSurTrepied.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh73h9mwb8pT6wuZqfzwbeSf7A8WTFjItVICwxIWLOR6UpVgiICHGw6YgJDbCx6pg6V8mEe8anuMnq8SkZ5cQa4faZcqltjWZMGUqig-KvmFBnoAcwduT4Ly-j_aiO5TeXiiw63Qfe19oE/s320/BidonSurTrepied.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
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'<a href="https://fr.wikipedia.org/wiki/Horizon-radar">horizon radar</a> théorique (D_miles = 2.2 * sqrt(altitude_m)).
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-rrp3ro5ydm8TtiD_IYl9J6gmAAB5AJHDkxJlzTv6Gcm4PfbV0GazYNALdpl3nx1XxmCBwAl35KVTM35pFtfsnyTQfKgem0fYHM-HQAr0Fa3u5CKY3y6-lu5TBLOarc09Yvfc4ShVmEs/s1600/bidon-diapason.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-rrp3ro5ydm8TtiD_IYl9J6gmAAB5AJHDkxJlzTv6Gcm4PfbV0GazYNALdpl3nx1XxmCBwAl35KVTM35pFtfsnyTQfKgem0fYHM-HQAr0Fa3u5CKY3y6-lu5TBLOarc09Yvfc4ShVmEs/s320/bidon-diapason.gif" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
De Liège, je capte des avions au delà de Paris et presque jusque Londres.
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-35816675089068374352019-02-17T10:29:00.000+01:002019-04-27T16:50:17.553+02:00AIS againPetite 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).
<pre>
/usr/bin/rtl_sdr -f 162000000 -s 262144 -n 16000000 core.iq
</pre>
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 :
<pre>
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);
</pre>
Avec plotspec.m,
<pre>
% 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
</pre>
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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf-4Jbb0UcwO8qTRJ9IAPww8Dl5wt45EbX9Fz_iQbgIkolNLCG_8SJuobEV_GF0BgzvDnethLFS9eNyTi9rXYfHJ72C919sYj_S-jtqlp4F018soXBhyphenhyphen6tSN-Jju-WY29Jo1MEv98mIj8/s1600/plotspect_15sec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf-4Jbb0UcwO8qTRJ9IAPww8Dl5wt45EbX9Fz_iQbgIkolNLCG_8SJuobEV_GF0BgzvDnethLFS9eNyTi9rXYfHJ72C919sYj_S-jtqlp4F018soXBhyphenhyphen6tSN-Jju-WY29Jo1MEv98mIj8/s320/plotspect_15sec.png" width="320" height="129" data-original-width="1332" data-original-height="539" /></a></div>
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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj51fEAj3PSOvbLcnXx8kBGNF4sc33_mJdBQutZkd_ke5hs_wQMp24ACyIUoefj8slMGLSBfTRZVYsD_lxV9bwCUuqYlY5rYggeBZfdKMYH14rkruyAE_f9n0aInyiK4AeE3-NSTOa2_AA/s1600/abs_15sec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj51fEAj3PSOvbLcnXx8kBGNF4sc33_mJdBQutZkd_ke5hs_wQMp24ACyIUoefj8slMGLSBfTRZVYsD_lxV9bwCUuqYlY5rYggeBZfdKMYH14rkruyAE_f9n0aInyiK4AeE3-NSTOa2_AA/s320/abs_15sec.png" width="320" height="138" data-original-width="962" data-original-height="415" /></a></div>
Zoomons...
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQFSvih68mYbDUf0qufCIvAXKJN617wrN0NIcGbe1T19CU4L-GvPBxfgHIsaHbcZi8zt8WUzSKR1wLMkRdaLL2ZBihicnCllykdNvq95Pa9QEVqkXcvlNMK8ybuytIsv63Aj_RpoK_Bzo/s1600/abs_zoom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQFSvih68mYbDUf0qufCIvAXKJN617wrN0NIcGbe1T19CU4L-GvPBxfgHIsaHbcZi8zt8WUzSKR1wLMkRdaLL2ZBihicnCllykdNvq95Pa9QEVqkXcvlNMK8ybuytIsv63Aj_RpoK_Bzo/s320/abs_zoom.png" width="320" height="130" data-original-width="822" data-original-height="333" /></a></div>
Zoomons encore...
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguA4YdOiNre4G7-YQX9IC3VmUZcoC3qsu0lZzrHaN9n7OVAeJQQJDRg0tncQhs2daxBQampxwsQebcppXTkS0LNTNrWYlmA4SypDXfh4e88I7nv81RVQ8NiwrWDb85WOZN-1p61aCGsVU/s1600/abs_zzoom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguA4YdOiNre4G7-YQX9IC3VmUZcoC3qsu0lZzrHaN9n7OVAeJQQJDRg0tncQhs2daxBQampxwsQebcppXTkS0LNTNrWYlmA4SypDXfh4e88I7nv81RVQ8NiwrWDb85WOZN-1p61aCGsVU/s320/abs_zzoom.png" width="320" height="130" data-original-width="855" data-original-height="348" /></a></div>
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.
<pre>
$ # 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
</pre>
En cherchant un peu, on trouve un message à +25 Khz dont on s'intéresse à l'évolution de la phase :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNB1DlQdTftHha3gfsJ6BPQN1mhFqL3mH_PWBjVGuZlw8AHMj0MkRpRYE1XdICk02cQoAG3Lizv60AMLFiG6bCn-hB7dXkJWNrym3KjTbANql6dEXRQFN8FlvlpywWDHRRBgVD1qgKkq8/s1600/up_plotspec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNB1DlQdTftHha3gfsJ6BPQN1mhFqL3mH_PWBjVGuZlw8AHMj0MkRpRYE1XdICk02cQoAG3Lizv60AMLFiG6bCn-hB7dXkJWNrym3KjTbANql6dEXRQFN8FlvlpywWDHRRBgVD1qgKkq8/s320/up_plotspec.png" width="320" height="244" data-original-width="534" data-original-height="407" /></a></div>
En regardant la phase et en zommant :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKfWPt3RNAYxHUKaBQg8FThcG4bTg4CDpPwQevXAt4gYFcp8ZToi_3hyphenhypheneMmMUkErzfwiV6qYpFC9prGfUYSGWKBw3-rG67CILjSGx9OsCKe6uDY4ayus29G3qVWrrVhHLrYJZpmbuqEtw/s1600/up_arg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKfWPt3RNAYxHUKaBQg8FThcG4bTg4CDpPwQevXAt4gYFcp8ZToi_3hyphenhypheneMmMUkErzfwiV6qYpFC9prGfUYSGWKBw3-rG67CILjSGx9OsCKe6uDY4ayus29G3qVWrrVhHLrYJZpmbuqEtw/s320/up_arg.png" width="320" height="248" data-original-width="513" data-original-height="398" /></a></div>
Et la même chose pour un message à -25 KHz :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqb_G9avWjIk8MVFWFX1r8OfLa18BkKsRK9i8Czu_jfqBGXdY5c3tfi3r5gWARfTXWySvo72bzjCb0yezymfcdlJCVlOy_TFEXm4eH1OH2xETvKT1LKaB_qkwnJd1hl2RxkPUxikyszw/s1600/down_plotspec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqb_G9avWjIk8MVFWFX1r8OfLa18BkKsRK9i8Czu_jfqBGXdY5c3tfi3r5gWARfTXWySvo72bzjCb0yezymfcdlJCVlOy_TFEXm4eH1OH2xETvKT1LKaB_qkwnJd1hl2RxkPUxikyszw/s320/down_plotspec.png" width="320" height="240" data-original-width="534" data-original-height="401" /></a></div>
qui donne une évolution de la phase descendante :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrgCnQKsIt-2WCzqEun6jsNyFc3HrlqvkqEvGgx0rAvKw5XoObdgfv_4X8aLYFUP93PVaJkbQud-iOS6vbq1KoC0Dg9P_-FLs77PG-q0adNJpEfjXZ8lN-BUbN8ylTO3ndxiWaC538Rz8/s1600/down_arg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrgCnQKsIt-2WCzqEun6jsNyFc3HrlqvkqEvGgx0rAvKw5XoObdgfv_4X8aLYFUP93PVaJkbQud-iOS6vbq1KoC0Dg9P_-FLs77PG-q0adNJpEfjXZ8lN-BUbN8ylTO3ndxiWaC538Rz8/s320/down_arg.png" width="320" height="244" data-original-width="516" data-original-height="393" /></a></div>
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.
<pre>
% 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
</pre>
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr1fId5os06a-pIQ41eGzYCQri20GJf6PucU46RTRCTXjLBi_mKL2t9-lDL1YLiROz-q1f1TIs4rFUwW-J3FGWZOw_Za-n8wht6NkbB964WAfWVXs0K-RC8sOoBPWvIGny8qg5WhN9qFE/s1600/up_msg_phi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr1fId5os06a-pIQ41eGzYCQri20GJf6PucU46RTRCTXjLBi_mKL2t9-lDL1YLiROz-q1f1TIs4rFUwW-J3FGWZOw_Za-n8wht6NkbB964WAfWVXs0K-RC8sOoBPWvIGny8qg5WhN9qFE/s320/up_msg_phi.png" width="320" height="128" data-original-width="1118" data-original-height="448" /></a></div>
Détail, le début avec le préambule et les premiers octets.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNL3TI_1r_SCtCLLTnCbJ4tWKhHyrw315kwfjARZtVytCPUWe2wAk6iZymACl5RWpmq2ufOE97mvdqUitcpT6PqhSASMH3pwAAg4XuUYcRb_VATU5HKc0lX6qYVs4Hr81bhoXRsBr1ijo/s1600/up_msg_phi_zoom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNL3TI_1r_SCtCLLTnCbJ4tWKhHyrw315kwfjARZtVytCPUWe2wAk6iZymACl5RWpmq2ufOE97mvdqUitcpT6PqhSASMH3pwAAg4XuUYcRb_VATU5HKc0lX6qYVs4Hr81bhoXRsBr1ijo/s320/up_msg_phi_zoom.png" width="320" height="130" data-original-width="1078" data-original-height="439" /></a></div>
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhODhp_V6yJVM-EDZsbV4jJyF63Hkm2V05ot_ED19I_NPM_oCSDUm11Pb7Pqaqewlmj1Lq-4wJ_0THek8WcwMI6nPO90swK_GnQClgqmJinPwv8QkwpOt8lARVxmFcU0-VwDbz448rRlgI/s1600/didat.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhODhp_V6yJVM-EDZsbV4jJyF63Hkm2V05ot_ED19I_NPM_oCSDUm11Pb7Pqaqewlmj1Lq-4wJ_0THek8WcwMI6nPO90swK_GnQClgqmJinPwv8QkwpOt8lARVxmFcU0-VwDbz448rRlgI/s320/didat.png" width="320" height="62" data-original-width="1247" data-original-height="241" /></a></div>
avec le grid à 9600 samples/sec :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPLHkDPh0qDbhusPPCtEjXwspwxiaWHU22H_OQalwBgNpa65HIwcNWkmR6BunUBtg0s391VOz0uSCDtERCV5T9bEnjglvk4ivyP-MLLEdzauYrQ4mCqwUhFsDlHXketzSFZPSX4aVWvXI/s1600/timed_didat.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPLHkDPh0qDbhusPPCtEjXwspwxiaWHU22H_OQalwBgNpa65HIwcNWkmR6BunUBtg0s391VOz0uSCDtERCV5T9bEnjglvk4ivyP-MLLEdzauYrQ4mCqwUhFsDlHXketzSFZPSX4aVWvXI/s320/timed_didat.png" width="320" height="31" data-original-width="1600" data-original-height="155" /></a></div>
<hr/><br/><br/>
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, <a href="https://github.com/dgiardini/rtl-ais">rtl_ais</a> 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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF4xlNhczyTIPnYOjFvAWp-hR-XRLN75KKNwns5Unz-f_xKzciYwVCow-6vF0fsqQAfwnTNHctZ5CuFPTV45AdjyxyHDSvyH7dRwUjtffEMSyqvEtkLCy7L46yHiQzFi9T2qQssSvdybs/s1600/StBarbe.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF4xlNhczyTIPnYOjFvAWp-hR-XRLN75KKNwns5Unz-f_xKzciYwVCow-6vF0fsqQAfwnTNHctZ5CuFPTV45AdjyxyHDSvyH7dRwUjtffEMSyqvEtkLCy7L46yHiQzFi9T2qQssSvdybs/s320/StBarbe.png" width="320" height="240" data-original-width="1200" data-original-height="900" /></a></div>
<hr/>
À suivre...
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-75504946514800386992018-06-23T10:31:00.001+02:002018-06-23T10:31:59.127+02:00GPSDO<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8lfcGOYWVTuTcVAqfg2JR6UfDNwQauFI5lPgrJ8lRySH6K-D8uuv1l_DyJDvttW8uRjsUXlMGzW_gsgd-sB9FXss7rQGapjDcCFNPcIqdFlmpeQAZsB4_qgErrvQojZPGnSM90GvwLGk/s1600/GPSDOs.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8lfcGOYWVTuTcVAqfg2JR6UfDNwQauFI5lPgrJ8lRySH6K-D8uuv1l_DyJDvttW8uRjsUXlMGzW_gsgd-sB9FXss7rQGapjDcCFNPcIqdFlmpeQAZsB4_qgErrvQojZPGnSM90GvwLGk/s320/GPSDOs.jpg" width="320" height="247" data-original-width="1200" data-original-height="925" /></a></div>
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?<br/><br/>
Oui. Au départ, les deux fréquences sont différentes :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoiTDMY4M8lPYNDMDctrh-aLra964_BEhPv2pat5FLTUjnAJE0lxxgbNKdLaoLcsJJZNaYwJBJh1jUpVilkhaFLiyf1lSwLruNoNNqXoJ3etnz-XQ7-MRu5KRyjuGMPPko-Xk8j1xrX2k/s1600/unlocked.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoiTDMY4M8lPYNDMDctrh-aLra964_BEhPv2pat5FLTUjnAJE0lxxgbNKdLaoLcsJJZNaYwJBJh1jUpVilkhaFLiyf1lSwLruNoNNqXoJ3etnz-XQ7-MRu5KRyjuGMPPko-Xk8j1xrX2k/s320/unlocked.jpg" width="320" height="240" data-original-width="800" data-original-height="600" /></a></div>
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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv9-RE8YJeboDHxJu4k8tbzvl9JgeW9jrmxX_oeeErmdTUswCvwddZbTJcEWoDi8iQnUoqqm08-jJUmG5Cb6REqS0CCizSJf4dapRKyBc1_Dv9G92LmUFKLfuAhRQolSSH09cfQTxdmCU/s1600/locked.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv9-RE8YJeboDHxJu4k8tbzvl9JgeW9jrmxX_oeeErmdTUswCvwddZbTJcEWoDi8iQnUoqqm08-jJUmG5Cb6REqS0CCizSJf4dapRKyBc1_Dv9G92LmUFKLfuAhRQolSSH09cfQTxdmCU/s320/locked.jpg" width="320" height="240" data-original-width="800" data-original-height="600" /></a></div>
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.<br/><br/>
Je semble donc bien avoir du 10 MHz à mieux qu'un centième de Hertz près (10E-09, 1 ppb).xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-89075505453629150842018-05-06T14:43:00.000+02:002018-05-06T14:58:33.439+02:00MiniVNA TinyUn joli 'gadget'...
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik0hCyOMxbyhca8z_7oS24cFw-hlMILLLnUWyXY8mVLwi9F9Nbrgma8m9PfSGh9cHWuHesznHfgIFmDpjLTMNbra-19EvJ0AMxD78yhxrmtz-pH03-E3j21sZfB-x7gkO5CULYPFr8Izc/s1600/miniVNA_Tiny.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik0hCyOMxbyhca8z_7oS24cFw-hlMILLLnUWyXY8mVLwi9F9Nbrgma8m9PfSGh9cHWuHesznHfgIFmDpjLTMNbra-19EvJ0AMxD78yhxrmtz-pH03-E3j21sZfB-x7gkO5CULYPFr8Izc/s320/miniVNA_Tiny.jpg" width="320" height="205" data-original-width="1200" data-original-height="768" /></a></div>
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.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp5t-n3BSoLqQ7fFJ-4AbT_qOimtYzgJs7ijGmjAQMDuO8zYVv-sCnEODMEAoo-CXmIGACL3XHiT70vWygQ3DsT89urne0K3SwT1Qw1JTbJLc-UijWPZK8Vtj6Ou00xtGfu4v06TeEBR4/s1600/_Frisco-UdaYagi-WiFi-2.4GHz.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp5t-n3BSoLqQ7fFJ-4AbT_qOimtYzgJs7ijGmjAQMDuO8zYVv-sCnEODMEAoo-CXmIGACL3XHiT70vWygQ3DsT89urne0K3SwT1Qw1JTbJLc-UijWPZK8Vtj6Ou00xtGfu4v06TeEBR4/s320/_Frisco-UdaYagi-WiFi-2.4GHz.jpg" width="320" height="118" data-original-width="1200" data-original-height="441" /></a></div>
Par chance, ce n'est pas trop loin du but.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUU9Jmj4Vw7I037LYe1sm2K1b_AhUZ6GQOjIQrbscntKx472MvzOwv69DnzfR7Xvx6QIrxe_R_2kidUdiqgPM78jMi1nEkW7JJkagfy5ZDUpsEGybbAYkDPUHKkrgL0SQhMcfy7jH_G1k/s1600/VNA_180506_095523-frisco.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUU9Jmj4Vw7I037LYe1sm2K1b_AhUZ6GQOjIQrbscntKx472MvzOwv69DnzfR7Xvx6QIrxe_R_2kidUdiqgPM78jMi1nEkW7JJkagfy5ZDUpsEGybbAYkDPUHKkrgL0SQhMcfy7jH_G1k/s320/VNA_180506_095523-frisco.jpg" width="320" height="256" data-original-width="1280" data-original-height="1024" /></a></div>
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.
<pre>
$ sudo add-apt-repository -y ppa:webupd8team/java && sudo apt-get update && sudo apt-get install -y oracle-java8-installer
</pre>xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0tag:blogger.com,1999:blog-4811625769590798586.post-49386123372709282692017-11-18T15:34:00.002+01:002017-11-18T15:34:46.537+01:00DCF77Un petit module <a href="https://fr.wikipedia.org/wiki/DCF77">DCF77</a>, trouvé sur eBay, fait par des Canadiens (<a href="https://universal-solder.com">Universal Solder</a>)... : <a href="https://universal-solder.com/product/dcf77-atomic-clock-antenna-receiver-europe/">page du constructeur</a>.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh32JejrvhfTMGjTwaZm-a2yg6KXlX_JwpVdXINqz6end57oFa61MDy_3YjkLp4H95YXt9QwYilPNXZsDjWif_hlOyUyu-d6rwWqTvsFltjYLIdAsxyTAkS11BcgYMMPNqJ7VOhnfWAN-M/s1600/dfc77-minimal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh32JejrvhfTMGjTwaZm-a2yg6KXlX_JwpVdXINqz6end57oFa61MDy_3YjkLp4H95YXt9QwYilPNXZsDjWif_hlOyUyu-d6rwWqTvsFltjYLIdAsxyTAkS11BcgYMMPNqJ7VOhnfWAN-M/s320/dfc77-minimal.jpg" width="320" height="232" data-original-width="1024" data-original-height="743" /></a></div>
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 <a href="http://canaduino.ca/downloads/MAS6180C.pdf">MAF6180C</a>).
<br/><br/>
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 <a href="https://fr.wikipedia.org/wiki/Mainflingen">Mainflingen</a> qui émet avec une puissance de 30 kW sur des antennes tirées entre des pylônes de 200 mètres de haut).
<br/></br>
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.
<br/><br/>
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é <a href="http://jmfriedt.free.fr/dcf77.pdf">les variations d'altitude de l'ionosphère avec une carte son de PC</a> en écoutant le DCF77 à Besançon... Bref, il y a moyen de s'amuser.
xofchttp://www.blogger.com/profile/17118537483006810989noreply@blogger.com0