update library

This commit is contained in:
Igor 2018-01-19 21:37:03 +03:00
parent 61dc0f9349
commit 4c7567255b
51 changed files with 690 additions and 392 deletions

View File

@ -1,113 +0,0 @@
#include "BaseMQ.h"
BaseMQ::BaseMQ(uint8_t pin) :
_pin (pin) {
}
BaseMQ::BaseMQ(uint8_t pin, uint8_t pinHeater) :
_pin (pin),
_pinHeater (pinHeater)
{
pinMode(_pinHeater, OUTPUT);
}
// калибровка датчика
void BaseMQ::calibrate(float ro) {
_ro = ro;
_stateCalibrate = true;
}
// калибровка датчика
void BaseMQ::calibrate() {
float ro = 0;
for (int i = 0; i < MQ_SAMPLE_TIMES; i++) {
ro += calculateResistance(analogRead(_pin));
delay(MQ_SAMPLE_INTERVAL);
}
ro = ro/MQ_SAMPLE_TIMES;
ro = ro/getRoInCleanAir();
calibrate (ro);
}
void BaseMQ::heaterPwrHigh() {
digitalWrite(_pinHeater, HIGH);
_heater = true;
_prMillis = millis();
}
void BaseMQ::heaterPwrLow() {
analogWrite(_pinHeater, 75);
_heater = true;
_cooler = true;
_prMillis = millis();
}
void BaseMQ::heaterPwrOff() {
digitalWrite(_pinHeater, LOW);
_heater = false;
}
// сопротивление датчика
float BaseMQ::calculateResistance(int rawAdc) const {
float vrl = rawAdc*(5.0 / 1023);
float rsAir = (5.0 - vrl)/vrl*getRL();
return rsAir;
}
// считывание датчика
float BaseMQ::readRs() const {
float rs = 0;
for (int i = 0; i < MQ_SAMPLE_TIMES; i++) {
rs += calculateResistance(analogRead(_pin));
delay(MQ_SAMPLE_INTERVAL);
}
rs = rs/MQ_SAMPLE_TIMES;
return rs;
}
unsigned long BaseMQ::readScaled(float a, float b) const {
float ratio = readRatio();
return exp((log(ratio)-b)/a);
}
float BaseMQ::readRatio() const {
return readRs()/getRo();
}
bool BaseMQ::heatingCompleted() const {
if ((_heater) && (!_cooler) && (millis() - _prMillis > 60000))
return true;
else
return false;
}
bool BaseMQ::coolanceCompleted() const {
if ((_heater) && (_cooler) && (millis() - _prMillis > 90000))
return true;
else
return false;
}
void BaseMQ::cycleHeat() {
_heater = false;
_cooler = false;
heaterPwrHigh();
#ifdef MQDEBUG
Serial.println("Heated sensor");
#endif //MQDEBUG
}
bool BaseMQ::atHeatCycleEnd() {
if (heatingCompleted()) {
heaterPwrLow();
#ifdef MQDEBUG
Serial.println("Cool sensor");
#endif //MQDEBUG
return false;
} else if (coolanceCompleted()) {
heaterPwrOff();
return true;
} else {
return false;
}
}

View File

@ -1,47 +0,0 @@
#ifndef BaseMQ_H
#define BaseMQ_H
#include <Arduino.h>
// кол-во считываний значений в цикле
#define MQ_SAMPLE_TIMES 5
// задержка после каждого считывания датчика
#define MQ_SAMPLE_INTERVAL 20
class BaseMQ {
public:
BaseMQ(uint8_t pin);
BaseMQ(uint8_t pin, uint8_t pinHeater);
void calibrate();
void calibrate(float ro);
void heaterPwrHigh();
void heaterPwrLow();
void heaterPwrOff();
void cycleHeat();
bool atHeatCycleEnd();
bool heatingCompleted() const;
bool coolanceCompleted() const;
float readRatio() const;
inline bool isCalibrated() const {
return _stateCalibrate;
};
inline float getRo() const {
return _ro;
};
protected:
unsigned long readScaled(float a, float b) const;
virtual float getRoInCleanAir() const = 0;
virtual int getRL() const = 0;
private:
bool _heater = false;
bool _cooler = false;
bool _stateCalibrate = false;
unsigned long _prMillis = 0;
float _ro = 1.0f;
uint8_t _pin;
uint8_t _pinHeater;
float readRs() const;
float calculateResistance(int rawAdc) const;
};
#endif

