Nouveau capteur de qualité d'air CCS811 sur le bus I2C, calqué sur le pattern S88 (local-only, pas encore dans le payload de transmission). - CCS811/get_data.py (lecture live) + write_data.py (timer 10s, self-heal table) - table data_CCS811 (timestamp, eCO2, TVOC) dans create_db.py - config CCS811 (bool) + CCS811_address (0x5A/0x5B, défaut 0x5A) dans set_config.py - service+timer systemd nebuleair-ccs811-data (10s) + ajout boucle d'activation - admin.html: case d'activation + dropdown adresse I2C - sensors.html: carte Get Data (TVOC + eCO2) - database.html + launcher.php: consultation/export/stats data_CCS811 - lib adafruit-circuitpython-ccs811 dans installation_part1.sh - CCS811/README.md: câblage, adresses, warning clock-stretching I2C sur Pi - CLAUDE.md + changelog mis à jour Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
84 lines
3.3 KiB
Markdown
84 lines
3.3 KiB
Markdown
# CCS811 — Capteur qualité d'air (eCO2 / TVOC)
|
||
|
||
Capteur de gaz **MOX** (oxyde métallique) AMS CCS811. Connecté en **I2C**.
|
||
|
||
## ⚠ À lire avant de câbler
|
||
|
||
Le CCS811 **n'est pas** un capteur CO2 NDIR comme le Senseair S88. C'est un capteur
|
||
de COV (composés organiques volatils) qui mesure :
|
||
|
||
- **TVOC** (Total Volatile Organic Compounds) — en **ppb**. C'est la mesure réellement
|
||
utile / fiable du capteur, et celle qui nous intéresse ici.
|
||
- **eCO2** (CO2 *équivalent*) — en **ppm**, plage 400–8192. Valeur *calculée* à partir
|
||
du TVOC par un algorithme interne, ce **n'est pas** une mesure directe du CO2. Pour
|
||
un vrai CO2, utiliser le S88. On stocke quand même l'eCO2 (gratuit, vient de la même
|
||
lecture) mais ne pas le confondre avec une mesure NDIR.
|
||
|
||
## ⚠ Clock-stretching I2C sur Raspberry Pi
|
||
|
||
Le CCS811 utilise massivement le **clock-stretching** I2C. Le contrôleur I2C matériel
|
||
du Raspberry Pi (BSC) gère **mal** le clock-stretching (bug matériel documenté). Sans
|
||
mitigation, les lectures échouent typiquement en `OSError` / `Remote I/O error`.
|
||
|
||
**Mitigation** : ralentir le bus I2C dans `/boot/firmware/config.txt` :
|
||
|
||
```
|
||
dtparam=i2c_arm_baudrate=10000
|
||
```
|
||
|
||
(10 kHz au lieu de 100 kHz par défaut.) Reboot ensuite. À valider au bench — sur
|
||
certains modules/CM4 ça passe à 100 kHz, sur d'autres non.
|
||
|
||
Vérifier la présence du capteur :
|
||
|
||
```bash
|
||
sudo i2cdetect -y 1 # doit montrer 5a (ou 5b selon la broche ADDR)
|
||
```
|
||
|
||
## Adresse I2C
|
||
|
||
- **0x5A** : ADDR à GND — défaut des breakouts **Adafruit**. Valeur par défaut du firmware.
|
||
- **0x5B** : ADDR à VDD — défaut des breakouts **SparkFun** / modules génériques.
|
||
|
||
Configurable dans `admin.html` (clé config `CCS811_address`, dropdown 0x5A / 0x5B).
|
||
|
||
## Câblage I2C
|
||
|
||
| CCS811 | Raspberry Pi |
|
||
|---|---|
|
||
| VCC / VIN | 3.3V |
|
||
| GND | GND |
|
||
| SDA | SDA (GPIO2) |
|
||
| SCL | SCL (GPIO3) |
|
||
| WAK / nWAKE | GND (réveil permanent ; sinon laisser le module gérer) |
|
||
| ADDR | GND → 0x5A, VDD → 0x5B |
|
||
|
||
⚠ La plupart des breakouts CCS811 sont en **3.3V** logique. Ne pas alimenter en 5V
|
||
sans level-shifter sauf si le module embarque son propre régulateur + shifter.
|
||
|
||
## Burn-in / conditionnement
|
||
|
||
- **Burn-in initial** : ~48 h de fonctionnement continu avant des valeurs stables (1ère mise en service).
|
||
- **Warm-up** à chaque démarrage : ~20 min pour des valeurs fiables. Au démarrage le
|
||
capteur renvoie souvent eCO2=400 ppm / TVOC=0 ppb (valeurs de repos).
|
||
|
||
## Implémentation NebuleAir
|
||
|
||
- `CCS811/get_data.py` — lecture live (bouton "Get Data" du web). Affiche
|
||
`{"eCO2": <ppm>, "TVOC": <ppb>}` ou `{"error": "..."}`.
|
||
- `CCS811/write_data.py` — lecture périodique (timer systemd, toutes les 10 s),
|
||
écrit dans la table `data_CCS811 (timestamp, eCO2, TVOC)`.
|
||
|
||
Librairie Python : `adafruit-circuitpython-ccs811` (installée par
|
||
`installation_part1.sh`). La table est créée par `sqlite/create_db.py` et
|
||
self-healée par `write_data.py` (CREATE TABLE IF NOT EXISTS) — garder les deux
|
||
schémas synchro.
|
||
|
||
Activation : `admin.html` → case "Send VOC sensor data (CCS811)".
|
||
|
||
### Pistes d'amélioration (non implémentées)
|
||
|
||
Le CCS811 supporte une compensation température/humidité (`SET_ENV_DATA`). Comme le
|
||
boîtier embarque déjà un BME280, on pourrait lui pousser temp/hum à chaque lecture
|
||
pour améliorer la précision. Non fait en v1 pour garder le script simple et autonome.
|