Table des matières:

Système de surveillance de la qualité de l'air pour la pollution par les particules : 4 étapes
Système de surveillance de la qualité de l'air pour la pollution par les particules : 4 étapes

Vidéo: Système de surveillance de la qualité de l'air pour la pollution par les particules : 4 étapes

Vidéo: Système de surveillance de la qualité de l'air pour la pollution par les particules : 4 étapes
Vidéo: Le nouvel indice de qualité de l'air ATMO prend désormais en compte les particules les plus fines 2024, Juillet
Anonim
Système de surveillance de la qualité de l'air pour la pollution par les particules
Système de surveillance de la qualité de l'air pour la pollution par les particules
Système de surveillance de la qualité de l'air pour la pollution par les particules
Système de surveillance de la qualité de l'air pour la pollution par les particules

INTRO:

1 Dans ce projet, je montre comment construire un détecteur de particules avec affichage des données, sauvegarde des données sur carte SD et IOT. Visuellement, un affichage annulaire en néopixels indique la qualité de l'air.

2 La qualité de l'air est aujourd'hui une préoccupation de plus en plus importante. il existe des systèmes pour mesurer le taux de poussière mais ils sont très coûteux. Il existe sur le marché des détecteurs de particules bon marché et de haute qualité, comme le montrent certaines études.

par exemple:

www.atmos-meas-tech.net/11/4823/2018/amt-1…

3 J'ai donc décidé de construire un appareil capable de mesurer le nombre de particules par classes de taille (0,5µm à 10 µm), visuellement avec un simple affichage du résultat (néo pixel ring), un affichage plus détaillé sur un écran TFT et un sauvegarde horodatée sur une carte SD.

4 De plus j'ai ajouté un module de communication bluetooth pour pouvoir communiquer avec une application android et ainsi publier les résultats sur un serveur IOT.

5 Le coût global de l'ensemble ne dépasse pas 60 €

Fournitures

-Arduino uno R3

-Bouclier proto Arduino

-Écran TFT ST7735

-Anneau néopixel 24 led

-Plantower PMS5003

-Module bluetooth HC-06

Étape 1: connexion des composants

Connexion des composants
Connexion des composants

les différents composants sont connectés selon le schéma ci-dessus

Étape 2: Bibliothèque et programme Arduino

1 la bibliothèque

pour l'écran TFT

github.com/adafruit/Adafruit-GFX-Library

pour la bague neo pixel

github.com/adafruit/Adafruit_NeoPixel

pour la carte sd

github.com/arduino-libraries/SD

2 le croquis arduino

#include #include // Bibliothèque pour l'I2C #include "RTClib.h" // Bibliothèque pour le module RTC RTC_DS1307 RTC; #comprendre

// Quelle broche de l'Arduino est connectée aux NeoPixels ?

#define PIN 6 // Sur Trinket ou Gemma, suggérez de le changer en 1

// Combien de NeoPixels sont attachés à l'Arduino ?

#define NUMPIXELS 24 // Taille de bague NeoPixel populaire Adafruit_NeoPixel pixels (NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); uint32_t vert = pixels. Couleur (0, 250, 0); uint32_t orange = pixels. Couleur (250, 250, 0); uint32_t rouge = pixels. Couleur(255, 0, 0);

LogicielSérie pmsSerial(2, 3);

#define cs 10 #define dc 9 #define rst 8 // vous pouvez également le connecter à la réinitialisation Arduino

#include // Bibliothèque graphique principale

#include // Bibliothèque spécifique au matériel #include #include const int cs_sd=4; int temps; // temps d'acquisition double tempsInit; // initialisation du timer au démarrage de la boucle()

#si défini(_SAM3X8E_)

#undef _FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif

// Option 1: utiliser n'importe quelle broche mais un peu plus lentement

//Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);

// Option 2: doit utiliser les broches SPI matérielles

// (pour UNO c'est sclk = 13 et sid = 11) et la broche 10 doit être // une sortie. C'est beaucoup plus rapide - également requis si vous souhaitez // utiliser la carte microSD (voir l'exemple de dessin de l'image) Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); float nombre_leds=0; void setup() { Serial.begin(9600); // Initialise la liaison I2C Wire.begin(); // Initialise le module RTC RTC.begin(); Serial.print("init SD"); retard(1000); if(!SD.begin(cs_sd)) //Condition vérifiant si la carte SD est présente dans l'appareil { Serial.print("Defaut SD"); revenir; } Serial.print("Carte SD OK");

Données du fichier = SD.open("donnees.txt", FILE_WRITE); // Ouvre le fichier "donnees.txt"

data.println(""); data.println("Démarrage acquisition"); // Ecrit dans ce fichier data.close(); tft.initR(INITR_GREENTAB); // initialise une puce ST7735S, onglet noir Serial.println("init"); // notre sortie de débogage tft.fillScreen(ST7735_BLACK); // le débit en bauds du capteur est de 9600 pmsSerial.begin(9600);

pixels.begin(); // INITIALISER l'objet bande NeoPixel (OBLIGATOIRE)

pixels.setBrightness(2);

}

struct pms5003data {

uint16_t framelen; uint16_t pm10_standard, pm25_standard, pm100_standard; uint16_t pm10_env, pm25_env, pm100_env; uint16_t particules_03um, particules_05um, particules_10um, particules_25um, particules_50um, particules_100um; uint16_t inutilisé; somme de contrôle uint16_t; };

struct pms5003data data; boucle vide() { pixels.clear(); // Définit toutes les couleurs de pixels sur 'off' DateTime now=RTC.now(); //Récupère l'heure et la date courante //affiche_date_heure(now);

temps = ((millis() - tempsInit))/1000; // Démarrage du chrono

if (readPMSdata(&pmsSerial)) { // tft.fillScreen(ST7735_BLACK); tft.setCursor (10, 5); tft.setTextColor(ST7735_WHITE); tft.println(" nbre pièces/ 0,1 l");

tft.setCursor(10, 17); tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.setCursor (10, 17); tft.print("0.3 um ");tft.print(data.particles_03um);tft.print(" ");

tft.setCursor(10, 29);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("0,5 um ");tft.print(data.particles_05um);tft.print(" ");

tft.setCursor (10, 41);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("1.0 um ");tft.print(data.particles_10um);tft.print(" ");

tft.setCursor (10, 53);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("2,5 um ");tft.print(data.particles_25um);tft.print(" ");

tft.setCursor(10, 65);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("5.0 um ");tft.print(data.particles_50um);tft.print(" ");

tft.setCursor (10, 77);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("10 um ");tft.print(data.particles_100um);tft.print(" ");

tft.setCursor(2, 89);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("PM 1.0 ");tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);tft.print(data.pm10_standard);tft.print(" ");tft.setTextColor(ST7735_GREEN, ST7735_BLACK);tft.print(" microg/m3 ");

tft.setCursor(2, 100); tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("PM 2.5 ");tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);tft.print(data.pm25_standard);tft.setTextColor(ST7735_GREEN, ST7735_BLACK);tft.print(" microg/m3 ");

tft.setCursor(2, 110);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setTextSize(1); tft.print("PM 10 ");tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);tft.print(data.pm100_standard);tft.setTextColor(ST7735_GREEN, ST7735_BLACK);tft.print(" microg/m3 ");

tft.setCursor (10, 5);

tft.setTextColor(ST7735_WHITE, ST7735_BLACK); tft.setTextSize(1); tft.println(" nbre pièces/ 0,1 l");

// Serial.print(temps);

// Serial.print (" "); Serial.print ("#"); Impression.série ("03µm "); Serial.print(data.particles_03um); Serial.print (" "); Impression.série ("05µm "); Serial.print(data.particles_05um); Serial.print (" "); Serial.print ("1µm "); Serial.print(data.particles_10um); Serial.print (" "); Impression.série ("25µm "); Serial.print(data.particles_25um); Serial.print (" "); Impression.série ("50µm "); Serial.print(data.particles_50um); Serial.print (" "); Impression.série ("100µm "); Serial.print(data.particles_100um); Serial.println (" "); nombre_leds =int (((float (data.particles_03um)/65535)*24)); //nombre_leds =(8); Serial.println (nombre_leds);

si ((nombre_leds=1)){

pixels.fill(vert, 0, nombre_leds); } else if ((nombre_leds=8)) { pixels.fill(vert, 0, 8); pixels.fill(orange, 8, ((nombre_leds)-8)); } else if (nombre_leds>16) {

pixels.fill(vert, 0, 8); pixels.fill(orange, 8, 8); pixels.fill(rouge, 16, ((nombre_leds)-16)); } else if (nombre_leds<=1) { pixels.fill(vert, 0, 1); } pixels.show(); // Envoie les couleurs de pixels mises à jour au matériel.