21
MQ2.h
View File

@ -1,21 +0,0 @@
#ifndef MQ2_H_
#define MQ2_H_
#include "BaseMQ.h"
class MQ2 : public BaseMQ {
public:
MQ2(uint8_t pin);
MQ2(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
unsigned long readSmoke();
unsigned long readHydrogen();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 5; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 9.83; }
};
#endif // MQ2_H_

19
MQ3.h
View File

@ -1,19 +0,0 @@
#ifndef MQ3_H_
#define MQ3_H_
#include "BaseMQ.h"
class MQ3 : public BaseMQ {
public:
MQ3(uint8_t pin);
MQ3(uint8_t pin, uint8_t pinHeater);
float readAlcoholMgL();
float readAlcoholPpm();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 200; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 60; }
};
#endif // MQ3_H_

18
MQ4.h
View File

@ -1,18 +0,0 @@
#ifndef MQ4_H_
#define MQ4_H_
#include "BaseMQ.h"
class MQ4 : public BaseMQ {
public:
MQ4(uint8_t pin);
MQ4(uint8_t pin, uint8_t pinHeater);
unsigned long readMethane();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 20; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 4.4; }
};
#endif // MQ4_H_

19
MQ5.h
View File

@ -1,19 +0,0 @@
#ifndef MQ5_H_
#define MQ5_H_
#include "BaseMQ.h"
class MQ5 : public BaseMQ {
public:
MQ5(uint8_t pin);
MQ5(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 20; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 6.5; }
};
#endif // MQ5_H_

18
MQ6.h
View File

@ -1,18 +0,0 @@
#ifndef MQ6_H_
#define MQ6_H_
#include "BaseMQ.h"
class MQ6 : public BaseMQ {
public:
MQ6(uint8_t pin);
MQ6(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 20; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 10; }
};
#endif // MQ6_H_

18
MQ7.h
View File

@ -1,18 +0,0 @@
#ifndef MQ7_H_
#define MQ7_H_
#include "BaseMQ.h"
class MQ7 : public BaseMQ {
public:
MQ7(uint8_t pin);
MQ7(uint8_t pin, uint8_t pinHeater);
unsigned long readCarbonMonoxide();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 10; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 27; }
};
#endif // MQ7_H_

18
MQ8.h
View File

@ -1,18 +0,0 @@
#ifndef MQ8_H_
#define MQ8_H_
#include "BaseMQ.h"
class MQ8 : public BaseMQ {
public:
MQ8(uint8_t pin);
MQ8(uint8_t pin, uint8_t pinHeater);
unsigned long readHydrogen();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 10; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 70; }
};
#endif // MQ8_H_

20
MQ9.h
View File

@ -1,20 +0,0 @@
#ifndef MQ9_H_
#define MQ9_H_
#include "BaseMQ.h"
class MQ9 : public BaseMQ {
public:
MQ9(uint8_t pin);
MQ9(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
unsigned long readCarbonMonoxide();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return 10; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return 9.8; }
};
#endif // MQ9_H_

View File

