Bentolux - Module qualité de l'air ambiant

Auteur avatarHank | Dernière modification 16/06/2022 par Hank

L'objectif de ce projet est de fabriquer et programmer un module de contrôle de qualité de l'air ambiant (TVOC et eCO2) qui viendra se greffer en tant que 3eme étage sur une station météo Bentolux, et qui permettra l'affichage des valeurs sur deux demi-cadrans faussement analogiques.

Introduction

La Bentolux est une station météo construite dans le cadre des cours de fabrication numérique dispensés par l'IMT d'Albi. Elle est d'abord constitué de deux premiers étages, qui sont le socle commun à tout les apprenants. Le premier étage contient la carte Arduino, une Led actionnée par potentiomètre, ainsi qu'un écran d'affichage LCD. Le second étage comporte le capteur météo dont les valeurs ( Temperature, hygrometrie relative et pression atmosphériques) sont envoyés vers l'écran LCD., ainsi qu'un anneau de Led permettant des animations visuelles en fonction des valeurs retournées. Le 3eme étage, objet de ce tuto, vise a afficher grâce a des servomoteurs les valeurs de eCO2 et de TVOC sous la forme de cadran à aiguilles.

Video d'introduction

[[File:{{{mp4video}}}]]

Étape 1 - Matériaux et outils

Outils

- Fer à souder

- Pince coupante

- Pince à dénuder

- Multimètre

- Colle cyanoacrylate

- Cintreuse

- Scie japonaise

- Ciseaux


Matériaux:

- Etain

- Un carrelet de méranti blanc

- Un carrelet d'acajou

- Une plaque d'isorel


Composants:

- arduino UNO

- 20 cables M/M

- 10 cables M/F

- 2 servomoteur DF9GMS

- 1 plaque de prototypage

- 1 potentionmetre

- 1 Led Blanche

- 1 Afficheur OLED 0,96'' I2C TF052

- 1 Anneau NeoPixel 12 leds RGB ADA1643

- 1 capteur pression/temp/hum BME280

- 1 Capteur de qualité d'air CCS811 SEN0339

- 4 Wago 5 entrées

- 2 Wago 3 entrées


Étape 2 - Prérequis - Bentolux Station Météo

  • Decoupe au laser des parois de la boite (DOC1)
  • Assemblage de la boite (DOC2)
  • Branchement des composants (DOC3)
  • Programmation du code pour faire interagir les élements (ecran LCD, capteur Temp/Hum, anneau OLED) (DOC4)


Étape 3 - Cablage

A partir du plan de cablage fourni à l'étape 1, il nous faut rajouter

- relier 1 Wago 5 entrée au premier Wago ou se rejoignent les alimentations des composants

- relier 1 Wago 5 entrées au premier Wago ou se rejoignent les GND des differents composants.

- relier 1 Wago 3 entrées à la broche SDL de la carte Arduino

- relier 1 Wago 3 entrées à la broche SDA de la carte Arduino


- Sur les Wago 5 entrées, brancher les VCC et GND des servomoteurs et du CSS811.

- Sur les bornes restantes des Wago 3 entrées, brancher les SDA et SCL du CSS811 et du BME 280.



