Interfacer les capteurs Sensirion SEN6x

Interfacer les capteurs Sensirion SEN6x

Sensirion commercialise une famille de capteurs destinés à mesurer les paramètres pertinents pour évaluer la qualité de l'air ambiant dans un bâtiment. Similaires à peu de chose près, les différents capteurs SEN6x se distinguent essentiellement par la norme de qualité de l'air qu'ils visent à satisfaire et le type de mesures offertes. Voyons comment les interfacer.




Les capteurs SEN6x se présentent sous la forme de petits parallélépipèdes rectangles noirs de 55mm de long, avec des ouïes sur une face pour faire circuler l'air à travers le capteur:

Le capteur de qualité de l'air SEN66
Le capteur de qualité de l'air SEN66


Ces capteurs sont destinés à être intégrés à la surface d'un boîtier fermé, pour garantir les caractéristiques du flux d'air qui traverse le capteur par convection forcée, grâce au petit ventilateur intégré. Sensirion fournit le modèle 3D imprimable d'un support permettant de clipser le capteur dans la position suggérée, mais il vous restera à l'intégrer à votre propre conception de boîtier.

Nous avons fait nos tests à l'aide d'un capteur SEN66, qui mesure l'humidité relative, la température et le taux de CO2, et fournit de plus une estimation de la concentration dans l'air de particules fines (PM1.0, PM2.5, PM4.0, PM10.0), ainsi qu'un indice de qualité de l'air par rapport aux VOC (composants organiques volatiles) et au NOx (oxydes d'azote). C'est l'un des capteurs les plus complets de la série, il ne lui manque que la mesure du taux de formaldéhyde, qu'on ne trouve que dans le SEN68.

Raccordement et communication avec le capteur

Le capteur se branche à l'aide d'un petit connecteur à 6 pôles compatible avec le JST-GHR-06V, mais seuls 4 fils sont nécessaires pour fournir une alimentation 3.3V et une communication I2C. Pour l'interroger, on va donc utiliser un Yocto-I2C branché comme suit:

Raccordement d'un capteur SEN6x au Yocto-I2C
Raccordement d'un capteur SEN6x au Yocto-I2C


La datasheet du SEN6x se réfère aux spécifications NXP du bus I2C et inclut les diagrammes habituels illustrant le fonctionnement d'une séquence I2C write et I2C read. On pourrait donc s'attendre à une interrogation par registres I2C très usuelle... Mais c'est là que cela se complique un peu: visiblement Sensirion a pris quelques libertés dans l'implémentation de l'interface I2C de ce capteur.

D'une part, contrairement à ce qui est illustré dans le diagramme de la datasheet, le capteur ne supporte pas l'utilisation du repeated start dans une séquence I2C read. Si on l'utilise, le capteur répond toujours FF. D'autre part, la grande bizarrerie de ce capteur est la nécessité d'ajouter un délai de plusieurs millisecondes au milieu des séquences de lecture, juste après l'envoi de la commande. Sans cette attente, le capteur va simplement ignorer la demande de lecture qui suit (NACK de l'adresse du capteur en lecture).

Nous pouvons observer ces deux comportements dans l'interface du Yocto-I2C. L'adresse I2C du capteur est 6B, donc l'octet d'adresse I2C avec le bit de direction est D6 pour un write et D7 pour un read. Dans l'interaction ci-dessous, on a commencé par une interrogation avec un repeated start. Puis, 8.96 s plus tard, on a fait une interrogation sans attendre entre l'envoi de la commande et la lecture, qui est donc ignorée par le capteur. Finalement, on effectue la séquence de lecture en deux temps et cela fonctionne comme prévu.

Interrogation du SEN6x sans prendre de précaution
Interrogation du SEN6x sans prendre de précaution


Le délai d'attente à respecter avant le read est spécifié pour chaque commande dans la datasheet, mais est généralement de 20 ms. Pour satisfaire à cette particularité, le plus simple est d'effectuer les lectures I2C sous forme de deux transactions distinctes: d'abord l'envoi de l'adresse, puis ensuite la lecture. Il suffit alors de configurer sur le Yocto-I2C un délai minimal de 20 ms entre l'envoi des messages pour contourner le problème:

Configuration du Yocto-I2C pour les capteurs SEN6x
Configuration du Yocto-I2C pour les capteurs SEN6x



Une fois ce problème réglé, on peut se lancer dans le véritable protocole. La séquence de commandes à envoyer pour obtenir des mesures est la suivante:

  • D304 pour faire un reset du capteur
  • 0021 pour lancer les mesures
  • 0202 pour demander au capteur si les mesures sont disponibles
  • 0300 pour lire les mesures du SEN66

Nous allons intégrer ces commandes dans un job d'interrogration automatique directement sur le Yocto-I2C, de sorte que les mesures soient capturées périodiquement, enregistrées et mises à disposition immédiate de l'API Yoctopuce. Le job comportera deux tâches: la première sert à faire l'initialisation du capteur et n'est exécutée qu'une seule fois, tandis que la seconde s'exécute périodiquement.

Voici la définition de la tâche d'initialisation, définie comme un custom protocol:

writeLine   @6B:D304
wait        50
writeLine   @6B:0021
wait        50


La tâche périodique est un peu plus complexe, nous allons donc la détailler morceau par morceau. Pour interroger le capteur, comme indiqué précédemment, on doit faire la lecture en deux temps: d'abord envoyer l'adresse de lecture, puis, un peu plus tard, effectuer la lecture proprement dite:

writeLine   @6B:0202
writeLine   {S}D7xxxxxx{P}


Cette première interrogation sert à savoir si de nouvelles mesures sont disponibles. Nous vérifions donc l'octet correspondant retourné par le capteur pour que la tâche n'aille pas plus loin tant que la condition n'est pas remplie:

expect      6B:{A}00($ready:BYTE)..
assert      $ready==1


Si des mesures sont disponibles, on lance la grande commande de lecture, à nouveau en deux temps. Notez que si vous utilisez un SEN63, SEN65 ou SEN68, vous devez utiliser la variante de commande correspondant au modèle du capteur et adapter le nombre d'octets à recevoir en conséquence.

writeLine   @6B:0300
writeLine   {S}D7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{P}"


Le décodage des valeurs retournées doit sauter les octets de CRC, puis appliquer les facteurs d'échelle donnés dans le datasheet du capteur, avant d'affecter les valeurs aux genericSensor1..9 du Yocto-I2C:

expect      6B:{A}($pm1:WORD)..($pm2:WORD)..($pm4:WORD)..($pm10:WORD)..
            ($hum:WORD)..($temp:WORD)..($voc:WORD)..($nox:WORD)..($co2:WORD)..
compute     $1 = ($pm1==0xffff ? -1 : $pm1/10.0)
compute     $2 = ($pm2==0xffff ? -1 : $pm2/10.0)
compute     $3 = ($pm4==0xffff ? -1 : $pm4/10.0)
compute     $4 = ($pm10==0xffff ? -1 : $pm10/10.0)
compute     $5 = $hum/100.0
compute     $6 = $temp/200.0
compute     $7 = ($voc==0x7fff ? -1 : $voc/10.0)
compute     $8 = ($nox==0x7fff ? -1 : $nox/10.0)
compute     $9 = ($co2==0xffff ? -1 : $co2)


Vous pouvez télécharger le fichier job complet si besoin.

Résultat

Une fois le job lancé, la magie opère et on voit les genericSensor du Yocto-I2C refléter les valeurs mesurées. En lançant Yocto-Visualization, on obtient facilement un graphique des mesures en temps réel:

Mesures du SEN66 dans Yocto-Visualization
Mesures du SEN66 dans Yocto-Visualization


Les données s'enregistrent aussi sur la mémoire flash du module et il est possible de les lire facilement avec l'API Yoctopuce.

Concernant le crédit à donner aux mesures estimées (VOC, NOx, PM), nous vous renvoyons aux différents articles de Sensirion concernant la précision de ces estimations par rapport à des mesures effectuées à l'aide d'instruments scientifiques. Mais gardez à l'esprit qu'il s'agit d'estimations sujettes à caution.

Conclusion

Il est toujours étonnant pour nous de découvrir des capteurs aussi sophistiqués utilisant une interface de communication tellement peu orthodoxe. Comme souvent, le fabricant élude le problème en fournissant une implémentation en Python de sa variante personnalisée du protocole I2C, mais le nombre de packages Python nécessaires à lancer le plus simple des exemples du kit d'évaluation ne rassure pas vraiment.

Tant mieux pour nous, cela démontre l'intérêt d'intégrer les capteurs divers et variés à l'aide des produits Yoctopuce plutôt qu'en multipliant les solutions propriétaires faites de bric et de broc. Notre librairie de programmation est efficace, sans dépendance externe, et permet de lire tous types de capteurs depuis la plupart des langages de programmation. On peut même accéder aux capteurs à travers le réseau sans effort supplémentaire, alors à quoi bon se priver?

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.