Le mois de Décembre a été principalement caractérisé par l'élaboration d'un banc de test ayant pour but d'évaluer chacun des capteurs fournis par le PMClab.
Pour caractériser un capteur, l'utilisation d'instrument de mesure servant de référence est essentiel. Le LATMOS possède des outil de précision et calibré récemment, destinés à la mesure de particules fines, d'ozones et de dioxyde d'azote. Chacun de ces instruments a été répertorié dans le tableau qui suit
description_des_instruments_de_reference.pdf
Le LATMOS possède 2 OSIRIS, 1 DUSTMATE, 2 POM et 1 NOx.
Même si la qualité de ces appareils semble satisfaisante, il conviendra, au préalable, de comparer les résultats obtenus par les instruments du LATMOS avec les mesures effectuées par AirParif. Des campagnes seront ainsi prévues afin de vérifier la précision des outils de références.
Les équipement du Fablab (découpe laser, photogravure, etc) seront utilisé pour mettre en place une enceinte de test dans laquelle les différents capteur seront testé et étalonnés.
On se propose ici d’effectuer l’étude de différents capteurs de gaz et de particules fines. En effet pour l’élaboration de nos capteurs il est intéressant d’avoir une indication sur le taux de NO2, d’ozone et des micro particules contenus dans l’air. L’objectif est de récupérer les données de ces capteurs et de tester leurs exactitudes.
Le Fablab possède différents capteurs de gaz qu'il est intéressant de tester:
Nom | Fonction |
MSQ-131 | Détecteur de NO2, O3 et CL2 |
MICS-2714 | Détecteur de NO2 et H2 |
SGX-4NO2 | Détecteur de NO2 |
MICS-2614 | Détecteur de O3 |
SHARP GP2Y1010AU0F | Détecteur de PM 2.5 |
SHINYEI PPD42NS | Détecteur de PM 2.5 |
L’idée est de concevoir une expérience permettant de comparer deux capteurs différents. Le processus envisagé pour chacun des éléments sera le suivant. On prend pour chacun des produits à comparer au minimum 3 échantillons différents. On connecte tout ces échantillons à une Arduino Uno et on effectue les mesures pour une durée de quelques jours. Un instrument de mesure plus précis sera aussi installé pour cette même durée afin d’obtenir des résultats de référence. Il est possible d’émettre au cours du test différentes contraintes significative afin d’observer la réaction de chacun des éléments à tester.
Un capteur de particule, comme son nom l'indique, permet de détecter les micro-poussières susceptibles d'avoir des effets néfaste sur la santé.Ce composant est constitué d'un laser émettant un rayon au travers d'une cuve contenant un échantillon d'air. En rencontrant une particule le laser sera plus ou moins diffracté (angle et intensité différentes). C'est en captant ces rayons dérivés avec une photodiode qu'il sera possible de détecter la quantité de particule.
D'un point de vue de l'électronique, le signal optique du laser est récupéré par une photodiode qui converti le signal optique en signal électrique. Ce signal sera ensuite amplifié puis filtré avant d'être envoyé à la sortie. Selon la valeur de la tension on pourra déterminer la concentration de particules dans l'aire après traitement par microcontrôleur.
Pour chacun des composants à tester les branchements sont explicités dans la datasheet.
Pour le SHARP, l'élément est alimenté avec 6 broches: 3 pour la LED et 3 pour le récepteur. Des connecteurs S6B-ZR-SM4A-TF sont utilisés pour ce type de communications. Il est assez contraignant d'utiliser ce type de connexion, il convient donc de réfléchir à une solution plus simple d'utilisation. Ainsi, pour nos tests on observera les résultats avec les nappes du S6B-ZR-SM4A-TF d'une part et avec de simples fils souder sur le PCB d'autre part afin de déterminer l'impact de la connectique sur les résultats.
Les connections sur la LED sont définis de la manière suivante:
Un signal créneau doit être envoyé sur la patte 3 du composant afin d'activer la diode. De même on s'assurera qu'une capa ainsi qu'une résistance sont bien reliées sur la première pin du capteur.
Concernant le SHINYEI, le branchement est “plus classique” avec uniquement une broche pour l'alimentation, une pour la masse et une dernière pour le signal à récupérer. Le taux de particule sera donnée en mesurant la durée pour laquelle le signal mesuré est à l'état bas sur une période données.
Pour chacun des capteurs c'est la carte Arduino Uno qui est utilisée pour le traitement des données. Le stockage sera quant à lui réalisé sur une carte SD. La partie matériel étant définie il convient désormais de définir le code utilisé par l'Arduino.
De part la nature du signal à mesurer on aura deux codes différents selon le capteur. Pour chacun la dernière version est décrite dans l'architecture qui suit:
''//capteur sharp'' #include <SPI.h> #include <SD.h> //déclaration PIN int capteur;//sortie capteur int sd_cs=4; // carte sd commande int sd_mosi=11; int sd_miso=12; int sck_sd=13; //Alim Led int interupteur=2; int charge=280; int lecture=40; float offTime=9680; //conversions float in_max=1023.0; float in_min=0; float out_max=5.0; float out_min=0; float taux=0;//données brutes unsigned long temps; float tauxconv=0;//données converties float data=0; //date unsigned long jour=0; unsigned long heure=0; unsigned long minute=0; unsigned long seconde=0; //autre unsigned long tempsmesure=30000; //durée d'une mesure unsigned long debut=0;// temps du début de la mesure unsigned long totalduration=0; //durée de l'échantillonage mesure int capteurmax=1000; //nombre de capteurs connectés int compteur=0; float somme[6]={0,0,0,0,0}; File fichier; void setup() { // init port série Serial.begin(9600); //initialisation de la carte sd Serial.print("Initialisation de la carte SD..."); if (!SD.begin(sd_cs)) { Serial.println("Carte non reconnue"); return; } Serial.println("OK!"); delay(1000); if (SD.exists("data.txt")==true){ Serial.println("Supression des anciennes données..."); SD.remove("data.txt"); Serial.println("Fichier supprimé"); delay(1000); } pinMode(interupteur, OUTPUT); Serial.println("Saisir le nombre de capteur:"); while (capteurmax>6){ if (Serial.available()> 0) { capteurmax=Serial.read(); capteurmax=capteurmax-'0'; Serial.println(capteurmax); } } fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { fichier.print("Jour;Heure;"); } fichier.close(); delay(100); for (capteur=0;capteur<=capteurmax; capteur++){ delay(100); fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { if (capteur<capteurmax){ fichier.print("Capteur"); fichier.print(capteur); fichier.print(";"); } else{ fichier.print("Capteur"); fichier.println(capteur); } fichier.close(); } else { Serial.println ("erreur à l'ouverture"); } } debut=millis(); Serial.print("Debut mesure: "); } void loop() { compteur++; digitalWrite(interupteur,LOW); // active la LED delayMicroseconds(charge); //mesure du temps temps= millis(); if (temps> 86400000){ jour= temps/86400000; temps=temps400000; } if (temps> 3600000){ heure= temps/3600000; temps=temps600000; } if (temps> 60000){ minute= temps/60000; temps=temps`000; } seconde= temps/1000; for (capteur=0; capteur<=capteurmax-1; capteur++){ //Lecture des données brut taux=analogRead(capteur); // conversion des données tauxconv = conversion(taux,in_min,in_max,out_min,out_max); data=conversion(tauxconv,0.5,4.0,0.0,0.59); somme[capteur]= somme[capteur]+data; } // calcul de la durée de l'expérience totalduration=millis()-debut; if (totalduration>= tempsmesure){ delayMicroseconds(lecture); digitalWrite(interupteur,HIGH); // éteind la led for (capteur=0; capteur<=capteurmax-1; capteur++){ float average=0; average= somme[capteur]/compteur; if(capteur==0){ Serial.print ("Jour "); Serial.print (jour); Serial.print (" "); Serial.print (heure); Serial.print (" h "); Serial.print (minute); Serial.print (" min "); Serial.print (seconde); Serial.println (" s "); } Serial.print ("CAPTEUR "); Serial.println(capteur); // Serial.print(" Voltage : "); // Serial.println(taux conv); Serial.print(" Taux de particule (mg/mcube) : "); Serial.println(average); //stockage dans la carte sd //ouverture du fichier fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { Serial.print("Enregistrement sur carte SD..."); //enregistrer if(capteur==0){ fichier.print ("Jour "); fichier.print (jour); fichier.print (" ; "); fichier.print (heure); fichier.print (" h "); fichier.print (minute); fichier.print (" min "); fichier.print (seconde); fichier.print (" s ;"); delay(100); } fichier.print(average); fichier.print(";"); if (capteur==4){ fichier.println(); } delay(1000); //fermeture fichier.close(); Serial.println("Enregistrement terminé"); } else { Serial.println ("erreur à l'ouverture"); } somme[capteur]=0; } compteur=0; debut=millis(); } delayMicroseconds(lecture); digitalWrite(interupteur,HIGH); // éteind la led delayMicroseconds(offTime); } //fonction conversion des données brutes float conversion (float in, float x_min, float x_max, float y_min, float y_max) { float out=0; out = (in-x_max)*((y_max-y_min)/(x_max-x_min))+y_max; return out; } //capteur shinyei #include <SPI.h> #include <SD.h> int sd_cs=4; // carte sd commande int sd_mosi=11; int sd_miso=12; int sck_sd=13; int capteur; int capteurmax=1000; int pin; unsigned long duration[7]={0,0,0,0,0,0}; //durée de la mesure unsigned long start=0; //heure de passage à l'état bas unsigned long stopp=0; //heure de passage à l'état haut unsigned long totallow[7]={0,0,0,0,0,0}; //durée à l'état bas unsigned long debut=0;// temps du début de la mesure unsigned long temps; //temps depuis le début du test unsigned long tempsmesure=30000; //durée d'une mesure unsigned long totalduration=0; //durée de l'échantillonage mesure float tauxparticules[7]={0.0,0.0,0.0,0.0,0.0,0.0}; // concentration en particules float ratio[7]={0,0,0,0,0,0}; //pourcentage de temps à l'état bas int etat[7]={1,1,1,1,1,1}; //envoie l'état logique en sortie int previous[7]={1,1,1,1,1,1}; // etat logique précédent int jour=0; int heure=0; int minute=0; int seconde=0; File fichier; void setup() { //ouverture connection série Serial.begin(9600); //initialisation de la carte sd Serial.print("Initialisation de la carte SD..."); if (!SD.begin(sd_cs)) { Serial.println("Carte non reconnue"); return; } Serial.println("OK!"); delay(1000); if (SD.exists("data.txt")==true){ Serial.println("Supression des anciennes données..."); SD.remove("data.txt"); Serial.println("Fichier supprimé"); delay(1000); } Serial.println("Saisir le nombre de capteur:"); while (capteurmax>6){ if (Serial.available()> 0) { capteurmax=Serial.read(); capteurmax=capteurmax-1-'0'; Serial.println(capteurmax); } } //définition de la PIN comme entrée fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { fichier.print("Jour;Heure;"); } fichier.close(); delay(100); for (capteur=0;capteur<=capteurmax; capteur++){ pin=capteur+14; pinMode (pin, INPUT); delay(100); fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { if (capteur<capteurmax){ fichier.print("Capteur"); fichier.print(capteur); fichier.print(";"); } else{ fichier.print("Capteur"); fichier.println(capteur); } fichier.close(); } else { Serial.println ("erreur à l'ouverture"); } } debut=millis(); Serial.print("Debut mesure: "); date(); } void loop() { //boucle sur chaque capteur for (capteur=0;capteur<=capteurmax; capteur++){ pin=capteur+14; // Vérifie l'état du capeur previous[capteur]=etat[capteur]; etat[capteur]=digitalRead (pin); if(etat[capteur]==LOW && previous[capteur]==HIGH){ start=millis(); } else if(previous[capteur]==LOW && etat[capteur]==HIGH){ stopp=millis(); duration[capteur]= stopp-start; //mesure de la durée total de l'état bas totallow[capteur]=totallow[capteur]+duration[capteur]; } } // calcul de la durée de l'expérience totalduration=millis()-debut; //affichage du taux de particule en pcs toute les 30 secondes if (totalduration>= tempsmesure){ date(); fichier=SD.open("data.txt", FILE_WRITE); fichier.print ("Jour "); fichier.print (jour); fichier.print (";"); fichier.print (heure); fichier.print (":"); fichier.print (minute); fichier.print (":"); fichier.print (seconde); fichier.print (";"); fichier.close(); for (capteur=0;capteur<=capteurmax; capteur++){ Serial.print("Capteur "); Serial.println(capteur); Serial.println (totallow[capteur]); ratio[capteur] = (totallow[capteur]*100.0)/tempsmesure; tauxparticules[capteur]=1.1*pow(ratio[capteur],3)-3.8*pow(ratio[capteur],2)+520*ratio[capteur]+0.62; Serial.println (tauxparticules[capteur]); fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { Serial.print("Enregistrement sur carte SD..."); if (capteur<5){ fichier.print(tauxparticules[capteur]); fichier.print(";"); } else{ fichier.println(tauxparticules[capteur]); } fichier.close(); Serial.println("Enregistrement terminé"); } else { Serial.println ("erreur à l'ouverture"); } totallow[capteur]=0; duration[capteur]=0; debut=millis(); } } } void date () { temps=millis(); if (temps> 86400000){ jour= temps/86400000; temps=temps400000; } if (temps> 3600000){ heure= temps/3600000; temps=temps600000; } if (temps> 60000){ minute= temps/60000; temps=temps`000; } seconde= temps/1000; Serial.print ("Jour "); Serial.print (jour); Serial.print (" "); Serial.print (heure); Serial.print (" h "); Serial.print (minute); Serial.print (" min "); Serial.print (seconde); Serial.println (" s "); }
Un capteur de gaz est un élément constitué de différentes couches de semi conducteurs sensible à la présence de certains composés gazeux. De manière générale l'objectif est de mesurer la valeur de la résistance interne du capteur qui va varier selon le taux de gaz présent dans l'air. En réalisant un pont diviseur de tension il est possible d'obtenir la valeur de cette résistance sensible. Il est aussi possible de noter la présence d'une résistance de chauffage qui aura pour but de placer le capteur dans les conditions optimal pour les mesures.
Pour chacun des capteurs à tester on aura une connectique légèrement différente, la logique restera néanmoins toujours la même. Les données seront récupérée via une carte Arduino uno et stockée sur carte SD. Il faut donc désormais définir le code à utiliser.
Le code qui suit correspond à la première version utilisée pour nos tests.
#include <SPI.h> #include <SD.h> int sd_cs=4; // carte sd commande int sd_mosi=11; int sd_miso=12; int sck_sd=13; int capteur; int capteurmax= 19; unsigned long debut=0;// temps depuis le démarrage de la dernière mesure unsigned long temps=0; //temps depuis le début du test unsigned long tempsmesure=300000; //temps de moyennage avant affichage unsigned long totalduration=0; //durée de la mesure float mesure[6]={0.0,0.0,0.0,0.0,0.0}; float tension[6]={0.0,0.0,0.0,0.0,0.0}; // tension mesurée par chacun des capteurs float totaltension[6]={0.0,0.0,0.0,0.0,0.0}; // moyenne des mesures float tauxgazs[6]={0.0,0.0,0.0,0.0,0.0}; // concentration en particules float in_max=1023.0; float in_min=0; float out_max=100.0; float out_min=0; int jour=0; int heure=0; int minute=0; int seconde=0; int compteur=0 File fichier; void setup() { //ouverture connection série Serial.begin(9600); //initialisation de la carte sd Serial.print("Initialisation de la carte SD..."); if (!SD.begin(sd_cs)) { Serial.println("Carte non reconnue"); return; } Serial.println("OK!"); delay(1000); if (SD.exists("data.txt")==true){ Serial.println("Supression des anciennes données..."); SD.remove("data.txt"); Serial.println("Fichier supprimé"); delay(1000); } //Serial.println("Saisir le nombre de capteur:"); //while (capteurmax>6){ // if (Serial.available()> 0) { //capteurmax=Serial.read(); //capteurmax=capteurmax-'0'; //Serial.println(capteurmax); // } //} // capteurmax=capteurmax+14; //définition de la PIN comme entrée for (capteur=14;capteur<=capteurmax; capteur++){ pinMode (capteur, INPUT); delay(100); fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { if (capteur<19){ fichier.print("Capteur"); fichier.print(capteur); fichier.print(";"); } else{ fichier.print("Capteur"); fichier.println(capteur); } fichier.close(); } } debut=millis(); Serial.print("Debut mesure: "); date(); } void loop() { compteur++ //boucle sur chaque capteur for (capteur=0;capteur<=capteurmax-14; capteur++){ // Mesure la tension du capteur mesure[capteur]=analogRead(capteur); // conversion des données tension[capteur]= conversion(mesure[capteur],in_min,in_max,out_min,out_max); //mesure de la durée total de l'état bas totaltension[capteur]=(totaltension[capteur]+tension[capteur]/compteur); totalduration=millis()-debut; //affichage du taux de gaz if (totalduration>= tempsmesure){ date(); fichier=SD.open("data.txt", FILE_WRITE); fichier.print ("Jour "); fichier.print (jour); fichier.print (";"); fichier.print (heure); fichier.print (":"); fichier.print (minute); fichier.print (":"); fichier.print (seconde); fichier.print (";"); fichier.close(); for (capteur=0;capteur<=capteurmax-14; capteur++){ Serial.print("Capteur "); Serial.println(capteur); Serial.println (tension[capteur]); //faire conversion selon le capteur //... fichier=SD.open("data.txt", FILE_WRITE); if (fichier) { Serial.print("Enregistrement sur carte SD..."); if (capteur<5){ fichier.print(tension[capteur]); fichier.print(";"); } else{ fichier.println(tension[capteur]); } fichier.close(); Serial.println("Enregistrement terminé"); } else { Serial.println ("erreur à l'ouverture"); } duration[capteur]=0; debut=millis(); } } } } // affichage de la date sur le port série void date () { temps=millis(); if (temps> 86400000){ jour= temps/86400000; temps=temps400000; } if (temps> 3600000){ heure= temps/3600000; temps=temps600000; } if (temps> 60000){ minute= temps/60000; temps=temps`000; } seconde= temps/1000; Serial.print ("Jour "); Serial.print (jour); Serial.print (" "); Serial.print (heure); Serial.print (" h "); Serial.print (minute); Serial.print (" min "); Serial.print (seconde); Serial.println (" s "); } //fonction conversion des données brutes float conversion (int in, float x_min, float x_max, float y_min, float y_max) { float out=0; out = (in-x_max)*((y_max-y_min)/(x_max-x_min))+y_max; return out; }
Pour cette manipulation seul les composant de type SHARP ont été testés. Trois d'entre eux utilisent les nappes de connexion de type S6-BR-ZR-SM4A-TF et deux sont reliés à la carte Arduino avec des fils simplement étanés sur le PCB.
L'enceinte de test est constituée d'une boite contenant les capteurs à tester mais aussi l'instrument de mesure OSIRIS. Un couvercle couvrira partiellement le contenant de manière à laisser passer l'air.
L'expérience durera 24 h en grande partie sous aire ambiant mais avec ajout de fumés à des instants donnés.
Le but ici n'est pas tant d'obtenir des résultats que de vérifier si la procédure de test est satisfaisante.
Après récupération des résultats plusieurs constats peuvent être fait. Tout d'abord le stockage sur carte SD doit être retravailler car l'arrivé trop rapide de données engendre une perte des résultats.
L'enceinte de test est également peu fiable car l'absence de ventilation ne permet de faire circuler la fumée dans l'ensemble de la boite. Un espace de test plus efficace avec ventilateur devra donc être réalisé.
Du point de vue résultats les capteurs semblent bien répondre aux contraintes extérieures, la perte de résultat ne permet malheureusement pas de définir la précision des composants.
Ce premier mois à été d'avantage consacré à la pris en main des instruments de mesures et à l'étude des capteurs. Un premier test à pu être élaboré, les résultats obtenue ne permette pas de tirer de réel conclusion sur les composants, l'enceinte de test ainsi que le code utilisé devront être retravaillé.