Étape 4 - Code

  1 // librairies pour le BME
  2 #include <BME280I2C.h>
  3 #include "DFRobot_CCS811.h"
  4 #include <Wire.h>
  5 #include "ssd1306.h"
  6 #include "FastLED.h"
  7 #include "DFRobot_CCS811.h"
  8 #include <Servo.h>
  9 //ici le nombre total de leds
 10 #define NUM_LEDS 12
 11 // ici la pin pour les leds
 12 #define DATA_PIN 6
 13 // déclaration d'un tableau pour les leds
 14 CRGB leds[NUM_LEDS];
 15 DFRobot_CCS811 CCS811;
 16 Servo ServoCO2;
 17 Servo ServoTVOC;
 18 
 19 const int POTAR = A0; // broche du potar
 20 const int LED = 9; // broche de la LED
 21 int valPOTAR = 0; //RAZ valeur
 22 
 23 int angle=120;
 24 int angle2=0;
 25 
 26 BME280I2C::Settings settings(
 27    BME280::OSR_X1,
 28    BME280::OSR_X1,
 29    BME280::OSR_X1,
 30    BME280::Mode_Forced,
 31    BME280::StandbyTime_1000ms,
 32    BME280::Filter_Off,
 33    BME280::SpiEnable_False,
 34    0x77 // I2C address. I2C specific.
 35 );
 36 
 37 BME280I2C bme(settings);
 38 
 39 /* Ces tableaux de caractères serviront UNIQUEMENT pour l'affichage à l'écran.
 40  *  Il faudra afficher ces variables et non les "floats" déclarées pour le capteur,
 41  *  l'écran ne reconnaissant que des chaînes de caractère
 42  */
 43 
 44   char tempC[9];
 45   char humC[10];
 46   char presC[11];
 47 
 48 void setup()
 49 {
 50       Serial.begin(9600);
 51       ServoCO2.attach(5);
 52       ServoTVOC.attach(3);
 53 
 54 // on vérifie que le capteur COE2/TVOC est branché
 55    while(CCS811.begin() != 0){
 56         Serial.println("failed to init chip, please check if the chip connection is fine");
 57         delay(1000);
 58     }
 59 
 60 // déclaration entrée et sortie de Potar et LED. Lecture en enregistrement dans la variable valPOTAR de la valeur analog du Potar
 61       
 62       pinMode(POTAR, INPUT);
 63       pinMode (LED, OUTPUT);
 64       valPOTAR = analogRead (POTAR);
 65 
 66 // tout ce blabla sert uniquement à vérifier si un capteur est présent et bien branché 
 67 
 68   while(!Serial) {} // Wait
 69 
 70   Wire.begin();
 71 
 72   while(!bme.begin())
 73   {
 74     Serial.println("Could not find BME280 sensor!");
 75     delay(1000);
 76   }
 77 
 78   // bme.chipID(); // Deprecated. See chipModel().
 79   switch(bme.chipModel())
 80   {
 81      case BME280::ChipModel_BME280:
 82        Serial.println("Found BME280 sensor! Success.");
 83        break;
 84      case BME280::ChipModel_BMP280:
 85        Serial.println("Found BMP280 sensor! No Humidity available.");
 86        break;
 87      default:
 88        Serial.println("Found UNKNOWN sensor! Error!");
 89   }
 90 
 91      // on lance l'écran et on le colore de noir
 92     
 93     ssd1306_128x64_i2c_init();
 94     ssd1306_fillScreen(0x00);
 95     // on lance la typo
 96     ssd1306_setFixedFont(ssd1306xled_font6x8);
 97 
 98     FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
 99       // on peut régler ici la luminosité : 0-255
100       LEDS.setBrightness(50);
101 
102 }
103 
104 void loop()
105 
106   {
107 
108     analogRead (A0);
109     valPOTAR = analogRead (POTAR);
110     analogWrite (9, valPOTAR/4);
111     // On déclare 3 variables : température, humidité, pression
112      float temp(NAN), hum(NAN), pres(NAN);
113 
114        if(CCS811.checkDataReady() == true){
115         Serial.print("CO2: ");
116         Serial.print(CCS811.getCO2PPM());
117         Serial.print("ppm, TVOC: ");
118         Serial.print(CCS811.getTVOCPPB());
119         Serial.println("ppb");
120         delay(1000);
121 
122     } else {
123         Serial.println("Data is not ready!");
124     }
125 
126 
127    // Déclenchement du capteur
128    BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
129    BME280::PresUnit presUnit(BME280::PresUnit_hPa);
130    bme.read(pres, temp, hum, tempUnit, presUnit);
131 
132  // ces lignes servent à convertir les valeurs "float" du capteur en "char" destinées à l'écran
133  // (utile uniquement pour votre code final)
134   dtostrf (temp,5,1,tempC); 
135   dtostrf (hum,5,1,humC); 
136   dtostrf (pres,5,2,presC);
137 
138 // on imprime les valeurs sur le moniteur série
139 
140   if(CCS811.checkDataReady() == true){
141         Serial.print("CO2: ");
142         Serial.print(CCS811.getCO2PPM());
143         Serial.print("ppm, TVOC: ");
144         Serial.print(CCS811.getTVOCPPB());
145         Serial.println("ppb");
146 
147     } else {
148         Serial.println("Data is not ready!");
149     }
150     /*!
151      * @brief Set baseline
152      * @param get from getBaseline.ino
153      */
154     CCS811.writeBaseLine(0x447B);
155     //delay cannot be less than measurement cycle
156     delay(1000);
157 
158     // Première ligne, normal
159    
160     ssd1306_printFixed (0, 8, "Temp:", STYLE_NORMAL);
161    ssd1306_printFixed(56, 8, tempC , STYLE_BOLD);
162    ssd1306_printFixed (96, 8, "C", STYLE_NORMAL);
163    ssd1306_printFixed(0, 16,"RH: ", STYLE_NORMAL);
164    ssd1306_printFixed(56, 16, humC , STYLE_BOLD);
165    ssd1306_printFixed(96, 16,"%", STYLE_NORMAL);
166    ssd1306_printFixed(0, 24, "Pres: ", STYLE_NORMAL);
167    ssd1306_printFixed(56, 24, presC , STYLE_BOLD);
168    ssd1306_printFixed(96, 24, "hPa" , STYLE_NORMAL);
169   
170 
171     
172 int CO2;
173 CO2 = map (CCS811.getCO2PPM(),400,6000,0, 120);
174 
175     for (int position=angle; position < CO2 ; position++) {
176     ServoCO2.write(position);
177      Serial.println(position);
178       angle = position;
179     delay(20);
180   } 
181   for (int position=angle ; position > CO2 ; position--) {
182     ServoCO2.write(position);
183      Serial.println(position);
184      angle = position;
185     delay(20);
186   }
187 
188 int TVOC;
189 TVOC = map (CCS811.getTVOCPPB(),8000,0,0, 120);
190 
191      for (int position=angle2; position < TVOC ; position++) {
192     ServoTVOC.write(position);
193      Serial.println(position);
194       angle2 = position;
195     delay(20);
196   } 
197   for (int position=angle2 ; position > TVOC ; position--) {
198     ServoTVOC.write(position);
199      Serial.println(position);
200      angle2 = position;
201     delay(20);
202   }
203 
204 
205 
206    if (hum > 40 && hum <50)
207    {
208     //Allumage rotatif des Leds 0 à 5 en bleu suivant valeur de délais  
209    
210  for( int i = 0; i < 12; i++){
211       leds[i] = CRGB::Green;
212        FastLED.show();
213         delay (60); 
214         }
215         for( int i = 0; i < 12; i++){
216      leds[i] = CRGB::Black;
217       FastLED.show();
218         delay (20);
219         }
220  }
221    else {
222   //Allumage rotatif des Leds 6 à 11 en rouge suivant valeur de délais
223  for( int i = 0; i < 12; i++){
224       leds[i] = CRGB::Red;
225         FastLED.show();
226         delay (20);
227         }
228  }
229  // Extinction rotative des 12 Led suivant valeur de délais
230  for( int i = 0; i < 12; i++){
231      leds[i] = CRGB::Black;
232       FastLED.show();
233         delay (10);
234         }
235   }

Étape 5 - Support décoratif en bois

Étape 6 - Impression 3D

-Impression 3D de supports de servomoteur. STL récupéré sur Thingiverse.

- Impression 3D d'un dessin perso de bouton de potentiometre

Commentaires

Published