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
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!
Complimenti bell'articolo
Grazie Gian, fa sempre piacere che qualcuno apprezzi un lavoro e si soffermi un attimo per comunicarlo esplicitamente :)
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.
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);
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.
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à.
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.
Di niente Angelo, l'importante è che sei riuscito a risolvere.
salve,mi interessa il progetto sensore gas ,per applicazioni in agricoltura.Vedremo gli sviluppi.ottimo programma.
Grazie Paolo,
spero possa tornarti utile per i tuoi scopi.
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.
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.
Grazie.
Per quanto riguarda i fili più lunghi del sensore MQ2 di 1 metro, ci sono problemi?
Grazie.
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.
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.
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.
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.
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?
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.
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.
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
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?
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).
Ciao Michele, l'indirizzo del mio LCD non è Ox27 ma lo trova a Ox3f.
Come modifichi lo sketch?
Saluti.
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);
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.
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.
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;
}
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'è).
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.
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.
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()
{
}
Ciao Moreno,
ti ho risposto nel tuo messaggio che hai scritto successivamente.
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);
}
}
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);
PERFETTO GRAZIE DI CUORE, la costanza e i buoni consigli pagano sempre.
Grazie.
Moreno.
Ottimo! Mi fa piacere che tu sia riuscito a risolvere.
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.
Se dai un'occhiata a questo sketch trovi la soluzione:
Water Sensor per Misurare il Livello di Liquido in un Serbatoio
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.
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);
Problema risolto, ma per la perfezione sfarfalla leggermente la scritta nel LCD
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).
Ora tutto è perfetto, grazie per i tuoi consigli e la tua professionalità, persona molto gentile e disponibile.
Ciao e di nuovo GRAZIE.
Grazie a te Moreno :)
Un saluto e buon proseguimento con il tuo progetto!
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.
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.
OK, farò anche questa prova.
Grazie.
Ottimo e sembra..., semplice...