MICHELEPISANI.IT
 

Sensore MQ-4, Buzzer, LED, LCD 1602 I2C

Rilevatore di Gas Con Allarme Sonoro e Visivo, con Arduino UNO

arduino - rilevatore di gas con allarme
February 19
07:152017

Ho recentemente acquistato un sensore per il rilevamento della concentrazione nell'aria di gas naturale (principalmente composto da Metano) e non ho potuto fare a meno di constatarne l'elevata sensibilità tradotta appunto in un tempo di risposta alla sollecitazione molto rapido.

Ho creato pertanto un piccolo progetto con Arduino UNO al fine di ottenere un sistema di allarme che segnali acusticamente e visivamente la presenza di Gas nell'aria.
In breve ho utilizzato un display LCD 1602 I2C per mostrare il valore del livello di GAS rilevato nell'aria dal sensore MQ-4. Sopra una certa soglia di rilevamento un buzzer, in funzione di allarme uditivo, emette un segnale acustico e contestualmente un led, in funzione di allarme visivo, si accende. Sotto la soglia stabilita i sensori di allarme tornano allo stato di inattività.

Di seguito lo schema elettrico del progetto

arduino - rilevatore di gas metano con allarme
Fig. 1 - Schema per Arduino - Rilevatore di Gas Metano con Allarme

Ed ecco la parte più interessante del progetto, lo sketch, ottimizzato con l'utilizzo della funzione millis() anziché il classico delay() per garantire un più efficace ed immediato recupero delle informazioni rilevate:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int buzzerPin = 12;
const int ledPin = 11;
const int sensorPin = A0;
const int intervallo_base = 200;

int sensorValue = 0;
int sensorAlertMinValue = 400;
int ledValue = 0;
bool buzzerTone = 0;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup(void) {
  lcd.begin(16, 2);
  pinMode(buzzerPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
}

void loop(void) { 
  currentMillis = millis();
  sensorValue = analogRead(sensorPin);

  lcd.setCursor(0, 0);
  lcd.print("Rilevamento GAS:");
  lcd.setCursor(0, 1);
  lcd.print(sensorValue);

  if (sensorValue > sensorAlertMinValue) {
    ledValue = HIGH;
    if ((currentMillis - previousMillis) >= (intervallo_base) && buzzerTone == 0) {
      noTone(buzzerPin);
      tone(buzzerPin, 500, 1000);
      buzzerTone = 1;
      updateMillis();
    }
    if ((currentMillis - previousMillis) >= (intervallo_base) && buzzerTone == 1) {
      noTone(buzzerPin);
      tone(buzzerPin, 300, 1000);
      buzzerTone = 0;
      updateMillis();
    }
  } else {
    ledValue = LOW;
  }

  digitalWrite(ledPin, ledValue);
  delay(100);

}

void updateMillis() {
  previousMillis = currentMillis;
}

Di seguito una breve dimostrazione del funzionamento del progetto dove è evidente la sensibilità del sensore principale utilizzato:

Il progetto è senz'altro migliorabile ed ampliabile utilizzando componenti di allerta più adeguati come ad esempio una sirena al posto del buzzer e del led.

Per consigli, suggerimenti o chiarimenti sentitevi liberi di lasciare un commento!

Tags

Autore

Michele Pisani

Michele Pisani

Ho uno spiccato orientamento al problem-solving, se è troppo facile non mi diverto :)
Credo nella volontà e nel cambiamento perchè hanno fatto della mia passione il mio pane quotidiano.
Se devo descrivermi con una sola parola direi... "Concretezza", la mia stretta di mano è una garanzia.