@ -25,3 +25,16 @@
Подробности и примеры работы для [датчика MQ-8](http://wiki.amperka.ru/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq8).
Подробности и примеры работы для [датчика MQ-9](http://wiki.amperka.ru/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq9).
В библиотеки используются коэффициенты для поиска значений в ppm для каждого газа, которые были найдены путём линейной и логарифмической аппроксимации графика из даташита.
Скачать исходники:
[MQ-2](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq2:mq2_graph_factors.zip),
[MQ-3](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq3:mq3_graph_factors.zip),
[MQ-4](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq4:mq4_graph_factors.zip),
[MQ-5](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq5:mq5_graph_factors.zip),
[MQ-6](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq6:mq6_graph_factors.zip),
[MQ-7](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq7:mq7_graph_factors.zip),
[MQ-8](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq8:mq8_graph_factors.zip),
[MQ-9](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq9:mq9_graph_factors.zip),
[MQ-135](http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq135:mq135_graph_factors.zip)

View File

@ -1,13 +0,0 @@
#ifndef TROYKAMQ_H_
#define TROYKAMQ_H_
#include "MQ2.h"
#include "MQ3.h"
#include "MQ4.h"
#include "MQ5.h"
#include "MQ6.h"
#include "MQ7.h"
#include "MQ8.h"
#include "MQ9.h"
#endif // TROYKAMQ_H_

View File

@ -0,0 +1,36 @@
// библиотека для работы с датчиками MQ (Troyka-модуль)
#include <TroykaMQ.h>
// имя для пина, к которому подключен датчик
#define PIN_MQ135 A0
// создаём объект для работы с датчиком и передаём ему номер пина
MQ135 mq135(PIN_MQ135);
void setup()
{
// открываем последовательный порт
Serial.begin(9600);
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq135.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 160
// mq135.calibrate(160);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq135.getRo());
}
void loop()
{
// выводим отношения текущего сопротивление датчика
// к сопротивлению датчика в чистом воздухе (Rs/Ro)
Serial.print("Ratio: ");
Serial.print(mq135.readRatio());
// выводим значения газов в ppm
Serial.print("\tCO2: ");
Serial.print(mq135.readCO2());
Serial.println(" ppm");
delay(100);
}

View File

@ -0,0 +1,49 @@
// библиотека для работы с датчиками MQ (Troyka-модуль)
#include <TroykaMQ.h>
// имя для пина, к которому подключен датчик
#define PIN_MQ135 A0
// имя для пина, к которому подключен нагреватель датчика
#define PIN_MQ135_HEATER 11
// создаём объект для работы с датчиком
// и передаём ему номер пина выходного сигнала и нагревателя
MQ135 mq135(PIN_MQ135);
void setup()
{
// открываем последовательный порт
Serial.begin(9600);
// включаем нагреватель
mq135.heaterPwrHigh();
Serial.println("Heated sensor");
}
void loop()
{
// если прошёл интервал нагрева датчика
// и калибровка не была совершена
if (!mq135.isCalibrated() && mq135.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq135.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 160
// mq135.calibrate(160);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq135.getRo());
}
// если прошёл интевал нагрева датчика
// и калибровка была совершена
if (mq135.isCalibrated() && mq135.heatingCompleted()) {
// выводим отношения текущего сопротивление датчика
// к сопротивлению датчика в чистом воздухе (Rs/Ro)
Serial.print("Ratio: ");
Serial.print(mq135.readRatio());
// выводим значения газов в ppm
Serial.print("\tCO2: ");
Serial.print(mq135.readCO2());
Serial.println(" ppm");
delay(100);
}
}

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq2.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 3.2
// mq2.calibrate(3.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq2.getRo());
@ -25,18 +28,18 @@ void loop()
Serial.print("Ratio: ");
Serial.print(mq2.readRatio());
// выводим значения газов в ppm
Serial.print("LPG: ");
Serial.print("\tLPG: ");
Serial.print(mq2.readLPG());
Serial.print(" ppm ");
Serial.print(" Methane: ");
Serial.print(" ppm");
Serial.print("\tMethane: ");
Serial.print(mq2.readMethane());
Serial.print(" ppm ");
Serial.print(" Smoke: ");
Serial.print(" ppm");
Serial.print("\tSmoke: ");
Serial.print(mq2.readSmoke());
Serial.print(" ppm ");
Serial.print(" Hydrogen: ");
Serial.print(" ppm");
Serial.print("\tHydrogen: ");
Serial.print(mq2.readHydrogen());
Serial.println(" ppm ");
Serial.println(" ppm");
delay(100);
}

View File

@ -26,6 +26,9 @@ void loop()
if (!mq2.isCalibrated() && mq2.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq2.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 3.2
// mq2.calibrate(3.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq2.getRo());
@ -38,18 +41,18 @@ void loop()
Serial.print("Ratio: ");
Serial.print(mq2.readRatio());
// выводим значения газов в ppm
Serial.print("LPG: ");
Serial.print("\tLPG: ");
Serial.print(mq2.readLPG());
Serial.print(" ppm ");
Serial.print(" Methane: ");
Serial.print(" ppm");
Serial.print("\tMethane: ");
Serial.print(mq2.readMethane());
Serial.print(" ppm ");
Serial.print(" Smoke: ");
Serial.print(" ppm");
Serial.print("\tSmoke: ");
Serial.print(mq2.readSmoke());
Serial.print(" ppm ");
Serial.print(" Hydrogen: ");
Serial.print(" ppm");
Serial.print("\tHydrogen: ");
Serial.print(mq2.readHydrogen());
Serial.println(" ppm ");
Serial.println(" ppm");
delay(100);
}
}

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq3.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 6.3
// mq3.calibrate(6.3);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq3.getRo());

