Spisu treści:
- Kieszonkowe dzieci
- Krok 1: Podłączanie komponentów
- Krok 2: Biblioteka i program Arduino
- Krok 3: Program MIT App Inventor 2
- Krok 4: WYNIK
Wideo: System monitorowania jakości powietrza pod kątem zanieczyszczeń pyłami: 4 kroki
2024 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2024-01-30 11:29
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
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
to jest blok kodu wynalazcy aplikacji MIT
Krok 4: WYNIK
oto wideo z rezultatem
Zalecana:
Wskaźnik LED stanu jakości powietrza PurpleAir: 4 kroki
Wyświetlacz LED stanu jakości powietrza PurpleAir: Niedawne pożary lasów w Kalifornii znacznie wpłynęły na jakość powietrza w San Francisco. Ciągle sprawdzaliśmy mapę PurpleAir na naszych telefonach lub laptopach, próbując sprawdzić, kiedy powietrze jest wystarczająco bezpieczne, aby wygrać
Czujnik jakości powietrza za pomocą Arduino: 4 kroki
Czujnik jakości powietrza za pomocą Arduino: W tym poście dowiemy się, jak zbudować prosty, ale użyteczny czujnik jakości powietrza. Użyjemy czujnika SGP30 wraz z Piksey Pico, chociaż szkic będzie działał z prawie każdą płytą kompatybilną z Arduino. Powyższy film prowadzi Cię przez t
System monitorowania powietrza za pomocą NodeMCU i IOT Thingspeak: 4 kroki
System monitorowania powietrza wykorzystujący NodeMCU i IOT Thingspeak: ThingSpeak to otwarta aplikacja IoT i interfejs API do przechowywania i pobierania danych z urządzeń sprzętowych i czujników. Do komunikacji używa protokołu HTTP przez Internet lub LAN. Analiza MATLAB jest dołączona do analizy i wizualizacji da
Jak zmodyfikować wyzwalacze lampy błyskowej CTR-301P (ebay) pod kątem stroboskopów niskonapięciowych.: 4 kroki
Jak zmodyfikować wyzwalacze błysku CTR-301P (ebay) dla stroboskopów niskonapięciowych.: Niedawno kupiłem zestaw wyzwalaczy błysku CTR-301P w serwisie eBay. Byłem szczęśliwy, że uruchomili moje studyjne lampy błyskowe, ale rozczarowałem się, że nie uruchomili mojej lampy błyskowej na gorącą stopkę Promaster. Poszukałem trochę i stwierdziłem, że inni dodali drut
Konwertuj nagłówki proste na nagłówki pod kątem prostym (w mgnieniu oka): 4 kroki
Konwertuj proste nagłówki na nagłówki pod kątem prostym (w mgnieniu oka): Po obejrzeniu ogłoszenia o konkursie arduino powiedziałem, hej, dlaczego nie spróbować. i dostałem zestaw barebone arduino, z zamiarem „zrobienia tego po swojemu”. Jedna z tych zmian była jedną z pierwszych rzeczy, które