Système de surveillance de la qualité de l'air pour ville intelligente basé sur LoRa
Composants et matériaux
| Composant | Quantité |
|---|---|
| Arduino UNO | 1 |
| Seeed Base Shield V2 | 1 |
| NodeMCU ESP8266 Breakout Board | 1 |
| Capteur de bruit Seeed Grove | 1 |
| Capteur de qualité de l'air Seeed Grove v1.3 | 1 |
| Capteur température/humidité Seeed Grove (DHT11) | 1 |
| Module LoRa Reyax | 1 |
| Panneau solaire Seeed 80x100mm 1W | 1 |
| Seeed LiPo Rider Pro | 1 |
| Batterie rechargeable 3,7 V | 1 |
Outils et équipement nécessaires
- Imprimante 3D (générique)
Logiciels et services en ligne
- Arduino IDE
- Grandeur (plateforme IoT backend)
- Grandeur Canvas (constructeur de tableau de bord)
Présentation du projet
Ville intelligente et qualité de l'air
Selon la Banque mondiale, une ville intelligente exploite la technologie pour fournir des services publics hautement efficaces et un environnement urbain durable. Au cœur de cette vision se trouve la surveillance environnementale en temps réel, qui permet d'identifier les sources de pollution et d'éclairer les décisions politiques basées sur les données — qu'il s'agisse d'optimiser les flux de trafic ou de conseiller les habitants sur les itinéraires piétonniers les plus sûrs.
Problématique et solution
La pollution atmosphérique urbaine représente un risque majeur pour la santé, et des données opportunes sont essentielles pour l'atténuer. Les réseaux IoT de nœuds capteurs à faible coût peuvent capturer en continu les paramètres de qualité de l'air et météorologiques. Combinés à une couche de communication fiable et basse consommation, ces réseaux permettent aux autorités de détecter les points chauds de pollution et de réagir de manière proactive.
Plan du projet
Notre solution surveille des indicateurs environnementaux clés — bruit, température, humidité et qualité de l'air — et transmet les données sans fil vers une plateforme cloud. Le nœud entier est alimenté par un panneau solaire de 1 W avec une batterie Li-ion de secours, garantissant un fonctionnement autonome. Un tableau de bord cloud visualise les données en temps réel, facilitant les analyses immédiates et le suivi des tendances sur le long terme.
Au lieu de connecter chaque capteur directement au cloud — une approche qui augmente la consommation d'énergie et les coûts — nous agrégeons les données de plusieurs nœuds proches et les transmettons via une unique passerelle LoRa. La portée longue et la faible consommation de LoRa le rendent idéal pour les déploiements urbains denses.

Nous avons choisi Grandeur comme plateforme backend pour ses SDK conviviaux pour Arduino, NodeMCU et Raspberry Pi, ainsi que pour son constructeur de tableau de bord par glisser-déposer.
L'énergie solaire offre une source d'alimentation durable et sans maintenance pour les nœuds distants, tandis que la batterie Li-ion assure le fonctionnement pendant les périodes d'ensoleillement faible.
Construction du nœud capteur
Le nœud intègre un capteur de qualité de l'air Grove, un capteur de bruit Grove et un capteur température/humidité DHT11 — tous se branchent sur le Seeed Base Shield sans soudure, simplifiant l'assemblage et la maintenance.

L'alimentation est assurée par un panneau solaire de 1 W et un chargeur Seeed LiPo Rider Pro, qui intègre un convertisseur boost 5 V pour maintenir l'Arduino dans sa plage de tension de fonctionnement.
Le transceiver LoRa Reyax RYLR998 gère la transmission sans fil. Comme le module accepte une logique 3,6 V, un simple pont diviseur de tension protège la ligne TX 5 V de l'Arduino.

Ci-dessous, le schéma de câblage reliant le module LoRa au Base Shield via un adaptateur personnalisé.

Lors de la connexion du module LoRa, assurez-vous que le commutateur d'alimentation du Base Shield est positionné sur 3,3 V.

Après l'assemblage, vérifiez la communication en envoyant une commande AT depuis l'Arduino vers le module LoRa.

Téléversement et test
Téléversez le sketch Arduino fourni, puis ouvrez le moniteur série pour confirmer que les relevés des capteurs sont transmis correctement.

Assemblage du boîtier
Imprimez les fichiers STL fournis dans la section pièces jointes. Après vérification de l'ajustement, assemblez les composants à l'intérieur du boîtier à l'aide de ruban double face ou de colle chaude. Fixez le panneau solaire sur le dessus et faites passer les câbles d'alimentation par le trou prévu.


Une fois tous les composants fixés, le nœud est prêt pour le déploiement sur le terrain.

Configuration de Grandeur
Grandeur est un backend IoT qui associe les appareils aux utilisateurs et fournit un tableau de bord en temps réel. Suivez ces étapes pour configurer votre projet :
- Créez un nouveau projet sur grandeur.dev.
- Enregistrez un compte utilisateur ; ce compte sera utilisé pour associer les appareils plus tard.
- Définissez un modèle d'appareil avec le schéma JSON :
{"temp":0, "humid":0, "air":0, "noise":0} - Instanciez un appareil, récupérez son identifiant unique et son jeton d'accès, et stockez-les pour le firmware Arduino.
- Associez l'appareil à l'utilisateur via le tableau de bord ou l'API (ex.
pairDevice()). - Construisez un tableau de bord Canvas : ajoutez quatre widgets graphiques — un pour la température, l'humidité, le niveau de bruit et la qualité de l'air — et liez-les aux variables correspondantes.
Une fois Canvas autorisé, les utilisateurs peuvent se connecter pour visualiser les données en direct. La clé API et le jeton d'appareil sont requis dans le firmware de la passerelle.
Préparation de la passerelle IoT LoRa
Le NodeMCU agit comme passerelle LoRa, recevant les données UART du nœud capteur et les transmettant à Grandeur via Wi-Fi. Bien qu'un Raspberry Pi puisse remplir ce rôle, le NodeMCU offre une solution compacte et peu coûteuse qui répond aux exigences de bande passante et de latence du projet.

Firmware de la passerelle
Le firmware analyse la charge utile reçue du module LoRa (séparée par des virgules), convertit chaque valeur en float et l'envoie à Grandeur via le SDK fourni. Voici la logique principale d'extraction et de transmission des données :
void process_received_data(){ start_pos = inputString.indexOf(start_val); end_pos = inputString.indexOf(end_val); String data_string = inputString.substring(start_pos+1, end_pos-1); int firstCommaIndex = data_string.indexOf(','); int secondCommaIndex = data_string.indexOf(',', firstCommaIndex+1); int thirdCommaIndex = data_string.indexOf(',', secondCommaIndex+1); String temperature = data_string.substring(0, firstCommaIndex); String humidity = data_string.substring(firstCommaIndex+1, secondCommaIndex); String noise_level = data_string.substring(secondCommaIndex+1, thirdCommaIndex); String air_auality = data_string.substring(thirdCommaIndex+1); temp = temperature.toFloat(); humid = humidity.toFloat(); noise = noise_level.toFloat(); air = air_auality.toFloat(); inputString = ""; stringComplete = false; }
Visualisation du tableau de bord


Code firmware
- Code du nœud capteur
- Code de la passerelle
Nœud capteur (Arduino)
#include "AirQuality.h" // Bibliothèque Grove air quality
#include "Arduino.h"
#include "DHT.h"
#define DHTPIN 4 // Broche digitale pour DHT11
#define DHTTYPE DHT11 // Modèle de capteur
DHT dht(DHTPIN, DHTTYPE);
AirQuality airqualitysensor;
int current_quality =-1;
const int sampleWindow = 50; // Échantillonnage 20 Hz
unsigned int sample;
float noise;
float temp, humid;
int airQuality;
void setup() {
Serial.begin(115200); // UART pour LoRa
airqualitysensor.init(14);
dht.begin();
}
void loop() {
noise = calculate_sound_in_db();
airQuality = calculate_air_quality();
calculate_temp_humid();
String values = String(temp)+","+String(humid)+","+String(noise)+","+String(airQuality);
String cmd = "AT+SEND=0,"+String(values.length())+","+values;
Serial.println(cmd);
delay(15000);
}
float calculate_sound_in_db(){
unsigned long startMillis= millis();
float peakToPeak = 0;
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
while (millis() - startMillis < sampleWindow){
sample = analogRead(A1);
if (sample < 1024){
if (sample > signalMax) signalMax = sample;
else if (sample < signalMin) signalMin = sample;
}
}
peakToPeak = signalMax - signalMin;
float db = map(peakToPeak,0,1000,48,120);
return db;
}
int calculate_air_quality(){
current_quality=airqualitysensor.slope();
return current_quality;
}
void calculate_temp_humid(){
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) return;
temp = t;
humid = h;
}
ISR(TIMER1_OVF_vect){
if(airqualitysensor.counter==61){
airqualitysensor.last_vol=airqualitysensor.first_vol;
airqualitysensor.first_vol=analogRead(A0);
airqualitysensor.counter=0;
airqualitysensor.timer_index=1;
PORTB=PORTB^0x20;
}else{
airqualitysensor.counter++;
}
}
Passerelle (Arduino)
/* Inclusion du SDK et de la bibliothèque WiFi */ #include#include #include SoftwareSerial LORA(D7, D8); /* Configurations */ String deviceID = "your device id"; String apiKey = "your api key"; String token = "your device token"; /* Identifiants WiFi */ String ssid = "your wifi ssid"; String password = "your wifi password"; /* Variables pour le projet et l'appareil */ Grandeur::Project project; Grandeur::Project::Device device; /* Variable pour suivre l'état de connexion et le temps */ int connected = 0; uint32_t lastUpdate = 0; String inputString = ""; // chaîne pour stocker les données entrantes boolean stringComplete = false; // indique si la chaîne est complète // : et % étaient définis depuis le nœud émetteur pour la séparation des données char start_val = ':'; char end_val = '%'; int start_pos = 0; int end_pos = 0; float temp = 0; float humid = 0; float air = 0; float noise = 0; /* Fonction pour vérifier l'état de connexion de l'appareil */ void onConnection(bool status) { switch(status) { case CONNECTED: Serial.println("Device is connected to the cloud."); connected = 1; lastUpdate = millis(); return; case DISCONNECTED: Serial.println("Device is disconnected from the cloud."); connected = 0; return; } } /* Fonction pour se connecter au WiFi */ void connectWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println(WiFi.localIP()); } /* Fonction pour confirmer la mise à jour des données */ void dataCallback(const char* code, Var res) { if(code == "DEVICE-DATA-UPDATED") { double temp_data = (double) res["update"]["temp"]; double humid_data = (double) res["update"]["humid"]; double noise_data = (double) res["update"]["noise"]; double air_data = (double) res["update"]["air"]; Serial.printf("Temperature: %f Humidity: %f Noise Level: %f Air Quality: %f\n", temp_data, humid_data, noise_data, air_data); return; } Serial.println("Failed to Update DATA"); return; } /* Fonction pour envoyer les relevés mis à jour */ void sendUpdate() { Var data; data["temp"] = temp; data["humid"] = humid; data["noise"] = noise; data["air"] = air; device.data().set("temp", temp, dataCallback); device.data().set("humid", humid, dataCallback); device.data().set("noise", noise, dataCallback); device.data().set("air", air, dataCallback); } void setup() { Serial.begin(9600); LORA.begin(115200); inputString.reserve(200); connectWiFi(); project = grandeur.init(apiKey, token); device = project.device(deviceID); project.onConnection(onConnection); } void loop() { serialEvent(); project.loop(WiFi.status() == WL_CONNECTED); if (stringComplete) { process_received_data(); if (connected) sendUpdate(); } } void serialEvent() { while (LORA.available()) { char inChar = (char)LORA.read(); if (inChar == '\n') { stringComplete = true; } else inputString += inChar; } }
Processus de fabrication
- De minuscules capteurs PM2,5 et VOC offrent un monitoring personnel de la qualité de l'air en temps réel
- Renesas enrichit sa plateforme capteur qualité d'air intérieur ZMOD4410 avec IA embarquée pour une détection d'odeurs améliorée
- Mesurer la qualité de l'air avec OpenSensors : Guide Arduino et Python
- Moniteur de qualité de l'air DIY : Détecteur économique conforme EPA
- Capteur de qualité de l'air solaire basé sur Helium : Guide de conception et déploiement
- Les capteurs IoT révolutionnent la surveillance de la pollution atmosphérique et la santé publique
- Surveillance de la qualité de l'air ambiant par IoT : Sécurité, productivité et durabilité
- Surveillance de la qualité de l'air industriel par IoT : augmenter la productivité et réduire les coûts
- Capteur NO₂ avancé à base de carbone pour une surveillance de la qualité de l'air intérieur améliorée