Senzor reaguje nejvíce na oxid uhelnatý (CO) ale i na hořlavé plyny metan a propan. Aktivním prvkem tohoto senzoru je tenká vrstva SnO2, jejíž odpor se mění s koncentrací zmíněných plynů. Funkce senzoru je vysvětlena v řadě článků na webu, zde jsou uvedeny dva odkazy a další jsou ještě v textu.Některé výpisy z těchto článků jsou uvedeny na konci textu jako přílohy k tomuto článku. https://www.digikey.be/htmldatasheets/production/2087922/0/0/1/mq-9.html
Napájecí napětí senzoru MQ-9 je 5V. Proudový odběr je maximálně 70 mA při počátečním zahřívání senzoru. Pokud budete tedy chtít používat i další moduly na stejném napájení Arduina, je nutné si dávat pozor na celkový proudový odběr a případně použít pro senzor MQ-9 externí zdroj.
Pro úspěšné propojení senzoru plynů MQ-9 a Arduino desky je nutné zapojit celkem 4 vodiče. Propojíme VCC s +5V Arduina, GND se zemí Arduina, D0 s pinem D2 a A0 s pinem A0. Pro analogový vstup je možné vybrat jiný analogový pin, ale je nutné tuto volbu provést také na začátku programu. Pro digitální vstup je nutné vybrat pin, který slouží jako přerušovací.
Kód pro Arduino:
//Arduino-sensor-MQ-9-CO-po2.ino
//zjednodušená verze programu Arduino-sensory-MQ-Dratek-po1.ino pouze na MQ-9 CO
// Senzor horlavych plynu MQ-2 a MQ-9
// sketch je funkcni i pro MQ-9
// rozsireni funkci o polograficky vystup
// a o vystup na bzucak
// Cisla pinu pripojeneho digitalniho
// a analogoveho vstupu
const int dOut = 2;
const int aOut = A0;
int bzucak = 4;
// promenne pro cteni napeti analogoveho vstupu
int analog = 0;
int analogPam = 0;
int analogLimit = 60; //muze se u kazdeho sensoru lisit
int analogDelta = 0;
int delayInt = 1000;
int RS_air;
int RS_gas;
float ratio;
float procento;
int konstantappm;
int konstantappmCO = 250; //pokusny odhad
//int konstantappmLPG = 1000; //pokusny odhad
float procentoCO = 2; // pokusny odhad pro CO
bool ppmOn = false;
//bool sensorLPG;
bool dataOn = false;
bool korekceOn = true;
bool grafOn = false;
//promenne pro volbu funkci
bool nadpisOn = false;
char ZnakRx = 0;
byte Datamode = 0;
unsigned long pznaky = 0;
// promenne pro bzucak
int Frekvence = 700;
int doba = 100;
bool bzucakOn = false;
void setup() {
// komunikace pres seriovou linku rychlosti 9600 baud
Serial.begin(9600);
// inicializace vstupu a vystupu
pinMode(dOut, INPUT);
pinMode(aOut, INPUT);
pinMode(bzucak, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// nastaveni preruseni na pin 2 (int0)
// pri klesajici hrane (log1->log0) se vykona program prerus - nepouzito
//attachInterrupt(0, prerus, FALLING);
dataOn = false;
nadpisOn = true;
bzucakOn = false;
ppmOn = false;
korekceOn = true;
grafOn = true;
Datamode = 65;
analogLimit = 100;
analogPam = 0;
//sensorLPG = false;
konstantappm = konstantappmCO;
digitalWrite(bzucak, LOW);
digitalWrite(LED_BUILTIN, LOW); // turn the LED on (LOW is the voltage level)
;
}
void loop() {
if (nadpisOn == false) {
Serial.println("Sensor plynu MQ-9 CO - volba:");
Serial.println("A=Mereni, P=ppm/%, V=Vypis dat On/Off, K=Korekce RsA On/Off, Rxx=RS_Air limit !");
Serial.println("Bzucak B=On/Off, Dxx=Delka zvuku [ms], Fxx=Frekvence [Hz], G=Graf On/Off, S=Stop !");
nadpisOn = true;
ZnakRx = 0;
analogPam = 0;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (High is the voltage level)
}
if (Serial.available()) {
ZnakRx = Serial.read();
//Serial.print("zadana volba: ");
//Serial.println(ZnakRx);
Serial.flush();
if (ZnakRx == 83) // S
{
//Serial.println(" => Stop :");
Datamode = 83;
nadpisOn = false;
}
if (ZnakRx == 82) // R
{
String Pstring = Serial.readString();
Pstring.trim();
analogLimit = Pstring.toInt();
Serial.print("Procentni limit RS_air: ");
Serial.print(analogLimit);
Serial.println("a.u. !");
//nadpisOn = false;
}
if (ZnakRx == 66) // B
{
if (bzucakOn == true) {
bzucakOn = false;
} else {
bzucakOn = true;
}
Serial.print("Bzucak: ");
if (bzucakOn == true) {
Serial.println("On !");
} else {
Serial.println("Off !");
}
//nadpisOn = false;
}
if (ZnakRx == 80) // P
{
if (ppmOn == true) //Merilo se v ppm
{
ppmOn = false;
} else {
ppmOn = true;
}
Serial.print("Mereni v ppm: ");
if (ppmOn == true) {
Serial.println("On !");
} else {
Serial.println("Off !");
}
//nadpisOn = false;
}
if (ZnakRx == 70) // F
{
String Pstring = Serial.readString();
Pstring.trim();
Frekvence = Pstring.toInt();
Serial.print("Frekvence : ");
Serial.print(Frekvence);
Serial.println(" Hz !");
//nadpisOn = false;
}
if (ZnakRx == 68) // D
{
String Pstring = Serial.readString();
Pstring.trim();
doba = Pstring.toInt();
Serial.print("Delka zvuku : ");
Serial.print(doba);
Serial.println(" ms !");
//nadpisOn = false;
}
if (ZnakRx == 65) {
Datamode = 65; //Obnova mereni
Serial.println("Mereni je aktivovano !");
}
if (ZnakRx == 86) // V
{
if (dataOn == true) {
dataOn = false;
} else {
dataOn = true;
}
Serial.print("Vypis servisnich dat: ");
if (dataOn == true) {
Serial.println("On !");
} else {
Serial.println("Off !");
}
//nadpisOn = false;
}
if (ZnakRx == 71) // G
{
if (grafOn == true) {
grafOn = false;
} else {
grafOn = true;
}
Serial.print("Graf dat: ");
if (grafOn == true) {
Serial.println("On !");
} else {
Serial.println("Off !");
}
//nadpisOn = false;
}
if (ZnakRx == 75) // K
{
if (korekceOn == true) //Korekce RS_air (RsA)
{
korekceOn = false;
} else {
korekceOn = true;
}
Serial.print("Korekce RS_air: ");
if (korekceOn == true) {
Serial.println("On !");
} else {
Serial.println("Off !");
}
}
if (Datamode == 83) {
Serial.println("S - Stop of all actions");
nadpisOn = false;
dataOn = false;
bzucakOn = false;
}
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (LOW is the voltage level)
ZnakRx = 0;
Serial.flush();
if (dataOn == true) {
Serial.print("Datamode: ");
Serial.println(Datamode);
}
}
//zacetek mereni
if (Datamode == 65) {
// nacteni hodnoty analogoveho vstupu
analog = analogRead(aOut);
if (dataOn == true) {
Serial.print("Analogova hodnota: ");
Serial.print(analog);
Serial.println(" a.u.");
}
analogDelta = analog - analogLimit;
if (analogDelta < 0) {
analogLimit = analog;
Serial.print("Delta minus: ");
Serial.print(analogDelta);
Serial.println(" a.u.");
Serial.print("Korekce limitu RS_air: ");
Serial.println(analogLimit);
}
RS_air = analogLimit;
RS_gas = analog;
ratio = (float)RS_gas / RS_air;
if (dataOn == true) {
Serial.print("ratio :");
Serial.println(ratio);
}
if (ratio > 1) {
// prepocet nactenych dat
// na koncentraci ppm 0-500 pro CO
ratio = ratio - 1;
} else {
ratio = 0;
}
//if (analog != analogPam)
//{
if (analog <= analogLimit) {
if (dataOn == true) {
Serial.println("Limit RS_air On and Bzucak On !");
}
bzucakOn = true;
digitalWrite(bzucak, LOW);
}
analogDelta = analog - analogLimit;
if (analogDelta > 0) {
if (dataOn == true) {
Serial.print(analogDelta);
Serial.println(" a.u.");
}
}
procento = ratio * procentoCO; // odhad
if (ppmOn == false) {
Serial.print(procento);
Serial.print("%");
if (analogDelta > 2) {
for (int i = 1; i < analogDelta; i++) {
Serial.print(" ");
}
Serial.println("*");
} else {
Serial.println(" ");
}
} else {
// vypocteme odhad koncentrace plynu
float ppm = ratio * konstantappm;
//float ppm = ratio * ppmCOkonstanta; //pokusny odhad
//float ppm = procento * konstantappm;
Serial.print(ppm);
Serial.println(" ppm");
}
if (bzucakOn = true) {
// zahraj(frekvence, doba),
// kde frekvence je v Hertzech a doba v milisekundach
if (analogDelta > 2) {
zahraj(Frekvence, doba);
}
}
analogPam = analog;
if (analogDelta < 2) {
// vyckej 1 sec kvuli zbytecnemu mnozstvi tisknutych znaku
delayInt = 1000;
delay(delayInt);
} else {
delayInt = 1000 - (analogDelta * 10);
if (delayInt <= 0) {
delayInt = 250;
}
if (dataOn == true) {
delayInt = 500;
}
delay(delayInt);
}
if (dataOn == true) {
Serial.print("Timeout: ");
Serial.println(delayInt);
}
}
}
// podprogram zahraj obsahuje vsechny dulezite
// funkce pro zahrani zadaneho zvuku
void zahraj(int frequence, int delka) {
// funkce tone ma na prvnim miste pin
// s pripojenym bzucakem, na druhem
// frekvenci hraneho zvuku a na tretim
// dobu hrani zvuku v milisekundach;
// maximalni frekvence je 65535 Hz,
// pro cloveka neslysitelna frekvence
tone(bzucak, frequence, delka);
digitalWrite(bzucak, LOW);
}
void prerus() {
// vypis varovnou hlasku, pokud je aktivovan digitalni vstup
// a senzor byl ustalen alespon po dobu 180s = 3 minut
if (millis() > 180000) {
Serial.println("Prekonana hranice plynu v okoli!");
delay(1000);
}
}
První část ukázkového kódu slouží pro zjištění měřící konstanty, která je následně použita v druhé části programu.
Na začátku první části programu si nastavíme propojovací analogový pin a poté vytvoříme proměnné, které budeme používat pro měření.
V podprogramu setup provedeme pouze inicializaci sériové linky, přes kterou budeme komunikovat.
Nekonečná smyčka loop v prvním kroku provede více měření, v kterých budeme přičítat do měřící proměnné hodnotu načtenou z analogového pinu.
Po ukončení měření pak výsledek vydělíme počtem měření a tím získáme průměr. Tento průměr poté využijeme pro výpočet hodnoty vstupního napětí odpovídajícího odporu čistého vzduchu.
Získanou potřebnou konstantu RS_air si pak uložíme pro následující měření. Zřejmě suchý vzduch dává v senzoru větší odpor než jiné hořlavé plyny.
Je nutné počítat s tím, že každý senzor se může mírně lišit a také záleží, v jak čistém prostředí měříte svoji „nulovou“ hodnotu.
Nekonečná smyčka loop v tomto případě už obsahuje pouze jedno načtení hodnoty z analogového pinu. Tuto hodnotu následně použijeme pro výpočet vstupního napětí a poté pro výpočet aktuálního odporu zkoumaného plynu.
A když máme nyní k dispozici konstantu RS_air, můžeme vypočítávat poměr RS_gas/RS_air, pomocí kterého můžeme následně vypočítat přibližnou koncentraci daných plynů podle grafu uvedeného níže.
V přílohách je uveden výpis zněkterých měření po sériové lince z monitoru, který je příslušenstvím k programu Arduino IDE.
A po pauze jedné sekundy se provede další měření a tak dále v opakovaném cyklu.
Na grafu je znázorněn relativí poměr odporu čistého vzduch a několika hořlavých plynů včetně CO .
Pro kalibraci senzoru v profesionálních přístrojů se používá plyn LPG v koncetraci 1000 ppm .
Senzor oxidu uhelnatého je zajímavý modul pro Arduino, který nám umožňuje měřit i koncentraci několika plynů v okolí. Může tedy nalézt uplatnění v projektech, které se zabývají měřením kon-centrací těchto plynů jak v domácnosti, tak třeba i na pracovišti.
Ve sketchi pro Arduino byl také uveden přepočet naměřeného poměru na koncentraci v jednotce ppm. Tento výpočet ale není příliš přesný, protože převodní konstata z poměru RS_gas na RS_air je zde pouze empiricky odhadnutá.
Ještě je potřeba k senzoru MQ-9 doplnit několik informací:
Zaprvé je nutné vždy senzor nechat řádně zahřát na pracovní teplotu, což znamená minimálně 5-10 minut, respektive do ustálení měřené srovnávací hodnoty.
Zadruhé je s tím spojené upozornění ohledně umístění senzoru. Pracovní teplota kovového pouzdra senzoru je cca 40 °C (lze udržet v ruce), ale je nutné si dát na toto pozor při uzavírání do krabiček apod. .
A třetí věc souvisí s předchozími – díky nutnosti předehřátí senzoru a poměrně vysokému proudovému odběru tento senzor není příliš vhodný do bateriově napájených zařízení.
Lze je ale použít s mobilem, na kterém máme nainstalovanou apku Serial USB Terminal, což je obdoba prográmku Terminal pro PC.
Seznam použitých komponent:
Poznámky:
Pro přesné měření hodnot CO je nutné přepínat mezi napájením 5V a 1,5V, přičemž napětí 1,5V musíme zajistit externím zdrojem. Pokud budete měřit pouze s 5V napájením, budete vždy měřit pouze koncentraci hořlavých plynů zmíněných v úvodu.
30.10.2024
Návod z Dratek.cz doplnil PavelOu
Link na použité informace :
https://en.wikipedia.org/wiki/Carbon_monoxide_detector
Semiconductor type
Thin wires of the semiconductor tin dioxide on an insulating ceramic base provide a sensor monitored by an integrated circuit. This sensing element must be heated to approximately 400 °C for operation. Oxygen increases the resistance of the tin dioxide while carbon monoxide reduces it. The integrated circuit monitors the resistance of the sensing element. Lifespans are approximately five years and alarms need testing on installation and at least annually with a test gas.
Due to the large power demand of this sensor, it is usually powered from the mains. A battery-powered, pulsed sensor is available with a lifetime of months.
https://en.wikipedia.org/wiki/Tin(IV)_oxide
Gas sensing
SnO2 is used in sensors of combustible gases including carbon monoxide detectors. In these the sensor area is heated to a constant temperature (few hundred °C) and in the presence of a combustible gas the electrical resistivity drops. Room temperature gas sensors are also being developed using reduced graphene oxide-SnO2 composites(e.g. for ethanol detection).
Doping with various compounds has been investigated (e.g. with CuO[25]). Doping with cobalt and manganese, gives a material that can be used in e.g. high voltage varistors. Tin(IV) oxide can be doped with the oxides of iron or manganese.
https://en.wikipedia.org/wiki/Graphene
Graphene is known for its exceptionally high tensile strength, electrical conductivity, transparency, and being the thinnest two-dimensional material in the world.