add comments
This commit is contained in:
parent
ce1a6273ee
commit
fac08df3d1
6 changed files with 120 additions and 356 deletions
|
@ -1,108 +1,83 @@
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@file MQ135.cpp
|
|
||||||
@author G.Krocker (Mad Frog Labs)
|
|
||||||
@license GNU GPLv3
|
|
||||||
First version of an Arduino Library for the MQ135 gas sensor
|
|
||||||
TODO: Review the correction factor calculation. This currently relies on
|
|
||||||
the datasheet but the information there seems to be wrong.
|
|
||||||
@section HISTORY
|
|
||||||
v1.0 - First release
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "MQ135.h"
|
#include "MQ135.h"
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Default constructor
|
|
||||||
@param[in] pin The analog input pin for the readout of the sensor
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
MQ135::MQ135(uint8_t pin) {
|
MQ135::MQ135(uint8_t pin) {
|
||||||
_pin = pin;
|
this->pin = pin;
|
||||||
|
pinMode(pin, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MQ135::getVoltage() {
|
||||||
/**************************************************************************/
|
return (double)analogRead(pin) * VStep;
|
||||||
/*!
|
|
||||||
@brief Get the correction factor to correct for temperature and humidity
|
|
||||||
@param[in] t The ambient air temperature
|
|
||||||
@param[in] h The relative humidity
|
|
||||||
@return The calculated correction factor
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
float MQ135::getCorrectionFactor(float t, float h) {
|
|
||||||
return CORA * t * t - CORB * t + CORC - (h-33.)*CORD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getResistance() {
|
||||||
/*!
|
double voltage = getVoltage();
|
||||||
@brief Get the resistance of the sensor, ie. the measurement value
|
double rs = ((VIn * RL) / voltage) - RL;
|
||||||
@return The sensor resistance in kOhm
|
if (rs < 0) {
|
||||||
*/
|
rs = 0;
|
||||||
/**************************************************************************/
|
}
|
||||||
float MQ135::getResistance() {
|
return rs;
|
||||||
int val = analogRead(_pin);
|
|
||||||
return ((1023./(float)val) * 5. - 1.)*RLOAD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getPPM(float a, float b) {
|
||||||
/*!
|
double ratio = getResistance() / R0;
|
||||||
@brief Get the resistance of the sensor, ie. the measurement value corrected
|
double ppm = a * pow(ratio, b);
|
||||||
for temp/hum
|
if (ppm < 0) {
|
||||||
@param[in] t The ambient air temperature
|
ppm = 0;
|
||||||
@param[in] h The relative humidity
|
}
|
||||||
@return The corrected sensor resistance kOhm
|
return ppm;
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
float MQ135::getCorrectedResistance(float t, float h) {
|
|
||||||
return getResistance()/getCorrectionFactor(t, h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getPPMLinear(float a, float b) {
|
||||||
/*!
|
double ratio = getResistance() / R0;
|
||||||
@brief Get the ppm of CO2 sensed (assuming only CO2 in the air)
|
double ppm_log = (log10(ratio) - b) / a;
|
||||||
@return The ppm of CO2 in the air
|
double ppm = pow(10, ppm_log);
|
||||||
*/
|
if (ppm < 0) {
|
||||||
/**************************************************************************/
|
ppm = 0;
|
||||||
float MQ135::getPPM() {
|
}
|
||||||
return PARA * pow((getResistance()/RZERO), -PARB);
|
return ppm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getAcetona() {
|
||||||
/*!
|
return getPPM(34.668, -3.369);
|
||||||
@brief Get the ppm of CO2 sensed (assuming only CO2 in the air), corrected
|
|
||||||
for temp/hum
|
|
||||||
@param[in] t The ambient air temperature
|
|
||||||
@param[in] h The relative humidity
|
|
||||||
@return The ppm of CO2 in the air
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
float MQ135::getCorrectedPPM(float t, float h) {
|
|
||||||
return PARA * pow((getCorrectedResistance(t, h)/RZERO), -PARB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getAlcohol() {
|
||||||
/*!
|
return getPPM(77.255, -3.18);
|
||||||
@brief Get the resistance RZero of the sensor for calibration purposes
|
|
||||||
@return The sensor resistance RZero in kOhm
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
float MQ135::getRZero() {
|
|
||||||
return getResistance() * pow((ATMOCO2/PARA), (1./PARB));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
double MQ135::getCO2() {
|
||||||
/*!
|
// return getPPMLinear(-0.3525, 0.7142) + ATMOCO2;
|
||||||
@brief Get the corrected resistance RZero of the sensor for calibration
|
return getPPM(110.47, -2.862) + ATMOCO2;
|
||||||
purposes
|
}
|
||||||
@param[in] t The ambient air temperature
|
|
||||||
@param[in] h The relative humidity
|
double MQ135::getCO() {
|
||||||
@return The corrected sensor resistance RZero in kOhm
|
return getPPM(605.18, -3.937);
|
||||||
*/
|
}
|
||||||
/**************************************************************************/
|
|
||||||
float MQ135::getCorrectedRZero(float t, float h) {
|
double MQ135::getNH4() {
|
||||||
return getCorrectedResistance(t, h) * pow((ATMOCO2/PARA), (1./PARB));
|
return getPPM(102.2, -2.473);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MQ135::getTolueno() {
|
||||||
|
return getPPM(44.947, -3.445);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MQ135::getR0() {
|
||||||
|
double r0 = getResistance() / 3.6;
|
||||||
|
return r0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double MQ135::getR0ByCO2Level(float ppm) {
|
||||||
|
if (ppm > ATMOCO2) {
|
||||||
|
ppm -= ATMOCO2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
double tmp = -(log10(ppm / 110.47) / -2.862) + log10(getResistance());
|
||||||
|
return pow(10, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MQ135::setR0(float r0) {
|
||||||
|
R0 = r0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,56 +1,66 @@
|
||||||
/**************************************************************************/
|
#ifndef MQ135New_H
|
||||||
/*!
|
#define MQ135New_H
|
||||||
@file MQ135.h
|
|
||||||
@author G.Krocker (Mad Frog Labs)
|
|
||||||
@license GNU GPLv3
|
|
||||||
|
|
||||||
First version of an Arduino Library for the MQ135 gas sensor
|
#include "Arduino.h"
|
||||||
TODO: Review the correction factor calculation. This currently relies on
|
|
||||||
the datasheet but the information there seems to be wrong.
|
|
||||||
|
|
||||||
@section HISTORY
|
/// Resistor on Sensor in kΩ
|
||||||
|
#define RL 10
|
||||||
|
|
||||||
v1.0 - First release
|
/// Voltage on Sensor in V
|
||||||
*/
|
#define VIn 5
|
||||||
/**************************************************************************/
|
|
||||||
#ifndef MQ135_H
|
|
||||||
#define MQ135_H
|
|
||||||
#if ARDUINO >= 100
|
|
||||||
#include "Arduino.h"
|
|
||||||
#else
|
|
||||||
#include "WProgram.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// The load resistance on the board
|
/// Board analog Input Resolution
|
||||||
#define RLOAD 10.0
|
/// Default: 2^10
|
||||||
/// Calibration resistance at atmospheric CO2 level
|
#define Resolution 1024
|
||||||
// #define RZERO 76.63
|
|
||||||
#define RZERO 840
|
|
||||||
/// Parameters for calculating ppm of CO2 from sensor resistance
|
|
||||||
#define PARA 116.6020682
|
|
||||||
#define PARB 2.769034857
|
|
||||||
|
|
||||||
/// Parameters to model temperature and humidity dependence
|
/// CO2 Level in Atmosphere
|
||||||
#define CORA 0.00035
|
|
||||||
#define CORB 0.02718
|
|
||||||
#define CORC 1.39538
|
|
||||||
#define CORD 0.0018
|
|
||||||
|
|
||||||
/// Atmospheric CO2 level for calibration purposes
|
|
||||||
#define ATMOCO2 397.13
|
#define ATMOCO2 397.13
|
||||||
|
|
||||||
|
/// Helper to calculate Voltage from Input
|
||||||
|
/// Voltage = input * Vin / (Resolution - 1)
|
||||||
|
const double VStep = (double)VIn / (Resolution - 1);
|
||||||
|
|
||||||
class MQ135 {
|
class MQ135 {
|
||||||
private:
|
private:
|
||||||
uint8_t _pin;
|
/// input pin
|
||||||
|
uint8_t pin;
|
||||||
|
/// calibration Resistance
|
||||||
|
float R0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Constructor with analog input Pin
|
||||||
MQ135(uint8_t pin);
|
MQ135(uint8_t pin);
|
||||||
float getCorrectionFactor(float t, float h);
|
/// Get R0 in default conditions for calibration purposes.
|
||||||
float getResistance();
|
/// Assume CO2 Level is the default Atmospheric Level (~400ppm)
|
||||||
float getCorrectedResistance(float t, float h);
|
float getR0();
|
||||||
float getPPM();
|
/// Get R0 in custom conditions for calibration purposes.
|
||||||
float getCorrectedPPM(float t, float h);
|
/// Can be used, if you know the current CO2 Level.
|
||||||
float getRZero();
|
double getR0ByCO2Level(float ppm);
|
||||||
float getCorrectedRZero(float t, float h);
|
/// Set R0 Value foir calibration.
|
||||||
|
void setR0(float r0);
|
||||||
|
|
||||||
|
/// Gets the resolved sensor voltage
|
||||||
|
double getVoltage();
|
||||||
|
/// Calculates the Resistance of the Sensor
|
||||||
|
double getResistance();
|
||||||
|
/// Calculates ppm on a exponential curve
|
||||||
|
/// (Different Gases have different curves)
|
||||||
|
double getPPM(float a, float b);
|
||||||
|
/// Calculates ppm on a linear curve
|
||||||
|
/// (Different Gases have different curves)
|
||||||
|
double getPPMLinear(float a, float b);
|
||||||
|
|
||||||
|
/// Gets ppm of Acetona in Air (C3H6O)
|
||||||
|
double getAcetona();
|
||||||
|
/// Gets ppm of Alcohol in Air
|
||||||
|
double getAlcohol();
|
||||||
|
/// Gets ppm of CO in Air
|
||||||
|
double getCO();
|
||||||
|
/// Gets ppm of CO2 in Air
|
||||||
|
double getCO2();
|
||||||
|
/// Gets ppm of NH4 in Air
|
||||||
|
double getNH4();
|
||||||
|
/// Gets ppm of Tolueno in Air (CH3)
|
||||||
|
double getTolueno();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include "MQ135New.h"
|
|
||||||
|
|
||||||
MQ135::MQ135(uint8_t pin) {
|
|
||||||
_pin = pin;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getVoltage() {
|
|
||||||
return (double)analogRead(_pin) * VStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getResistance() {
|
|
||||||
double voltage = getVoltage();
|
|
||||||
double rs = ((VIn * RL) / voltage) - RL;
|
|
||||||
if (rs < 0) {
|
|
||||||
rs = 0;
|
|
||||||
}
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getPPM(float a, float b) {
|
|
||||||
double ratio = getResistance() / R0;
|
|
||||||
double ppm = a * pow(ratio, b);
|
|
||||||
if (ppm < 0) {
|
|
||||||
ppm = 0;
|
|
||||||
}
|
|
||||||
return ppm;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getAcetona() {
|
|
||||||
return getPPM(34.668, -3.369);
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getAlcohol() {
|
|
||||||
return getPPM(77.255, -3.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getCO2() {
|
|
||||||
return getPPM(110.47, -2.862) + ATMOCO2;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getCO() {
|
|
||||||
return getPPM(605.18, -3.937);
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getNH4() {
|
|
||||||
return getPPM(102.2, -2.473);
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getTolueno() {
|
|
||||||
return getPPM(44.947, -3.445);
|
|
||||||
}
|
|
||||||
|
|
||||||
float MQ135::getR0() {
|
|
||||||
double r0 = getResistance() / 3.6;
|
|
||||||
return r0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double MQ135::getR0By(float ppm, float a, float b) {
|
|
||||||
double tmp = (log10(ppm / a) / b) - log10(RL);
|
|
||||||
return pow(10, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MQ135::setR0(float r0) {
|
|
||||||
R0 = r0;
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef MQ135New_H
|
|
||||||
#define MQ135New_H
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
|
|
||||||
#define RL 10
|
|
||||||
#define VIn 5
|
|
||||||
#define Resolution 1024
|
|
||||||
|
|
||||||
#define ATMOCO2 397.13
|
|
||||||
|
|
||||||
const double VStep = (double)VIn / (Resolution - 1);
|
|
||||||
|
|
||||||
class MQ135 {
|
|
||||||
private:
|
|
||||||
uint8_t _pin;
|
|
||||||
float R0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MQ135(uint8_t pin);
|
|
||||||
float getR0();
|
|
||||||
double getR0By(float ppm, float a, float b);
|
|
||||||
void setR0(float r0);
|
|
||||||
|
|
||||||
double getVoltage();
|
|
||||||
double getResistance();
|
|
||||||
double getPPM(float a, float b);
|
|
||||||
|
|
||||||
double getAcetona();
|
|
||||||
double getAlcohol();
|
|
||||||
double getCO();
|
|
||||||
double getCO2();
|
|
||||||
double getNH4();
|
|
||||||
double getTolueno();
|
|
||||||
};
|
|
||||||
#endif
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -1,5 +1,5 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "MQ135New.h"
|
#include "MQ135.h"
|
||||||
|
|
||||||
#define PIN_MQ135 A0
|
#define PIN_MQ135 A0
|
||||||
#define PIN_LED_GREEN DD2
|
#define PIN_LED_GREEN DD2
|
||||||
|
@ -15,7 +15,7 @@ MQ135 co2_sensor(PIN_MQ135);
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
pinMode(PIN_MQ135, INPUT);
|
pinMode(PIN_MQ135, INPUT);
|
||||||
co2_sensor.setR0(66.0);
|
co2_sensor.setR0(1000.);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printValues(float ppm, float temp, float humidity);
|
void printValues(float ppm, float temp, float humidity);
|
||||||
|
@ -24,14 +24,6 @@ void loop() {
|
||||||
float value = co2_sensor.getCO2();
|
float value = co2_sensor.getCO2();
|
||||||
Serial.print("co2: ");
|
Serial.print("co2: ");
|
||||||
Serial.println(value);
|
Serial.println(value);
|
||||||
Serial.print("resistance: ");
|
|
||||||
Serial.println(co2_sensor.getResistance());
|
|
||||||
Serial.print("voltage: ");
|
|
||||||
Serial.println(co2_sensor.getVoltage());
|
|
||||||
Serial.print("r01: ");
|
|
||||||
Serial.println(co2_sensor.getR0());
|
|
||||||
Serial.print("r02: ");
|
|
||||||
Serial.println(co2_sensor.getR0By(1, 110.47, -2.862));
|
|
||||||
delay(2000);
|
delay(2000);
|
||||||
// if (count >= maxCount || count < 0) {
|
// if (count >= maxCount || count < 0) {
|
||||||
// float temp = bme.readTemperature();
|
// float temp = bme.readTemperature();
|
||||||
|
|
112
test/main.cpp
112
test/main.cpp
|
@ -1,112 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include <MQ135.h>
|
|
||||||
#include <dht.h>
|
|
||||||
|
|
||||||
#define PIN_MQ135 A0
|
|
||||||
#define PIN_DHT11 A1
|
|
||||||
|
|
||||||
#define PIN_LED_GREEN DD2
|
|
||||||
#define PIN_LED_YELLOW DD3
|
|
||||||
#define PIN_LED_RED DD4
|
|
||||||
#define PIN_NOISE DD5
|
|
||||||
|
|
||||||
#define MEASURE_DELAY 1000
|
|
||||||
#define NOISE_DELAY 100
|
|
||||||
|
|
||||||
MQ135 co2_sensor = MQ135(PIN_MQ135);
|
|
||||||
dht dht_sensor;
|
|
||||||
const int maxCount = MEASURE_DELAY / NOISE_DELAY;
|
|
||||||
int count = 0;
|
|
||||||
float ppm = -1;
|
|
||||||
bool noise = false;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(9600);
|
|
||||||
pinMode(PIN_MQ135, INPUT);
|
|
||||||
pinMode(PIN_DHT11, INPUT);
|
|
||||||
pinMode(PIN_LED_GREEN, OUTPUT);
|
|
||||||
pinMode(PIN_LED_YELLOW, OUTPUT);
|
|
||||||
pinMode(PIN_LED_RED, OUTPUT);
|
|
||||||
pinMode(PIN_NOISE, OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
float measure() {
|
|
||||||
Serial.print(RZERO);
|
|
||||||
Serial.println("---------------------------");
|
|
||||||
Serial.print("DHT:\t");
|
|
||||||
int chk = dht_sensor.read11(PIN_DHT11);
|
|
||||||
switch (chk)
|
|
||||||
{
|
|
||||||
case DHTLIB_OK:
|
|
||||||
Serial.print("OK,\t");
|
|
||||||
break;
|
|
||||||
case DHTLIB_ERROR_CHECKSUM:
|
|
||||||
Serial.print("Checksum error,\t");
|
|
||||||
break;
|
|
||||||
case DHTLIB_ERROR_TIMEOUT:
|
|
||||||
Serial.print("Time out error,\t");
|
|
||||||
break;
|
|
||||||
case DHTLIB_ERROR_CONNECT:
|
|
||||||
Serial.print("Connect error,\t");
|
|
||||||
break;
|
|
||||||
case DHTLIB_ERROR_ACK_L:
|
|
||||||
Serial.print("Ack Low error,\t");
|
|
||||||
break;
|
|
||||||
case DHTLIB_ERROR_ACK_H:
|
|
||||||
Serial.print("Ack High error,\t");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Serial.print("Unknown error,\t");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
Serial.print ("temperature: ");
|
|
||||||
Serial.println (dht_sensor.temperature);
|
|
||||||
Serial.print ("humidity: ");
|
|
||||||
Serial.println (dht_sensor.humidity);
|
|
||||||
|
|
||||||
float val = analogRead(A0);
|
|
||||||
Serial.print ("raw = ");
|
|
||||||
Serial.println (val);
|
|
||||||
float zero = co2_sensor.getCorrectedRZero(dht_sensor.temperature, dht_sensor.humidity);
|
|
||||||
Serial.print ("rzero: ");
|
|
||||||
Serial.println (zero);
|
|
||||||
float ppm = co2_sensor.getCorrectedPPM(dht_sensor.temperature, dht_sensor.humidity);
|
|
||||||
Serial.print ("ppm: ");
|
|
||||||
Serial.println (ppm);
|
|
||||||
return ppm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
if (count >= maxCount || ppm < 0) {
|
|
||||||
ppm = measure();
|
|
||||||
count = 0;
|
|
||||||
if (ppm < 1000) {
|
|
||||||
digitalWrite(PIN_LED_GREEN, 1);
|
|
||||||
digitalWrite(PIN_LED_YELLOW, 0);
|
|
||||||
digitalWrite(PIN_LED_RED, 0);
|
|
||||||
}
|
|
||||||
else if (ppm <= 2000) {
|
|
||||||
digitalWrite(PIN_LED_GREEN, 0);
|
|
||||||
digitalWrite(PIN_LED_YELLOW, 1);
|
|
||||||
digitalWrite(PIN_LED_RED, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
digitalWrite(PIN_LED_GREEN, 0);
|
|
||||||
digitalWrite(PIN_LED_YELLOW, 0);
|
|
||||||
digitalWrite(PIN_LED_RED, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ppm > 2000) {
|
|
||||||
noise = !noise;
|
|
||||||
digitalWrite(PIN_NOISE, noise);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
digitalWrite(PIN_NOISE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
delay(NOISE_DELAY);
|
|
||||||
count++;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue