Utiliser une caméra infra-rouge I2C

Utiliser une caméra infra-rouge I2C

Il existe maintenant des petites caméras infra-rouge sous forme de break-out board très abordables et faciles à intégrer à un projet d'automatisation. Etonnamment, elles utilisent souvent le protocole I2C pour transférer les données. Nous allons donc vous montrer aujourd'hui comment utiliser un Yocto-I2C pour interfacer ce type de caméra.



Le Yocto-I2C est capable de gérer de manière autonome les subtilités d'une communication I2C, bidirectionnelle par nature. Pour effectuer une requête I2C, l'hôte envoie au Yocto-I2C le format de l'échange désiré, et il reçoit en retour la trace détaillée de l'échange effectué, y compris les ACK/NAK et les valeurs transmises par le périphérique I2C.

Ce mécanisme avait initialement été conçu pour les échanges de messages courts utilisés habituellement en I2C, par exemple pour discuter avec un capteur. Avec ces petites caméras infra-rouge, la lecture d'une image de 768 pixels de 16 bits mène à utiliser des messages beaucoup plus longs que d'habitude, raison pour laquelle nous avons récemment augmenté la taille maximale des messages supportés par le Yocto-I2C. Donc, pour commencer, mettez à jour votre Yocto-I2C avec un firmware 52846 ou plus récent, pour pouvoir utiliser des messages longs.

La caméra que nous allons utiliser pour cet exemple est la Melexis MLX90640, disponible chez Adafruit directement montée sur un break-out board. C'est sous cette forme que nous l'avons utilisée, pour la raccorder à un Yocto-I2C:

Le break-out board d'Adafruit pour la caméra thermique MLX90640, connecté à un Yocto-I2C
Le break-out board d'Adafruit pour la caméra thermique MLX90640, connecté à un Yocto-I2C



Comme il s'agissait d'un test que nous faisions pour un client, plutôt que de développer nous-même tout le code de configuration de la caméra et de lecture synchrone des deux demi-images entrelacées, nous avons choisi de réutiliser le code Python fourni par Adafruit pour utiliser ce break-out board. Le code est bien structuré, avec un module d'interface séparé qui gère la communication I2C puisqu'il est destiné à fonctionner aussi bien sur un Raspberry Pi que sur un microcontrolleur CircuitPython. Nous nous sommes donc contentés de faire notre propre version du module d'interface I2C d'Adafruit qui fonctionne avec le Yocto-I2C. Voici notre fichier i2c_device_emu.py:

from yocto_i2cport import *

class I2CDevice:
    def __init__(self, i2c, device_address, probe = True):
        self.i2cport = i2c
        self.device_address = device_address
        if probe:
            self.__probe_for_device()

    def write(self, buf, *, start = 0, end = None):
        if end is None:
            end = len(buf)
        self.i2cport.i2cSendArray(self.device_address, buf[start:end])

    def write_then_readinto(self, out_buffer, in_buffer, *,
            out_start = 0, out_end = None, in_start = 0, in_end = None):
        if out_end is None:
            out_end = len(out_buffer)
        if in_end is None:
            in_end = len(in_buffer)
        res = self.i2cport.i2cSendAndReceiveArray(
            self.device_address,
            out_buffer[out_start:out_end],
            in_end - in_start
        )
        for i in range(0,len(res)):
            in_buffer[in_start+i] = res[i]

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

    def __probe_for_device(self):
        # Try to read a byte from an address,
        try:
            self.i2cport.i2cSendArray(self.device_address, [])
        except OSError:
            raise ValueError("No I2C device at address: 0x%x" % self.device_address)


Dans le fichier adafruit_mlx90640.py, nous avons remplacé l'import de adafruit_bus_device.i2c_device par:

from i2c_device_emu import I2CDevice
from yocto_i2cport import YI2cPort


Dans le constructeur de la classe MLX90640, nous avons remplacé le type I2C d'Adafruit par la version Yoctopuce YI2cPort. Nous avons aussi changé la constante I2C_READ_LEN à 256 words, ce qui correspond à la taille maximale des messages du Yocto-I2C (512 octets).

On peut alors reprendre n'importe quel exemple d'Adafruit et le faire fonctionner avec un Yocto-I2C en mettant le code d'initialisation suivant:

errmsg = YRefParam()
if YAPI.RegisterHub("usb", errmsg) != YAPI.SUCCESS:
    sys.exit("Failed to attach to USB port: "+errmsg.value)
i2cPort = YI2cPort.FirstI2cPort()
if i2cPort is None:
    sys.exit("No Yocto-I2C device found, check USB cable!")
i2cPort.set_i2cMode("600kbps")
mlx = adafruit_mlx90640.MLX90640(i2cPort)



Pour vérifier que tout fonctionne bien, nous avons repris l'exemple mlx90640_camtest.py destiné au Raspberry Pi, et nous l'avons porté pour fonctionner sur une machine Windows ou Linux avec PyQt6 et un Yocto-I2C. Voici le résultat:



Grâce à cette petite librairie i2c_device_emu, vous devriez donc désormais pouvoir utiliser tous les codes d'exemples pour les break-out boards I2C d'Adafruit sur un vrai PC avec un Yocto-I2C et ne plus être limités à l'utilisation d'un Raspberry Pi.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.