dimanche 21 novembre 2021

Gravier luminescent 2

Le TSL230R n'ayant pas donné de très bon résultats, j'ai commandé un kit TSL2591 d'Adafruit...
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 Argon One qui ne demande qu'à servir.

Première étape, télécharger et installer le Raspberry Pi OS. 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 Pi imager qui, malheureusement, refuse de s'installer sur mon vieil Ubuntu pour une question de dépendance (libc, qt,...) et donc, ce sera une alternative : BalenaEtcher... 90 MB pour remplacer dd... Il est bien loin le temps où tout un environnement Linux tournait sur une disquette 3.5' 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.

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 headless. 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 :
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"
}
À 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 nmap, 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).
$ nmap -sP 192.168.1.*
...
$ ssh pi@raspberripy # or ssh pi@192.168.1.47
pi@raspberrypi:~ $
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.
$ curl https://download.argon40.com/argon1.sh | bash 
Reste maintenant à configurer le Rpi pour pouvoir utiliser l'interface i2c. Cela se passe du côté de 'raspi-config' avec des menus texte.
$ sudo raspi-config
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...
$ 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: -- -- -- -- -- -- -- --                         
Le TSL2591 est bien détecté en 0x29.

Il ne reste plus qu'à lire la datasheet et à trouver quelques exemples de programmes (i2c et tsl2591) pour (la facilité) et en faire une version minimaliste (pour la compréhension) :
#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;
        }
Et compiler le tout avec un Makefile naïf :
tsl2591: tsl2591.c
	gcc -o tsl2591 tsl2591.c -lwiringPi
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.
Avec un gravier bleu, cela donne :
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))

Puis, il faudrait bien sûr refaire l'expériences de nombreuses fois pour en maîtriser tous les paramètres...