View File

@ -26,6 +26,9 @@ void loop()
if (!mq3.isCalibrated() && mq3.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq3.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 6.3
// mq3.calibrate(6.3);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq3.getRo());

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq4.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 7.1
// mq4.calibrate(7.1);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq4.getRo());

View File

@ -26,6 +26,9 @@ void loop()
if (!mq4.isCalibrated() && mq4.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq4.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 7.1
// mq4.calibrate(7.1);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq4.getRo());

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq5.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 4.7
// mq5.calibrate(4.7);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq5.getRo());

View File

@ -26,6 +26,9 @@ void loop()
if (!mq5.isCalibrated() && mq5.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq5.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 4.7
// mq5.calibrate(4.7);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq5.getRo());

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq6.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 8.2
// mq6.calibrate(8.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq6.getRo());

View File

@ -26,6 +26,9 @@ void loop()
if (!mq6.isCalibrated() && mq6.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq6.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 8.2
// mq6.calibrate(8.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq6.getRo());

View File

@ -27,6 +27,9 @@ void loop()
if (!mq7.isCalibrated() && mq7.atHeatCycleEnd()) {
// выполняем калибровку датчика на чистом воздухе
mq7.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 7.2
// mq7.calibrate(7.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq7.getRo());

View File

@ -13,6 +13,9 @@ void setup()
// перед калибровкой датчика прогрейте его 60 секунд
// выполняем калибровку датчика на чистом воздухе
mq8.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 6.1
// mq8.calibrate(6.1);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq8.getRo());

View File

@ -26,6 +26,9 @@ void loop()
if (!mq8.isCalibrated() && mq8.heatingCompleted()) {
// выполняем калибровку датчика на чистом воздухе
mq8.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 6.1
// mq8.calibrate(6.1);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq8.getRo());

View File

@ -27,6 +27,9 @@ void loop()
if (!mq9.isCalibrated() && mq9.atHeatCycleEnd()) {
// выполняем калибровку датчика на чистом воздухе
mq9.calibrate();
// при знании сопративления датчика на чистом воздухе
// можно его указать вручную, допустим 7.2
// mq9.calibrate(7.2);
// выводим сопротивление датчика в чистом воздухе (Ro) в serial-порт
Serial.print("Ro = ");
Serial.println(mq9.getRo());

40
keywords.txt Normal file
View File

@ -0,0 +1,40 @@
#######################################
# Syntax Coloring Map TroykaMQ
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MQ2 KEYWORD1 MQ2
MQ3 KEYWORD1 MQ3
MQ4 KEYWORD1 MQ4
MQ5 KEYWORD1 MQ5
MQ6 KEYWORD1 MQ6
MQ7 KEYWORD1 MQ7
MQ8 KEYWORD1 MQ8
MQ9 KEYWORD1 MQ9
MQ135 KEYWORD1 MQ135
#######################################
# Methods and Functions (KEYWORD2)
#######################################
calibrate KEYWORD2
heaterPwrHigh KEYWORD2
heaterPwrLow KEYWORD2
heaterPwrOff KEYWORD2
cycleHeat KEYWORD2
atHeatCycleEnd KEYWORD2
heatingCompleted KEYWORD2
coolanceCompleted KEYWORD2
readRatio KEYWORD2
isCalibrated KEYWORD2
getRo KEYWORD2
readLPG KEYWORD2
readMethane KEYWORD2
readSmoke KEYWORD2
readHydrogen KEYWORD2
readAlcoholMgL KEYWORD2
readAlcoholPpm KEYWORD2
readCarbonMonoxide KEYWORD2
readCO2 KEYWORD2

9
library.properties Normal file
View File

@ -0,0 +1,9 @@
name=TroykaMQ
version=1.1
author=Igor Dementiev, Amperka
maintainer=Amperka <amperka.ru>
sentence=Allows to read data from gas sensors of the MQx series in ppm.
paragraph=This library reads data from the MQx series sensors and displays the readings in ppm. Before reading the indicators, the sensor must be calibrated in clean air.
category=Sensors
url=https://github.com/amperka/TroykaMQ
architectures=*

122
src/BaseMQ.cpp Normal file
View File

@ -0,0 +1,122 @@
/****************************************************************************/
// Function: cpp file for BaseMQ
// Hardware: MQ2, MQ3, MQ4, MQ5, MQ6, MQ7, MQ8, MQ9, MQ135
// Arduino IDE: Arduino 1.8.3
// Author: Igor Dementiev
// Date: Jan 19, 2018
// Version: v1.1
// by www.amperka.ru
/****************************************************************************/
#include "BaseMQ.h"
BaseMQ::BaseMQ(uint8_t pin) {
_pin = pin;
}
BaseMQ::BaseMQ(uint8_t pin, uint8_t pinHeater) {
_pin = pin;
_pinHeater = pinHeater;
pinMode(_pinHeater, OUTPUT);
}
// фиксированая калибровка датчика
// при знании сопративления датчика на чистом воздухе
void BaseMQ::calibrate(float ro) {
_ro = ro;
_stateCalibrate = true;
}
// калибровка датчика
// считывания показаний сопративление датчика на чистом воздухе
// далее фиксированая калибровка датчика
void BaseMQ::calibrate() {
float rs = readRs();
float ro = rs / getRoInCleanAir();
calibrate(ro);
}
// включение нагревателя на 100%
void BaseMQ::heaterPwrHigh() {
digitalWrite(_pinHeater, HIGH);
_heater = true;
_prMillis = millis();
}
// включение нагревателья на 20%
void BaseMQ::heaterPwrLow() {
analogWrite(_pinHeater, 75);
_heater = true;
_cooler = true;
_prMillis = millis();
}
// выключение нагревателя
void BaseMQ::heaterPwrOff() {
digitalWrite(_pinHeater, LOW);
_heater = false;
}
// циклическое считывание сопративления датчика
float BaseMQ::readRs() const {
float rs = 0;
for (int i = 0; i < MQ_SAMPLE_TIMES; i++) {
rs += calculateResistance(analogRead(_pin));
delay(MQ_SAMPLE_INTERVAL);
}
rs = rs / MQ_SAMPLE_TIMES;
return rs;
}
// сопротивление датчика
float BaseMQ::calculateResistance(int sensorADC) const {
float sensorVoltage = sensorADC * (OPERATING_VOLTAGE / ADC_VALUE_MAX);
float sensorResistance = (OPERATING_VOLTAGE - sensorVoltage) / sensorVoltage * getRL();
return sensorResistance;
}
float BaseMQ::readScaled(float a, float b) const {
float ratio = readRatio();
return exp((log(ratio) - b) / a);
}
float BaseMQ::readRatio() const {
return readRs() / getRo();
}
bool BaseMQ::heatingCompleted() const {
if ((_heater) && (!_cooler) && (millis() - _prMillis > MQ_HEATING_TIME)) {
return true;
} else {
return false;
}
}
bool BaseMQ::coolanceCompleted() const {
if ((_heater) && (_cooler) && (millis() - _prMillis > MQ_COOLANCE_TIME)) {
return true;
} else {
return false;
}
}
void BaseMQ::cycleHeat() {
_heater = false;
_cooler = false;
heaterPwrHigh();
// Serial.println("Heated sensor");
}
bool BaseMQ::atHeatCycleEnd() {
if (heatingCompleted()) {
heaterPwrLow();
// Serial.println("Cool sensor");
return false;
} else if (coolanceCompleted()) {
heaterPwrOff();
return true;
} else {
return false;
}
}

72
src/BaseMQ.h Normal file
View File

@ -0,0 +1,72 @@
/****************************************************************************/
// Function: Header file for BaseMQ
// Hardware: MQ2, MQ3, MQ4, MQ5, MQ6, MQ7, MQ8, MQ9, MQ135
// Arduino IDE: Arduino 1.8.3
// Author: Igor Dementiev
// Date: Jan 19, 2018
// Version: v1.1
// by www.amperka.ru
/****************************************************************************/
#ifndef BaseMQ_H
#define BaseMQ_H
#include <Arduino.h>
// кол-во считываний значений в цикле
#define MQ_SAMPLE_TIMES 5
// задержка после каждого считывания датчика
#define MQ_SAMPLE_INTERVAL 20
// время нагрева датчика
#define MQ_HEATING_TIME 6000
// время охлаждение датчика
#define MQ_COOLANCE_TIME 9000
// разрядность АЦП
#define ADC_BIT 10
// масимальное значение АЦП
#define ADC_VALUE_MAX pow(2, ADC_BIT)
#if defined(__AVR__)
#define OPERATING_VOLTAGE 5.0
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) || defined(__SAMD21G18A__)
#define OPERATING_VOLTAGE 3.3
#endif
class BaseMQ {
public:
BaseMQ(uint8_t pin);
BaseMQ(uint8_t pin, uint8_t pinHeater);
void calibrate();
void calibrate(float ro);
void heaterPwrHigh();
void heaterPwrLow();
void heaterPwrOff();
void cycleHeat();
bool atHeatCycleEnd();
bool heatingCompleted() const;
bool coolanceCompleted() const;
float readRatio() const;
inline bool isCalibrated() const {
return _stateCalibrate;
};
inline float getRo() const {
return _ro;
};
protected:
float readScaled(float a, float b) const;
virtual float getRoInCleanAir() const = 0;
virtual int getRL() const = 0;
private:
bool _heater = false;
bool _cooler = false;
bool _stateCalibrate = false;
unsigned long _prMillis = 0;
float _ro = 1.0f;
uint8_t _pin;
uint8_t _pinHeater;
float readRs() const;
float calculateResistance(int sensorADC) const;
};
#endif

13
src/MQ135.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "MQ135.h"
MQ135::MQ135(uint8_t pin)
: BaseMQ(pin) {
}
MQ135::MQ135(uint8_t pin, uint8_t pinHeater)
: BaseMQ(pin, pinHeater) {
}
unsigned long MQ135::readCO2() {
return readScaled(-0.42 , 1.92);
}

26
src/MQ135.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef MQ135_H_
#define MQ135_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ135_RL_BOARD 10
// концентрация углекислого газа в сухом воздухе
#define PPM_CO2_IN_CLEAR_AIR 397.13
class MQ135 : public BaseMQ {
public:
MQ135(uint8_t pin);
MQ135(uint8_t pin, uint8_t pinHeater);
unsigned long readCO2();
private:
virtual int getRL() const {
return MQ135_RL_BOARD;
}
virtual float getRoInCleanAir() const {
return exp((log(PPM_CO2_IN_CLEAR_AIR) * -0.42) + 1.92);
}
};
#endif // MQ135_H_

24
src/MQ2.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef MQ2_H_
#define MQ2_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ2_RL_BOARD 5
// коефициент чистого воздуха из графика
#define MQ2_RO_IN_CLEAR_AIR 9.83
class MQ2 : public BaseMQ {
public:
MQ2(uint8_t pin);
MQ2(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
unsigned long readSmoke();
unsigned long readHydrogen();
private:
virtual int getRL() const { return MQ2_RL_BOARD; }
virtual float getRoInCleanAir() const { return MQ2_RO_IN_CLEAR_AIR; }
};
#endif // MQ2_H_

View File

@ -13,5 +13,5 @@ float MQ3::readAlcoholMgL() {
}
float MQ3::readAlcoholPpm() {
return readScaled(-0.66, -0.62)*2.2;
return readScaled(-0.66, -0.62) * 2.2;
}

22
src/MQ3.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef MQ3_H_
#define MQ3_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ3_RL_BOARD 200
// коефициент чистого воздуха из графика
#define MQ3_RO_IN_CLEAR_AIR 60
class MQ3 : public BaseMQ {
public:
MQ3(uint8_t pin);
MQ3(uint8_t pin, uint8_t pinHeater);
float readAlcoholMgL();
float readAlcoholPpm();
private:
virtual int getRL() const { return MQ3_RL_BOARD; }
virtual float getRoInCleanAir() const { return MQ3_RO_IN_CLEAR_AIR; }
};
#endif // MQ3_H_

21
src/MQ4.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MQ4_H_
#define MQ4_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ4_RL_BOARD 20
// коефициент чистого воздуха из графика
#define MQ4_RO_IN_CLEAR_AIR 4.4
class MQ4 : public BaseMQ {
public:
MQ4(uint8_t pin);
MQ4(uint8_t pin, uint8_t pinHeater);
unsigned long readMethane();
private:
virtual int getRL() const { return MQ4_RL_BOARD ; }
virtual float getRoInCleanAir() const { return MQ4_RO_IN_CLEAR_AIR; }
};
#endif // MQ4_H_

22
src/MQ5.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef MQ5_H_
#define MQ5_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ5_RL_BOARD 20
// коефициент чистого воздуха из графика
#define MQ5_RO_IN_CLEAR_AIR 6.5
class MQ5 : public BaseMQ {
public:
MQ5(uint8_t pin);
MQ5(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
private:
virtual int getRL() const { return MQ5_RL_BOARD; }
virtual float getRoInCleanAir() const { return MQ5_RO_IN_CLEAR_AIR; }
};
#endif // MQ5_H_

21
src/MQ6.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MQ6_H_
#define MQ6_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ6_RL_BOARD 20
// коефициент чистого воздуха из графика
#define MQ6_RO_IN_CLEAR_AIR 10
class MQ6 : public BaseMQ {
public:
MQ6(uint8_t pin);
MQ6(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
private:
virtual int getRL() const { return MQ6_RL_BOARD ; }
virtual float getRoInCleanAir() const { return MQ6_RO_IN_CLEAR_AIR; }
};
#endif // MQ6_H_

21
src/MQ7.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MQ7_H_
#define MQ7_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ7_RL_BOARD 10
// коефициент чистого воздуха из графика
#define MQ7_RO_IN_CLEAR_AIR 27
class MQ7 : public BaseMQ {
public:
MQ7(uint8_t pin);
MQ7(uint8_t pin, uint8_t pinHeater);
unsigned long readCarbonMonoxide();
private:
virtual int getRL() const { return MQ7_RL_BOARD; }
virtual float getRoInCleanAir() const { return MQ7_RO_IN_CLEAR_AIR; }
};
#endif // MQ7_H_

21
src/MQ8.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MQ8_H_
#define MQ8_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ8_RL_BOARD 10
// коефициент чистого воздуха из графика
#define MQ8_RO_IN_CLEAR_AIR 27
class MQ8 : public BaseMQ {
public:
MQ8(uint8_t pin);
MQ8(uint8_t pin, uint8_t pinHeater);
unsigned long readHydrogen();
private:
virtual int getRL() const { return MQ8_RL_BOARD; }
virtual float getRoInCleanAir() const { return MQ8_RO_IN_CLEAR_AIR ; }
};
#endif // MQ8_H_

25
src/MQ9.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef MQ9_H_
#define MQ9_H_
#include "BaseMQ.h"
// резистор установленный на плату (кОм)
#define MQ9_RL_BOARD 10
// коефициент чистого воздуха из графика
#define MQ9_RO_IN_CLEAR_AIR 9.8
class MQ9 : public BaseMQ {
public:
MQ9(uint8_t pin);
MQ9(uint8_t pin, uint8_t pinHeater);
unsigned long readLPG();
unsigned long readMethane();
unsigned long readCarbonMonoxide();
private:
// Резистор установленный на плату (кОм)
virtual int getRL() const { return MQ9_RL_BOARD; }
// коефициент чистого воздуха
virtual float getRoInCleanAir() const { return MQ9_RO_IN_CLEAR_AIR; }
};
#endif // MQ9_H_

23
src/TroykaMQ.h Normal file
View File

@ -0,0 +1,23 @@
/****************************************************************************/
// Function: Header file for TroykaMQ
// Hardware: MQ2, MQ3, MQ4, MQ5, MQ6, MQ7, MQ8, MQ9, MQ135
// Arduino IDE: Arduino 1.8.3
// Author: Igor Dementiev
// Date: Jan 19, 2018
// Version: v1.1
// by www.amperka.ru
/****************************************************************************/
#ifndef TROYKAMQ_H_
#define TROYKAMQ_H_
#include "MQ2.h"
#include "MQ3.h"
#include "MQ4.h"
#include "MQ5.h"
#include "MQ6.h"
#include "MQ7.h"
#include "MQ8.h"
#include "MQ9.h"
#include "MQ135.h"
#endif // TROYKAMQ_H_