49 Commenti

  1. Gian Monday, March 20, 2017 alle ore 12:08

    Complimenti bell'articolo

    Rispondi a questo commento
  2. angelo Saturday, May 13, 2017 alle ore 20:13

    Ciao innanzitutto complimenti bellissima ed utilissima idea. ti disturbo piochè ho provato a realizzare partendo da tuo progetto ma a lavoro ultimato ho riscontrato problemi con il display nello sketch visualizzo\:LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
    se cancello la stringa il programma me lo carica funziona tutto ma non leggo nulla sul display. Vuoi essere cosi gentile da indicarmi la soluzione. grazie e buona serata.

    Rispondi a questo commento
    • Michele PisaniAutore Sunday, May 14, 2017 alle ore 00:16

      Ciao Angelo,
      sei in possesso del convertitore I2C (ovvero quel componente nero che vedi nel video sopra il display LCD)? In caso negativo, ossia se hai collegato i singoli pin come da procedura standard senza l'ausilio del componente I2C, allora quella stringa che hai evidenziato non è adeguata.
      Se hai collegato correttamente i pin dell'LCD ad Arduino, al potenziometro, ecc... prova a sostituire il contenuto di quella riga con la seguente stringa ed il display LCD dovrebbe funzionare correttamente:

      LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

      Rispondi a questo commento
  3. Angelo Sunday, May 14, 2017 alle ore 15:45

    Ciao Michele ti ringrazio nuovamente per la tua disponibilità.Ho collegato il display al convertitore I2C ed il rimanente come fai vedere nel tuo video il sensore mq5 funziona il bazzer ed il led si accendono mentre il display è alimentato ma non visualizzo nessuna scritta.

    Rispondi a questo commento
    • Michele PisaniAutore Sunday, May 14, 2017 alle ore 15:50

      Ciao Angelo,
      ma quella stringa l'hai lasciata?
      Hai provato inoltre a regolare il potenziometro che sta sulla I2C? Può essere che le scritte ci siano ma non le vedi per una questione di luminosità.

      Rispondi a questo commento
      • Angelo Monday, May 15, 2017 alle ore 08:40

        Buongiorno Michele la stringa l'ho lasciata l'errore me lo da durante la compilazione dello sketch .Comunque per venirne a capo ho messo sul display una scritta statica "rilevato gas pericolo!!!" Ed il tutto funziona.Ti ringrazio nuovamente per la tua disponibilità e ti rinnovo i complimenti per questo tuo interessantissimo sito,alla prossima Michele buon lavoro.

      • Michele PisaniAutore Monday, May 15, 2017 alle ore 21:36

        Di niente Angelo, l'importante è che sei riuscito a risolvere.

  4. Paolo Tuesday, June 13, 2017 alle ore 18:49

    salve,mi interessa il progetto sensore gas ,per applicazioni in agricoltura.Vedremo gli sviluppi.ottimo programma.

    Rispondi a questo commento
  5. Moreno Thursday, January 25, 2018 alle ore 11:29

    Sulla mia barca con motori fuoribordo mercury da 150 cv, ho montato un impianto ad idrogeno. Sono interessato al tuo bellissimo progetto per installarlo come dotazione di sicurezza in caso di perdite di idrogeno. Chiedo, vorrei installare solo il sensore di idrogeno nella calandra del motore e con tre fili di circa 1 metro collegati all'arduino montato nella barca .Sapresti dirmi all'incirca la soglia di allarme e come si modifica nello sketch. Io installo un MQ2 va bene per l'idrogeno.
    Ti ringrazio.

    Rispondi a questo commento
    • Michele PisaniAutore Friday, January 26, 2018 alle ore 00:56

      Ciao Moreno,
      per quanto riguarda la soglia d'allarme dell'idrogeno purtroppo non so darti indicazioni, immagino esistano delle tabelle di sicurezza certificate riguardo questo tema.
      Mentre, per modificare dallo sketch presente in questo articolo il valore oltre il quale il sistema di allarme si attiva, ti basterà inserire il valore desiderato alla variabile 'sensorAlertMinValue' dove, nel caso dell'esempio, è impostato a 400.

      Rispondi a questo commento
      • Moreno Friday, January 26, 2018 alle ore 11:24

        Grazie.
        Per quanto riguarda i fili più lunghi del sensore MQ2 di 1 metro, ci sono problemi?
        Grazie.

      • Michele PisaniAutore Monday, January 29, 2018 alle ore 12:10

        Ciao Moreno,
        ho sempre realizzato prototipi in scala per cui non so darti questa risposta con certezza ma 1 metro non mi sembra tuttavia una misura eccessiva.

  6. Moreno Tuesday, February 6, 2018 alle ore 15:32

    Ciao Michele, trovo problemi con la programmazione dello sketch.
    Da la scritta fatal error :LiquidCrystall_i2c.h: No such file or directory.
    Sai dirmi da cosa dipende e come risolvere il problema.
    Grazie.

    Rispondi a questo commento
    • Michele PisaniAutore Tuesday, February 6, 2018 alle ore 15:48

      Ciao Moreno,
      hai provato a disinstallare l'IDE di Arduino, pulire eventuali suoi file rimasti, e reinstallare la versione aggiornata?
      E' un errore un po' anomalo, è probabile che qualche file si sia corrotto.

      Rispondi a questo commento
  7. Moreno Tuesday, February 6, 2018 alle ore 20:42

    Provato a disinstallare e rimesso arduino 1.8.5 da sempre lo stesso errore, non carica lo sketch.
    E\:sketch_feb06sketch.ino\:2\:31\: fatal error\:LiquidCrystal_I2C.h\: No such file or directory.Non so cosa fare.
    MI puoi dare una dritta come fare.
    Grazie.

    Rispondi a questo commento
    • Michele PisaniAutore Tuesday, February 6, 2018 alle ore 23:08

      Ad occhio sembra che non riesca a trovare la libreria LiquidCrystal_I2C.h
      Hai verificato che nelle preferenze nell'IDE se il percorso dove recupera la cartella degli sketch è corretto? La libreria 'LiquidCrystal_I2C.h' si trova effettivamente in qualche cartella o hai solo copiato ed incollato lo sketch e quindi non la rileva?

      Rispondi a questo commento
  8. Moreno Friday, February 9, 2018 alle ore 17:57

    Scusa se ti disturbo ancora, il problema dovrebbe essere quello che dici.
    Ho incollato il Tuo sketch su una pagina nuova di arduino.
    Sai dirmi come devo fare e dove copiate il tuo sketch per farlo eseguire.
    Grazie, molto gentile.

    Rispondi a questo commento
  9. Moreno Friday, February 9, 2018 alle ore 18:36

    Dove posso scaricare il Tuo sketch il formato zip con le relative librerie da poterlo immettere su arduino o in alternativa come devo fare?
    Il tuo progetto è molto interessante mi dispiace non riuscire ad eseguirlo.
    Di muovo grazie.

    Rispondi a questo commento
  10. Michele PisaniAutore Friday, February 9, 2018 alle ore 19:44

    Prova a vedere se questo link ti aiuta, quantomeno per la libreria 'LiquidCrystal-I2C-library': https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library.

    Lo sketch funziona correttamente, devi solo trovare le librerie e importarle dall'IDE di Arduino da: Sketch > Import Library

    Rispondi a questo commento
  11. Moreno Wednesday, February 14, 2018 alle ore 16:49

    Michele, sono ancora nelle tue mani ma non demordo. Adesso non carica e da \: "POSITIVE" vas not declared in tis scope.
    Sai da cosa dipende?

    Rispondi a questo commento
    • Michele PisaniAutore Wednesday, February 14, 2018 alle ore 17:26

      Ciao Moreno,
      presumo sia un problema di libreria, ce ne sono diverse che hanno nomi simili e soprattutto ci sono versioni diverse, dovresti provare ad installarne altre sempre per LiquidCrystal_I2C (magari cancellando quelle che non ti funzionano per evitare eventuali conflitti tra loro).
      Mi sono ritrovato anch'io a volte ad andare a tentativi per trovare quelle effettivamente funzionanti nei diversi sketch.
      Non ricordo nel caso specifico quale ho usato, ho scritto questo articolo un anno fa. Provo a dare un'occhiata se riesco a risalirci tuttavia se fai una ricerca su Google farai senz'altro prima e vedrai che ci sono molti post a riguardo, il problema in questione è abbastanza diffuso e molti l'hanno risolto (sempre in rete, tra i messaggi nei forum anche stranieri, ci sono utenti che hanno inserito un link alla libreria presumibilmente funzionante, puoi verificare se quelle fanno al caso tuo).

      Rispondi a questo commento
  12. Moreno Thursday, February 15, 2018 alle ore 15:09

    Ciao Michele, l'indirizzo del mio LCD non è Ox27 ma lo trova a Ox3f.
    Come modifichi lo sketch?
    Saluti.

    Rispondi a questo commento
    • Michele PisaniAutore Thursday, February 15, 2018 alle ore 15:54

      Lo sketch del tutorial è basato sun display con 16 caratteri e righe.
      Se hai un LCD a 20 caratteri e 4 righe, che corrisponde allo 0x3f lo script sarà tipo:

      LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 6, 5, 7, 3, POSITIVE);
      //...
      lcd.begin(20,4);

      Rispondi a questo commento
  13. Moreno Thursday, February 15, 2018 alle ore 17:02

    Ho un LCD 16 caratteri e 2 righe.
    Cambiato la riga con questa:
    LiquidCristal_I2C lcd (0x3f, 16, 2);
    Lo sketch si carica ma non va.

    Rispondi a questo commento
    • Michele PisaniAutore Thursday, February 15, 2018 alle ore 18:03

      Secondo me devi cercare un'altra libreria che ti funzioni con il valore 0x27 (dato che il display sembra essere lo stesso che ho usato nel video).

      Hai provato a togliere tutti i riferimenti relativi all'LCD dallo sketch e provare a vedere se il resto ti funziona? In quel modo avresti intanto un sistema funzionante (senza visualizzare i valori nell'LCD), dopodiché puoi concentrarti a far funzionare l'LCD indipendentemente da tutto il resto dei sensori collegati.

      Rispondi a questo commento
  14. Moreno Thursday, February 15, 2018 alle ore 18:42

    Questo sketch lo carica e suona perfettamente quando rileva il gas, ma non va lcd.
    invio sketch:
    #include
    #include

    LiquidCrystal_I2C lcd(0x3f, 16, 2);

    const int buzzerPin = 12;
    const int ledPin = 11;
    const int sensorPin = A0;
    const int intervallo_base = 200;

    int sensorValue = 0;
    int sensorAlertMinValue = 200;
    int ledValue = 0;
    bool buzzerTone = 0;

    unsigned long currentMillis = 0;
    unsigned long previousMillis = 0;

    void setup(void) {
    lcd.begin(16, 2);
    pinMode(buzzerPin, OUTPUT);
    pinMode(ledPin, OUTPUT);
    }

    void loop(void) {
    currentMillis = millis();
    sensorValue = analogRead(sensorPin);

    lcd.setCursor(0, 0);
    lcd.print("Rilevamento GAS:");
    lcd.setCursor(0, 1);
    lcd.print("sensorValue");

    if (sensorValue > sensorAlertMinValue) {
    ledValue = HIGH;
    if ((currentMillis - previousMillis) >= (intervallo_base) && buzzerTone == 0) {
    noTone(buzzerPin);
    tone(buzzerPin, 500, 1000);
    buzzerTone = 1;
    updateMillis();
    }
    if ((currentMillis - previousMillis) >= (intervallo_base) && buzzerTone == 1) {
    noTone(buzzerPin);
    tone(buzzerPin, 300, 1000);
    buzzerTone = 0;
    updateMillis();
    }
    } else {
    ledValue = LOW;
    }

    digitalWrite(ledPin, ledValue);
    delay(100);

    }

    void updateMillis() {
    previousMillis = currentMillis;
    }

    Rispondi a questo commento
    • Michele PisaniAutore Thursday, February 15, 2018 alle ore 18:49

      Già il fatto che funzioni è positivo. Bene!
      Per quanto riguarda l'LCD prova a girare il regolatore di luminosità, quella sorta di vite grigia all'interno dell'elemento celeste, mi è capitato in un'occasione con un altro progetto di non vedere niente sul display ma era in realtà un problema di luminosità (fai una prova con il programma in esecuzione così sei sicuro che qualcosa di scritto da poter visualizzare c'è).

      Rispondi a questo commento
  15. Moreno Thursday, February 15, 2018 alle ore 19:01

    No non è quello il problema.
    Prima ho installato uno sketch per provare LCD e tutto va bene è apparsa la scritta hallo word.
    Quqado apro per vedere i valori gas non li da.

    Rispondi a questo commento
    • Michele PisaniAutore Thursday, February 15, 2018 alle ore 19:06

      Se l'hai provato con l'I2C ed in quel caso l'LCD ha funzionato ti basta utilizzare quella libreria e quelle impostazioni usate nello sketch funzionante e sostituirle in questo del rilevatore di gas.

      Rispondi a questo commento
  16. Moreno Friday, February 16, 2018 alle ore 13:47

    Michele sono ancore qua, ti mando lo sketch che funziona per far apparire la scritta nei LCD,non riesco a modificare il tuo, per cortesia a tempo perso,gli puoi dare una guardata. Grazie per la Tua pazienza.
    //DT Studio
    //Compatible with the Arduino IDE 1.0
    //Library version\:1.1
    \#include
    \#include

    LiquidCrystal_I2C lcd(0x3f,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display

    void setup()
    {
    lcd.init(); // initialize the lcd

    // Print a message to the LCD.
    lcd.backlight();
    lcd.print("Hello,DT Studio!");
    }

    void loop()
    {
    }

    Rispondi a questo commento
  17. Moreno Friday, February 16, 2018 alle ore 18:27

    Salve Michele, in alternativa questo sketch funziona tutto e rileva il gas il problema sta nell’LCD, appare “rilevamento gas” nella prima riga, ma nella seconda riga appare zero fisso e non da valori rilevati. Cortesemente mi correggi l’errore, grazie.

    //Moreno Radi
    #include
    #include

    LiquidCrystal_I2C lcd(0x3f,16, 2);
    const int sensorPin= A0;
    const int buzzerPin= 13;
    int smoke_level;

    void setup()
    {
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print(“Rilevamenti GAS”);
    lcd.setCursor(0, 1);
    lcd.print(smoke_level);
    Serial.begin(9600); //sets the baud rate for data transfer in bits/second
    pinMode(sensorPin, INPUT);//the smoke sensor will be an input to the arduino
    pinMode(buzzerPin, OUTPUT);//the buzzer serves an output in the circuit
    }

    void loop() {
    Serial.println(smoke_level);//prints just for debugging purposes, to see what values the sensor is picking up
    smoke_level= analogRead(A0); //arduino reads the value from the smoke sensor
    if(smoke_level > 200){ //if smoke level is greater than 200, the buzzer will go off
    digitalWrite(buzzerPin, HIGH);
    }
    else{
    digitalWrite(buzzerPin, LOW);
    }
    }

    Rispondi a questo commento
    • Michele PisaniAutore Friday, February 16, 2018 alle ore 19:01

      Ciao Moreno,
      non vedi cambiare l'LCD perchè nel loop() non è mai utilizzato.
      Prova ad inserire le seguenti righe:

      lcd.setCursor(0, 0);
      lcd.print("Rilevamento GAS:");
      lcd.setCursor(0, 1);
      lcd.print(smoke_level);

      Sotto alla riga:

      Serial.println(smoke_level);

      Rispondi a questo commento
  18. Moreno Friday, February 16, 2018 alle ore 19:44

    PERFETTO GRAZIE DI CUORE, la costanza e i buoni consigli pagano sempre.
    Grazie.
    Moreno.

    Rispondi a questo commento
  19. Moreno Friday, February 16, 2018 alle ore 20:54

    Mi sono accorto ora che quando il valore gas va su e poi va sotto 100 rimane uno zero, se il valore è 40 nel lcd è 400,sai dirmi come fare per eliminare lo zero di troppo.

    Rispondi a questo commento
  20. Moreno Saturday, February 17, 2018 alle ore 12:12

    Michele io non sono al Tuo livello di conoscenza in materia. Purtroppo.
    Quando i valori salgono va tutto bene, il problema è quando scendono e arrivano a 100.
    Dopo i 100 passano a 990 sul LCD ma in realta sono 99 , 330 ma sono 33.Se spengo e riaccendo lo zero di troppo va via , ma rifa lo stesso problema quando rileva il gas e va sopra 100.

    Rispondi a questo commento
  21. Michele PisaniAutore Saturday, February 17, 2018 alle ore 13:15

    Quel comportamento è dovuto al fatto che ad ogni loop i nuovi caratteri sovrascrivono i precedenti pertanto se il numero dei caratteri è sempre lo stesso non si nota niente di strano ma se il successivo numero di caratteri è inferiore al precedente, quelli eccedenti non vengono sovrascritti.

    Prova a sostituire queste righe di codice:

    lcd.setCursor(0, 0);
    lcd.print("Rilevamento GAS:");
    lcd.setCursor(0, 1);
    lcd.print(smoke_level);

    con queste:

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Rilevamento GAS:");
    lcd.setCursor(0, 1);
    lcd.print(smoke_level);
    delay(100);

    Rispondi a questo commento
  22. Moreno Saturday, February 17, 2018 alle ore 14:16

    Problema risolto, ma per la perfezione sfarfalla leggermente la scritta nel LCD

    Rispondi a questo commento
    • Michele PisaniAutore Saturday, February 17, 2018 alle ore 17:09

      Nello sketch, così come lo hai costruito, puoi provare ad aumentare il valore del dalay per rendere meno fastidioso lo sfarfallio:
      Ad esempio:

      delay(500);

      In ogni caso il delay mette in pausa l'Arduino per il lasso di tempo definito. Non credo comporti grosse complicazioni nel caso specifico tuttavia l'approccio migliore è quello di utilizzare millis() anziché il classico delay() per garantire un più efficace ed immediato recupero delle informazioni rilevate (come ho descritto nell'articolo).

      Rispondi a questo commento
  23. Moreno Saturday, February 17, 2018 alle ore 18:13

    Ora tutto è perfetto, grazie per i tuoi consigli e la tua professionalità, persona molto gentile e disponibile.
    Ciao e di nuovo GRAZIE.

    Rispondi a questo commento
  24. Moreno Monday, February 19, 2018 alle ore 14:51

    Ciao Michele, visto che sei così gentile, mi sono incuriosito di sostituire delay(500); con millis(); per vedere l'effetto che fa, come da Te consigliato.
    Premetto che delay(55); va benissimo.
    Come correggo lo sketch, elimino delay(500); e lo sostituisco con millis(500);
    Grazie.

    Rispondi a questo commento
    • Michele PisaniAutore Monday, February 19, 2018 alle ore 18:17

      Ciao Moreno,
      per l'utilizzo della funzione millis() devi fare riferimento al codice nello sketch dell'articolo, non basta sostituire il delay come hai scritto, anche perchè millis() non accetta parametri e la sua logica funziona in altro modo.

      Considerando che nello sketch che hai attualmente l'LCD ti funziona correttamente, a mio avviso, ti basta riportare la relativa configurazione che hai sul tuo sketch in quello mio ed hai già tutto pronto.

      Rispondi a questo commento
  25. Moreno Monday, February 19, 2018 alle ore 18:44

    OK, farò anche questa prova.
    Grazie.

    Rispondi a questo commento
  26. Ezio Cogoli Saturday, January 15, 2022 alle ore 15:08

    Ottimo e sembra..., semplice...

    Rispondi a questo commento

Scrivi un Commento

Il tuo indirizzo email non sarà pubblicato.
I campi contrassegnati da un * sono obbligatori

Articoli e Argomenti correlati

Il Canale YouTube in ITALIANO

1 VIDEO GRATIS ogni 2 settimane! ISCRIVITI!

Entra a far parte della community su Facebook

Categorie popolari

Iscriviti alla mia newsletter

La tua e-mail con me sarà al sicuro.
Non fornirò mai le tue informazioni a nessuno!

Ultimi commenti

Michele Pisani

Ciao Anna Rita, diciamo che... esisteva. Ho mantenuto il prodotto gratuitamente fintanto che ho …

sassacy

Questo articolo è molto interessante e utile ((((jajatemple@null.net))). Quando sei innamorato e …

christina

Ho ripristinato il mio matrimonio in crisi dopo il mio incontro in sole 48 ore con il sacerdote …

Michele Pisani

Ciao Vincenzo, per i vari video l'obiettivo è soffermarsi sul video e ricopiarli in modo da …