// Définition des données String PM03=String(data.particles_03um); Chaîne PM05=Chaîne(data.particles_05um); Chaîne PM10=Chaîne(data.particles_10um); Chaîne PM25=Chaîne(data.particles_25um); Chaîne PM50=Chaîne(data.particles_50um); Chaîne PM100=Chaîne(data.particles_100um); Chaîne PMS10=Chaîne(data.pm10_standard); Chaîne PMS25=Chaîne(data.pm25_standard); Chaîne PMS100=Chaîne(data.pm100_standard); Chaîne Temps=Chaîne(temps);

//Ecriture des données dans le fichier texte

Données de fichier=SD.open("donnees.txt", FILE_WRITE); data.println(Temps + " " + PM03+ " " + PM05 +" " +PM10+" " +PM25+" "+PM50+" " +PM100+" "+PMS10+" "+PMS25+" "+PMS100+" "); data.close(); }

}

booléen readPMSdata(Stream *s) {

if (! s->available()) { return false; } // Lire un octet à la fois jusqu'à ce que nous arrivions à l'octet de début spécial '0x42' if (s->peek() != 0x42) { s->read(); renvoie faux; }

// Maintenant, lisez les 32 octets

if (s->available() readBytes(buffer, 32);

// prépare la somme de contrôle

for (uint8_t i=0; i<30; i++) { sum += buffer; }

/* débogage

pour (uint8_t i=2; i<32; i++) { Serial.print("0x"); Serial.print(tampon, HEX); Serial.print(", "); } Serial.println(); */ // Les données sont en endian, cela résout le problème afin que cela fonctionne sur toutes les plates-formes uint16_t buffer_u16[15]; pour (uint8_t i=0; i<15; i++) { buffer_u16 = buffer[2 + i*2 + 1]; buffer_u16 += (buffer[2 + i*2] << 8); }

// le mettre dans une belle structure:)

memcpy((void *)&data, (void *)buffer_u16, 30);

if (somme != data.checksum) {

Serial.println("échec de la somme de contrôle"); renvoie faux; } // Succès! renvoie vrai; }

//Converti le numéro de jour en jour /!\ la semaine commence un dimanche

String donne_jour_semaine(uint8_t j){ switch(j){ case 0: renvoie "DIM"; cas 1: retour « LUN »; cas 2: retour « MAR »; cas 3: retour « MER »; cas 4: retour « JEU »; cas 5: retour « VEN »; cas 6: retour « SAM »; par défaut: return " "; } }

// affiche la date et l'heure sur l'écran

void affiche_date_heure(DateTime datetime){ // Chaîne de date jour = donne_jour_semaine(datetime.dayOfTheWeek()) + " " + Vers2Chiffres(datetime.day())+ "/" + Vers2Chiffres(datetime.month())+ "/" + Chaîne(dateheure.année(), DEC); // heure String heure = ""; heure = Vers2Chiffres(dateheure.heure())+ ":" + Vers2Chiffres(dateheure.minute())+ ":" + Vers2Chiffres(dateheure.seconde());

Serial.print(jour); Serial.print(" "); Serial.print(heure); //Série.print(" "); Données de fichier=SD.open("donnees.txt", FILE_WRITE); data.print(jour + " " + heure+" "); data.close();

tft.setCursor(2, 120);

tft.setTextColor(ST7735_GREEN); tft.setTextSize(1); tft.print("date ");tft.setTextColor(ST7735_YELLOW);tft.print(jour);tft.setTextColor(ST7735_GREEN);tft.setCursor(2, 130);tft.print("heure");tft. setTextColor(ST7735_YELLOW);tft.print(heure);

retard (500);

}

//permet d'afficher les nombres sur deux chiffres

String Vers2Chiffres(byte nombre) { String resultat = ""; if(nombre < 10) resultat = "0"; return resultat += String(nombre, DEC); }

Étape 3: programme MIT App Inventor 2

Programme MIT App Inventor 2
Programme MIT App Inventor 2

c'est le bloc de code de l'inventeur de l'application MIT

Étape 4: LE RÉSULTAT

voici la vidéo du résultat

Conseillé: