[PROJEKT] Czujnik stężenia gazów ziemnych i LPG na Arduino Uno i modMQ-5
Moduł modMQ-5 to układ pozwalający na pomiar stężenia gazów ziemnych i LPG – wykorzystując sensor MQ-5, pozwala na precyzyjny pomiar stężenia propan-butanu, metanu (CH4), wodoru (H2), a także alkoholu i tlenku węgla (CO). Struktura czujnika przez cały czas pracy podtrzymywana jest w podwyższonej temperaturze – zapewnia to zintegrowany element grzejny o maksymalnym poborze mocy poniżej 0,8 W. Czujnik charakteryzuje się szybką odpowiedzią na wykrycie gazu, prostotą użycia i niską czułością na dym.
W module modMQ-5, poza wyprowadzeniem napięcia z dzielnika rezystancyjnego (tworzonego przez czujnik i rezystor ściągający do masy) wykorzystano także komparator z regulowanym progiem zadziałania – moduł pozwala na wygenerowanie sygnału (stan wysoki) w momencie przekroczenia progu czułości ustawianego potencjometrem regulacyjnym. Dodatkowo, przekroczenie tego progu, jak i sama praca czujnika, sygnalizowane są diodami świecącymi.
W projekcie wykorzystano wyjście analogowe modułu modMQ-5 – napięcie zmieniające się w zakresie 0…5 V mierzone jest przez przetwornik ADC mikrokontrolera ATmega328p, zawartego w płytce Arduino UNO R3. Na wyświetlaczu o organizacji 2×16 znaków, zawartym w nakładanym na Arduino zestawie LCD Keypad Shield wyświetlana jest informacja o stanie pracy układu i, po wykryciu niebezpiecznego gazu, pokazywane jest jego przybliżone stężenie w otoczeniu czujnika. Wykrycie sygnalizowane jest także akustycznie – podłączony do układu buzzer Pololu – 1260 sygnalizuje wystąpienie alarmu sygnałem przerywanym (dla niskich wartości stężenia) lub ciągłym (dla wartości wysokiej).
Do poprawnej pracy układu wymagane jest także dostarczenie stabilizowanego napięcia 5 V – pobór prądu urządzenia przekracza wydajność prądową stabilizatora zintegrowanego z Arduino oraz portu USB komputera (niekorzystny spadek napięcia) – dlatego bardzo ważne jest użycie dodatkowego zasilacza podłączanego za stabilizatorem Arduino (użycie ww. modułów z zasileniem płytki Arduino UNO R3 przez wtyk zasilacza DC spowoduje nieodwracalne uszkodzenie stabilizatora w Arduino!).
Program sterujący pracą mikrokontrolera napisano w kompilatorze Arduino. Na początku kodu programu deklarowane jest użycie biblioteki wyświetlacza oraz przypisanie wyprowadzeń mikrokontrolera do LCD. Definiowane są także dwie zmienne typu unsigned char. W funkcji setup() konfigurowane są wyprowadzenia, generowany jest sygnał akustyczny (instrukcja Tone()) oraz chwilowo wygaszone zostaje podświetlanie LCD – pozwala to użytkownikowi na szybką ocenę, czy urządzenie działa poprawnie. Na końcu następuje skok do funkcji Licz(). Fragment kodu przedstawiono na listingu 1.
Listing 1. Deklaracje i funkcja Setup():
#include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); unsigned char alarm=0; unsigned char czas=0; void setup() { lcd.begin(16, 2); pinMode(10,OUTPUT); pinMode(2, OUTPUT); tone(2,500,30); digitalWrite(10,LOW); delay(100); noTone(2); digitalWrite(10,HIGH); licz(); }
Celem funkcji Licz(), przedstawionej na listingu 2, jest odmierzenie około minuty po włączeniu zasilania – ten czas pozwala na rozgrzanie się struktury czujnika na tyle, by nie pojawiały się fałszywe alarmy. Funkcja odmierzająca opóźnienie dekrementuje zmienną czas co sekundę – od wartości 59 do zera. Wartość zmiennej jest na bieżąco wyświetlana jako czas pozostały do przejścia w stan gotowości.
Listing 2. Funkcja licz() opóźniająca uruchomienie trybu gotowości
void licz() { for (czas=59; czas>0; czas--) { lcd.setCursor(0,0); lcd.print("Nagrzewanie..."); lcd.setCursor(0,1); lcd.print("Pozostalo: "); lcd.print (czas); lcd.print(" s"); delay(1000); lcd.clear(); } lcd.clear(); czas=0; }
W pętli głównej loop() mierzone i konwertowane jest napięcie odczytane z pinu A1 modułu Arduino. W pierwszej linii LCD wyświetlony zostaje napis statyczny, zaś w drugiej może zostać wyświetlony jeden z czterech napisów informujących o poziomie stężenia wykrytego gazu – z prostych obliczeń przeprowadzonych na podstawie charakterystyki czujnika wyliczone zostały progi napięciowe, odpowiadające kolejno poziomom: 100 ppm (0,49 V), 1000 ppm (1,18 V), 10000 ppm (2,1 V) stężenia gazu LPG w obszarze sensora. Napięcia te podane są dla modułu modMQ-5, w którym wartość rezystora ściągającego do masy wynosi 10 k?. Za pomocą zmiennej alarm i instrukcji switch() wybierana jest treść drugiej linii wyświetlacza, w zależności od przedziału napięcia pochodzącego z ADC (sprawdzanego w instrukcjach if() dla zmiennej voltage).
Wykorzystując zmienną czas, w pętli loop mierzony jest pewien czas, przez który pozostaje włączone podświetlenie ekranu LCD – w celach oszczędzania energii, gdy urządzenie jest w trybie gotowości, po około 6 sekundach wyświetlacz przestaje być podświetlany. Ponowne włączenie podświetlenia następuje samoistnie, po przejściu do stanu alarmu.
W przypadku spełnienia warunku w którejś z instrukcji if(), dla której napięcie będzie większe od progu 0,49 V, uruchomiony zostanie buzzer, którego sygnał generowany jest przez instrukcję Tone(). Dla rosnącej wartości napięcia, maleje opóźnienie Delay() między kolejnymi dźwiękami buzzera – dla wartości napięcia przekraczającej 2,1 V sygnał alarmu jest już praktycznie ciągły.
Funkcja if(voltage<0,49) kasuje wszelkie sygnały dźwiękowe oraz przypisuje zmiennej alarm wartość 0 – na wyświetlaczu pojawia się napis „poziom normalny” i odmierzany zostaje czas do wyłączenia podświetlenia ekranu. Pętlę główną przedstawiono na listingu 3.
Listing 3. Pętla główna loop()
void loop() { int sensorValue = analogRead(A1); float voltage = sensorValue * (5.00 / 1023.0); lcd.setCursor(0,0); lcd.print("Czujnik GAZU LPG "); lcd.print(voltage); lcd.setCursor (0,1); lcd.print(" "); lcd.setCursor(0,1); switch(alarm) { case 0: lcd.print("Poziom normalny"); break; case 1: lcd.print("Poziom >100ppm"); czas=0; break; case 2: lcd.print("Poziom >1000ppm"); czas=0; break; case 3: lcd.print("Poziom >10000ppm"); czas=0; break; } if (czas > 100 && alarm == 0) { digitalWrite(10, LOW); } else { czas++; digitalWrite(10,HIGH); } delay(50); if(voltage > 0.49 && voltage <1.18) { alarm=1; tone(2,500,200); delay(300); } if(voltage > 1.18 && voltage <2.1) { alarm=2; tone(2,500,200); delay(150); } if (voltage > 2.1 && voltage < 5) { alarm=3; tone(2,500,200); delay(50); } if (voltage<0.49) { noTone(2); alarm=0; } }
Koncepcja układu pozwala na skuteczny pomiar stężenia gazu LPG, choć wprowadzając zmiany w kodzie programu mierzyć można także i inne gazy (na które czuły jest czujnik MQ-5).
UWAGA! Wszystkie eksperymenty z czujnikiem gazu należy wykonywać mając na uwadze bezpieczeństwo pracy z łatwopalnymi gazami!
Pełny kod programu:
#include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); unsigned char alarm=0; unsigned char czas=0; void setup() { lcd.begin(16, 2); pinMode(10,OUTPUT); pinMode(2, OUTPUT); tone(2,500,30); digitalWrite(10,LOW); delay(100); noTone(2); digitalWrite(10,HIGH); licz(); } void licz() { for (czas=59; czas>0; czas--) { lcd.setCursor(0,0); lcd.print("Nagrzewanie..."); lcd.setCursor(0,1); lcd.print("Pozostalo: "); lcd.print (czas); lcd.print(" s"); delay(1000); lcd.clear(); } lcd.clear(); czas=0; } void loop() { int sensorValue = analogRead(A1); float voltage = sensorValue * (5.00 / 1023.0); lcd.setCursor(0,0); lcd.print("Czujnik GAZU LPG "); lcd.print(voltage); lcd.setCursor (0,1); lcd.print(" "); lcd.setCursor(0,1); switch(alarm) { case 0: lcd.print("Poziom normalny"); break; case 1: lcd.print("Poziom >100ppm"); czas=0; break; case 2: lcd.print("Poziom >1000ppm"); czas=0; break; case 3: lcd.print("Poziom >10000ppm"); czas=0; break; } if (czas > 100 && alarm == 0) { digitalWrite(10, LOW); } else { czas++; digitalWrite(10,HIGH); } delay(50); if(voltage > 0.49 && voltage <1.18) { alarm=1; tone(2,500,200); delay(300); } if(voltage > 1.18 && voltage <2.1) { alarm=2; tone(2,500,200); delay(150); } if (voltage > 2.1 && voltage < 5) { alarm=3; tone(2,500,200); delay(50); } if (voltage<0.49) { noTone(2); alarm=0; } }