# NextPM (Tera Sensor) Capteur de particules **Tera Sensor NextPM** : mesure PM1, PM2.5, PM10 en masse (µg/m³) et en nombre (#/cm³), intègre un capteur de température et d'humidité embarqué. Communication **UART**. ## Caractéristiques | Paramètre | Valeur | |------------------------|--------------------------------------------------| | Fabricant / modèle | Tera Sensor — NextPM | | Grandeurs | PM1, PM2.5, PM10 (µg/m³ et #/cm³), T (°C), HR (%) | | Plage PM | 0 – 1000 µg/m³ | | Alimentation | 5 V, ~100 mA pic, ~35 mA en veille | | Interface | UART 3V3 (logique CMOS 3.3 V tolérante 5 V TX) | | Vitesse UART par défaut | 115200 baud, 8N1 | | Datasheet | https://www.tera-sensor.com/ | ## Câblage Connecteur JST-PH 4 broches du NextPM (vue côté capteur) : | Pin capteur | Fil usuel | Fonction | MCU (exemple) | |-------------|-----------|----------------|------------------------| | 1 | Rouge | VCC 5 V | 5V | | 2 | Noir | GND | GND | | 3 | Blanc | RX capteur (← TX MCU) | UART TX du MCU | | 4 | Vert | TX capteur (→ RX MCU) | UART RX du MCU | > Le NextPM est en 3V3 côté logique : si le MCU est en 3V3 (nRF9151, ESP32…), connecter directement. Pour un MCU 5 V, prévoir un level shifter sur TX→RX. ## Protocole UART - 115200 bauds, 8 bits, pas de parité, 1 stop. - Toutes les trames commencent par **`0x81`** (préambule). - Checksum = `(256 - somme(octets précédents)) mod 256`, placé en dernier octet. - Délai de traitement côté capteur : 15–30 ms typique ; prévoir timeout de lecture de 200 ms. ### Structure des trames **Requête MCU → capteur** (sans données) : ``` +------+------+------+ | 0x81 | CMD | CS | +------+------+------+ ``` **Requête MCU → capteur** (avec données) : ``` +------+------+----------+------+ | 0x81 | CMD | DATA... | CS | +------+------+----------+------+ ``` **Réponse capteur → MCU** : ``` +------+------+-------+------------+------+ | 0x81 | CMD | STATE | DATA... | CS | +------+------+-------+------------+------+ ``` `STATE` (1 octet) est un bitfield d'état : | Bit | Signification | |-----|-------------------------------------------------| | 0 | Fan default (1 = vitesse dégradée / anormale) | | 1 | Memory error | | 2 | Sensor laser default | | 3 | T/RH sensor default | | 4 | Sleep mode | | 5–7 | Réservés | Un `STATE == 0x00` indique un fonctionnement nominal. ### Commandes principales | Commande | Code | Taille requête | Taille réponse | Notes | |-------------------------------|-------|----------------|----------------|----------------------------------------------| | Read concentrations 10 s | 0x11 | 3 | 16 | Moyenne glissante 10 s | | Read concentrations 60 s | 0x12 | 3 | 16 | Moyenne glissante 60 s (plus stable) | | Read concentrations 900 s | 0x13 | 3 | 16 | Moyenne glissante 15 min | | Read T/RH | 0x14 | 3 | 10 | Température et humidité | | Sleep (fan off) | 0x15 | 3 | 4 | Passe en veille, ventilateur coupé | | Wake / fan on | 0x16 | 3 | 4 | Sort de veille | | Set fan speed | 0x17 | 4 | 4 | 1 octet supplémentaire (% vitesse) | | Set clock | 0x21 | 9 | 4 | Horodatage interne | | Read firmware version | 0x41 | 3 | variable | Retourne une chaîne ASCII | > Les codes et tailles ci-dessus sont issus de l'intégration de référence. **Toujours recroiser avec la datasheet Tera Sensor la plus récente** avant d'implémenter une nouvelle version firmware — certains registres ont changé entre révisions hardware. ### Format de la réponse `0x11` / `0x12` / `0x13` 16 octets de DATA, big-endian : | Offset | Taille | Champ | Unité | Décodage | |--------|--------|-----------------------|---------------|-------------------------| | 0 | 2 | PM1 number | #/cm³ | valeur brute | | 2 | 2 | PM2.5 number | #/cm³ | valeur brute | | 4 | 2 | PM10 number | #/cm³ | valeur brute | | 6 | 2 | PM1 mass | µg/m³ × 10 | `raw / 10.0` | | 8 | 2 | PM2.5 mass | µg/m³ × 10 | `raw / 10.0` | | 10 | 2 | PM10 mass | µg/m³ × 10 | `raw / 10.0` | ### Format de la réponse `0x14` | Offset | Taille | Champ | Unité | Décodage | |--------|--------|---------------|--------------|---------------------------| | 0 | 2 | Température | °C × 100 | `raw / 100.0` (signed) | | 2 | 2 | Humidité | %HR × 100 | `raw / 100.0` | ## Exemple de code ### Construction de la requête (C) ```c #include #include static uint8_t nextpm_checksum(const uint8_t *buf, size_t len) { uint32_t sum = 0; for (size_t i = 0; i < len; i++) sum += buf[i]; return (uint8_t)(256 - (sum & 0xFF)); } // Envoie une commande sans données (0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x41) size_t nextpm_build_cmd(uint8_t cmd, uint8_t *out) { out[0] = 0x81; out[1] = cmd; out[2] = nextpm_checksum(out, 2); return 3; } ``` ### Décodage de la réponse 0x11 / 0x12 / 0x13 (Python) ```python import struct def decode_pm(frame: bytes) -> dict: if len(frame) != 16 or frame[0] != 0x81: raise ValueError("trame NextPM invalide") cmd, state = frame[1], frame[2] data = frame[3:15] cs_expected = (256 - sum(frame[:15])) & 0xFF if cs_expected != frame[15]: raise ValueError("checksum NextPM incorrect") pm1_n, pm25_n, pm10_n, pm1_m, pm25_m, pm10_m = struct.unpack(">HHHHHH", data) return { "state": state, "pm1_num": pm1_n, "pm25_num": pm25_n, "pm10_num": pm10_n, "pm1": pm1_m / 10.0, "pm25": pm25_m / 10.0, "pm10": pm10_m / 10.0, } ``` ## Mise en œuvre recommandée 1. Au boot : `0x16` (wake) puis laisser 30 s de stabilisation du flux avant de lire. 2. Utiliser `0x12` (moyenne 60 s) pour l'envoi réseau standard — meilleur compromis bruit/latence. 3. Loguer `STATE` à chaque lecture ; remonter au backend si `STATE != 0`. 4. En cas de cycle veille/mesure (ex. applications sur batterie) : `0x15` (sleep), attendre la prochaine fenêtre, `0x16`, 30 s stabilisation, lire, renvoyer en sleep. ## Pièges connus - Les **2 premières minutes** après le wake sont à ignorer (le ventilateur monte en régime, concentrations sous-estimées). - Si le checksum est faux une fois sur deux : vérifier la masse commune (GND) entre MCU et NextPM — flottement du GND observé sur certains câbles longs. - Le NextPM renvoie parfois un octet `0x00` avant le préambule si la ligne UART n'était pas propre au démarrage : implémenter une resynchronisation sur `0x81` côté parser MCU. ## Références - Datasheet : https://www.tera-sensor.com/ (demander la dernière révision PDF) - Code firmware de référence AirCarto : `nebuleair_pro_4g` et `esp32_NPM_only` sur [gitea.aircarto.fr](https://gitea.aircarto.fr/PaulVua). ## Historique | Date | Révision | Changement | |------------|----------|---------------------------------| | 2026-04-23 | v1 | Création de la doc. |