Spisu treści:

System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłami: 4 kroki
System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłami: 4 kroki

Wideo: System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłami: 4 kroki

Wideo: System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłami: 4 kroki
Wideo: ZANIECZYSZCZENIE POWIETRZA – Szkolenia internetowe w służbie ochrony powietrza 2024, Lipiec
Anonim
System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłowych
System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłowych
System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłowych
System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłowych

WSTĘP:

1 W tym projekcie pokazuję, jak zbudować detektor cząstek z wyświetlaczem danych, kopią zapasową danych na karcie SD i IOT. Wizualnie wyświetlacz pierścieniowy neopikseli wskazuje jakość powietrza.

2 Jakość powietrza jest dziś coraz ważniejszym problemem. istnieją systemy do pomiaru stopnia zapylenia, ale są one bardzo drogie. Na rynku dostępne są tanie, wysokiej jakości detektory cząstek, jak pokazują niektóre badania.

na przykład:

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

3 Dlatego zdecydowałem się zbudować urządzenie zdolne do pomiaru liczby cząstek według klas wielkości (od 0,5 µm do 10 µm), wizualnie z prostym wyświetlaniem wyniku (pierścień neopikselowy), bardziej szczegółowym wyświetlaniem na ekranie TFT i kopia zapasowa ze znacznikiem czasu na karcie SD.

4 Dodatkowo dodałem moduł komunikacji bluetooth, aby móc komunikować się z aplikacją na Androida i dzięki temu publikować wyniki na serwerze IOT.

5 Całkowity koszt całości nie przekracza 60 €

Kieszonkowe dzieci

-Arduino uno R3

-Prototarcza Arduino

-ekran TFT ST7735

-Pierścień neopikselowy 24 led

-Donica PMS5003

-Moduł bluetooth HC-06

Krok 1: Podłączanie komponentów

Podłączanie komponentów
Podłączanie komponentów

różne komponenty są połączone zgodnie z powyższym schematem

Krok 2: Biblioteka i program Arduino

1 biblioteka

dla ekranu TFT

github.com/adafruit/Adafruit-GFX-Library

dla pierścienia neo pixel

github.com/adafruit/Adafruit_NeoPixel

dla karty sd

github.com/arduino-libraries/SD

2 szkic arduino

#include #include // Bibliothèque dla l'I2C #include "RTClib.h" // Bibliothèque dla modułu RTC RTC_DS1307 RTC; #włączać

// Który pin w Arduino jest podłączony do NeoPixels?

#define PIN 6 // W Trinket lub Gemma zasugeruj zmianę na 1

// Ile NeoPixeli jest podłączonych do Arduino?

#define NUMPIXELS 24 // Popularny rozmiar pierścienia NeoPixel Piksele Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); uint32_t vert = piksele. Color(0, 250, 0); uint32_t orange = piksele. Color(250, 250, 0); uint32_t rouge = piksele. Kolor(255, 0, 0);

OprogramowanieSerial pmsSerial(2, 3);

#define cs 10 #define dc 9 #define rst 8 // można to również podłączyć do resetu Arduino

#include // Podstawowa biblioteka graficzna

#include // Biblioteka specyficzna dla sprzętu #include #include const int cs_sd=4; temp. wewn.; // temps d'acquisition double tempsInit; // inicjalizacja du timer au demarrage du loop()

#jeśli zdefiniowano(_SAM3X8E_)

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

// Opcja 1: użyj dowolnych pinów, ale trochę wolniej

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

// Opcja 2: należy użyć sprzętowych pinów SPI

// (dla UNO to sclk = 13 i sid = 11) i pin 10 muszą być // wyjściem. Jest to znacznie szybsze - również wymagane, jeśli chcesz // korzystać z karty microSD (patrz przykład rysowania obrazu) Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); pływak nombre_leds=0; void setup() { Serial.begin(9600); // Zainicjuj połączenie I2C Wire.begin(); // Zainicjuj moduł RTC RTC.begin(); Serial.print("początkowe SD"); opóźnienie (1000); if(!SD.begin(cs_sd)) //Weryfikacja warunku karty SD jest obecna w urządzeniu { Serial.print("Domyślna SD"); powrót; } Serial.print("Karta SD OK");

Dane pliku = SD.open("donnees.txt", FILE_WRITE); // Opublikuj plik „donnees.txt”

data.println(""); data.println("Akwizycja demarrage"); // Ecrit dans ce fichier data.close(); tft.initR(INITR_GREENTAB); // zainicjuj układ ST7735S, czarna karta Serial.println("init"); // nasze wyjście debugowania tft.fillScreen(ST7735_BLACK); // szybkość transmisji czujnika to 9600 pmsSerial.begin(9600);

piksele.początek(); // INICJALIZUJ obiekt paska NeoPixel (WYMAGANE)

piksele.setJasność(2);

}

struktura danych pms5003 {

uint16_t ramka; uint16_t pm10_standard, pm25_standard, pm100_standard; uint16_t pm10_env, pm25_env, pm100_env; uint16_t cząstki_03um, cząstki_05um, cząstki_10um, cząstki_25um, cząstki_50um, cząstki_100um; uint16_t nieużywany; suma kontrolna uint16_t; };

struktury danych pms5003data; void loop() { piksele.clear(); // Ustaw wszystkie kolory pikseli na 'off' DateTime now=RTC.now(); //Récupère l'heure et le date curante //affiche_date_heure(teraz);

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("liczba części/ 0,1 l");

tft.setCursor(10, 17); tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.setCursor(10, 17); tft.print("0,3 um");tft.print(dane.cząstki_03um);tft.print("");

tft.setCursor(10, 29);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.print("0,5um");tft.print(dane.cząstki_05um);tft.print("");

tft.setCursor(10, 41);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.print("1,0 um");tft.print(dane.cząstki_10um);tft.print(" ");

tft.setCursor(10, 53);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.print("2,5um");tft.print(dane.cząstki_25um);tft.print("");

tft.setCursor(10, 65);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.print("5,0um");tft.print(dane.cząstki_50um);tft.print("");

tft.setCursor(10, 77);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.print("10um");tft.print(dane.cząstki_100um);tft.print("");

tft.setCursor(2, 89);

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(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(" mikrog/m3");

tft.setCursor(2, 100); tft.setTextColor(ST7735_GREEN, ST7735_BLACK); tft.setRozmiarTekstu(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("mikrog/m3");

tft.setCursor(2, 110);

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

tft.setCursor(10, 5);

tft.setTextColor(ST7735_WHITE, ST7735_BLACK); tft.setRozmiarTekstu(1); tft.println("liczba części/ 0,1 l");

// Serial.print(temps);

// Serial.print (" "); Serial.print ("#"); Serial.print ("03µm"); Serial.print(data.particles_03um); Serial.print (" "); Serial.print ("05µm"); Serial.print(dane.cząstki_05um); Serial.print (" "); Serial.print ("1µm"); Serial.print(data.particles_10um); Serial.print (" "); Serial.print ("25µm"); Serial.print(dane.cząstki_25um); Serial.print (" "); Serial.print ("50µm"); Serial.print(dane.cząstki_50um); Serial.print (" "); Serial.print ("100µm"); Serial.print(data.particles_100um); Serial.println (" "); nombre_leds =int (((liczba zmiennoprzecinkowa (data.particles_03um)/65535)*24)); //nombre_leds =(8); Serial.println (nombre_leds);

jeśli ((nombre_leds=1)){

piksele.fill(vert, 0, nombre_leds); } else if ((nombre_leds=8)) { piksele.fill(vert, 0, 8); piksele.fill(pomarańczowy, 8, ((nombre_leds)-8); } else if (nombre_leds>16) {

piksele.wypełnienie(pion, 0, 8); piksele.wypełnienie(pomarańczowy, 8, 8); piksele.fill(rouge, 16, ((nombre_leds)-16)); } else if (nombre_leds<=1) { piksele.fill(vert, 0, 1); } piksele.show(); // Wyślij zaktualizowane kolory pikseli do sprzętu.

// Définition données String PM03=String(data.particles_03um); Ciąg PM05=Ciąg(dane.cząstki_05um); Ciąg PM10=Ciąg(dane.cząstki_10um); Ciąg PM25=Ciąg(dane.cząstki_25um); Ciąg PM50=Ciąg(dane.cząstki_50um); Ciąg PM100=Ciąg(dane.cząstki_100um); Ciąg PMS10=Ciąg(dane.pm10_standard); Ciąg PMS25=Ciąg(data.pm25_standard); Ciąg PMS100=Ciąg(dane.pm100_standard); String Temps=String(temps);

//Ecriture des données dans le fichier texte

Plik data=SD.open("donnees.txt", FILE_WRITE); data.println(Temps + " " + PM03+ " " + PM05 +" " +PM10+" " +PM25+" "+PM50+" " +PM100+" "+PMS10+" "+PMS25+" "+PMS100+" "); data.zamknij(); }

}

wartość logiczna readPMSdata (strumień *s) {

if (! s->available()) { return false; } // Odczytaj bajt na raz, aż dojdziemy do specjalnego bajtu startowego '0x42' if (s->peek() != 0x42) { s->read(); zwróć fałsz; }

// Teraz przeczytaj wszystkie 32 bajty

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

// przygotuj sumę kontrolną

for (uint8_t i=0; i<30; i++) { suma += bufor; }

/* debugowanie

for (uint8_t i=2; i<32; i++) { Serial.print("0x"); Serial.print(bufor, HEX); Serial.print(", "); } Serial.println(); */ // Dane przychodzą w endian'd, to rozwiązuje problem, więc działa na wszystkich platformach uint16_t buffer_u16[15]; for (uint8_t i=0; i<15; i++) { bufor_u16 = bufor[2 + i*2 + 1]; bufor_u16 += (bufor[2 + i*2] << 8); }

// umieść to w ładnej strukturze:)

memcpy((nieważne *)&dane, (nieważne *)buffer_u16, 30);

if (suma != dane.suma kontrolna) {

Serial.println("Błąd sumy kontrolnej"); zwróć fałsz; } // powodzenie! zwróć prawdę; }

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

String donne_jour_semaine(uint8_t j){ switch(j){ case 0: return "DIM"; przypadek 1: zwróć "LUN"; przypadek 2: zwróć "MAR"; przypadek 3: zwróć "MER"; przypadek 4: zwrot „JEU”; przypadek 5: zwróć "VEN"; przypadek 6: zwrot "SAM"; domyślnie: return " "; } }

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

void affiche_date_heure(DateTime datetime){ // Date String jour = donne_jour_semaine(datetime.dayOfTheWeek()) + " " + Vers2Chiffres(datetime.day())+ "/" + Vers2Ciffres(datetime.month())+ "/" + String(datagodzina.rok(), DEC); // heure String heure = ""; heure = Vers2Chiffres(datetime.hour())+ ":" + Vers2Chiffres(datetime.minute())+ ":" + Vers2Chiffres(datetime.second());

Serial.print(dziennik); Serial.print(" "); Serial.print(heure); //Serial.print(" "); Plik data=SD.open("donnees.txt", FILE_WRITE); data.print(jour + " " + heure+" "); data.zamknij();

tft.setCursor(2, 120);

tft.setTextColor(ST7735_GREEN); tft.setRozmiarTekstu(1); tft.print("data");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);

opóźnienie (500);

}

//permet d'afficher les nombres sur deux chiffres

String Vers2Chiffres(byte nombre) { String resultat = ""; if(nombre < 10) wynik = "0"; zwróć wynik += String(norma, DEC); }

Krok 3: Program MIT App Inventor 2

MIT App Inventor 2 Program
MIT App Inventor 2 Program

to jest blok kodu wynalazcy aplikacji MIT

Krok 4: WYNIK

oto wideo z rezultatem

Zalecana: