From fac08df3d143ec391a9a745dd4b4b8d08c462004 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Mon, 5 Apr 2021 16:06:32 +0200 Subject: [PATCH] add comments --- lib/MQ135/MQ135.cpp | 157 ++++++++++++++++---------------------- lib/MQ135/MQ135.h | 94 +++++++++++++---------- lib/MQ135New/MQ135New.cpp | 65 ---------------- lib/MQ135New/MQ135New.h | 36 --------- src/main.cpp | 12 +-- test/main.cpp | 112 --------------------------- 6 files changed, 120 insertions(+), 356 deletions(-) delete mode 100644 lib/MQ135New/MQ135New.cpp delete mode 100644 lib/MQ135New/MQ135New.h delete mode 100644 test/main.cpp diff --git a/lib/MQ135/MQ135.cpp b/lib/MQ135/MQ135.cpp index 1da60a4..ef235f7 100644 --- a/lib/MQ135/MQ135.cpp +++ b/lib/MQ135/MQ135.cpp @@ -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" -/**************************************************************************/ -/*! -@brief Default constructor -@param[in] pin The analog input pin for the readout of the sensor -*/ -/**************************************************************************/ - MQ135::MQ135(uint8_t pin) { - _pin = pin; + this->pin = pin; + pinMode(pin, INPUT); } - -/**************************************************************************/ -/*! -@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::getVoltage() { + return (double)analogRead(pin) * VStep; } -/**************************************************************************/ -/*! -@brief Get the resistance of the sensor, ie. the measurement value -@return The sensor resistance in kOhm -*/ -/**************************************************************************/ -float MQ135::getResistance() { - int val = analogRead(_pin); - return ((1023./(float)val) * 5. - 1.)*RLOAD; +double MQ135::getResistance() { + double voltage = getVoltage(); + double rs = ((VIn * RL) / voltage) - RL; + if (rs < 0) { + rs = 0; + } + return rs; } -/**************************************************************************/ -/*! -@brief Get the resistance of the sensor, ie. the measurement value corrected - for temp/hum -@param[in] t The ambient air temperature -@param[in] h The relative humidity -@return The corrected sensor resistance kOhm -*/ -/**************************************************************************/ -float MQ135::getCorrectedResistance(float t, float h) { - return getResistance()/getCorrectionFactor(t, h); +double MQ135::getPPM(float a, float b) { + double ratio = getResistance() / R0; + double ppm = a * pow(ratio, b); + if (ppm < 0) { + ppm = 0; + } + return ppm; } -/**************************************************************************/ -/*! -@brief Get the ppm of CO2 sensed (assuming only CO2 in the air) -@return The ppm of CO2 in the air -*/ -/**************************************************************************/ -float MQ135::getPPM() { - return PARA * pow((getResistance()/RZERO), -PARB); +double MQ135::getPPMLinear(float a, float b) { + double ratio = getResistance() / R0; + double ppm_log = (log10(ratio) - b) / a; + double ppm = pow(10, ppm_log); + if (ppm < 0) { + ppm = 0; + } + return ppm; } -/**************************************************************************/ -/*! -@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::getAcetona() { + return getPPM(34.668, -3.369); } -/**************************************************************************/ -/*! -@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::getAlcohol() { + return getPPM(77.255, -3.18); } -/**************************************************************************/ -/*! -@brief Get the corrected resistance RZero of the sensor for calibration - purposes -@param[in] t The ambient air temperature -@param[in] h The relative humidity -@return The corrected sensor resistance RZero in kOhm -*/ -/**************************************************************************/ -float MQ135::getCorrectedRZero(float t, float h) { - return getCorrectedResistance(t, h) * pow((ATMOCO2/PARA), (1./PARB)); -} \ No newline at end of file +double MQ135::getCO2() { + // return getPPMLinear(-0.3525, 0.7142) + ATMOCO2; + 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::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; +} diff --git a/lib/MQ135/MQ135.h b/lib/MQ135/MQ135.h index a64e707..c9d980c 100644 --- a/lib/MQ135/MQ135.h +++ b/lib/MQ135/MQ135.h @@ -1,56 +1,66 @@ -/**************************************************************************/ -/*! -@file MQ135.h -@author G.Krocker (Mad Frog Labs) -@license GNU GPLv3 +#ifndef MQ135New_H +#define MQ135New_H -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. +#include "Arduino.h" -@section HISTORY +/// Resistor on Sensor in kΩ +#define RL 10 -v1.0 - First release -*/ -/**************************************************************************/ -#ifndef MQ135_H -#define MQ135_H -#if ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif +/// Voltage on Sensor in V +#define VIn 5 -/// The load resistance on the board -#define RLOAD 10.0 -/// Calibration resistance at atmospheric CO2 level -// #define RZERO 76.63 -#define RZERO 840 -/// Parameters for calculating ppm of CO2 from sensor resistance -#define PARA 116.6020682 -#define PARB 2.769034857 +/// Board analog Input Resolution +/// Default: 2^10 +#define Resolution 1024 -/// Parameters to model temperature and humidity dependence -#define CORA 0.00035 -#define CORB 0.02718 -#define CORC 1.39538 -#define CORD 0.0018 - -/// Atmospheric CO2 level for calibration purposes +/// CO2 Level in Atmosphere #define ATMOCO2 397.13 +/// Helper to calculate Voltage from Input +/// Voltage = input * Vin / (Resolution - 1) +const double VStep = (double)VIn / (Resolution - 1); + class MQ135 { private: - uint8_t _pin; + /// input pin + uint8_t pin; + /// calibration Resistance + float R0; public: + /// Constructor with analog input Pin MQ135(uint8_t pin); - float getCorrectionFactor(float t, float h); - float getResistance(); - float getCorrectedResistance(float t, float h); - float getPPM(); - float getCorrectedPPM(float t, float h); - float getRZero(); - float getCorrectedRZero(float t, float h); + /// Get R0 in default conditions for calibration purposes. + /// Assume CO2 Level is the default Atmospheric Level (~400ppm) + float getR0(); + /// Get R0 in custom conditions for calibration purposes. + /// Can be used, if you know the current CO2 Level. + double getR0ByCO2Level(float ppm); + /// 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 diff --git a/lib/MQ135New/MQ135New.cpp b/lib/MQ135New/MQ135New.cpp deleted file mode 100644 index b81301d..0000000 --- a/lib/MQ135New/MQ135New.cpp +++ /dev/null @@ -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; -} diff --git a/lib/MQ135New/MQ135New.h b/lib/MQ135New/MQ135New.h deleted file mode 100644 index 46da745..0000000 --- a/lib/MQ135New/MQ135New.h +++ /dev/null @@ -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 diff --git a/src/main.cpp b/src/main.cpp index b3067b1..9d02e87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ #include -#include "MQ135New.h" +#include "MQ135.h" #define PIN_MQ135 A0 #define PIN_LED_GREEN DD2 @@ -15,7 +15,7 @@ MQ135 co2_sensor(PIN_MQ135); void setup() { Serial.begin(9600); pinMode(PIN_MQ135, INPUT); - co2_sensor.setR0(66.0); + co2_sensor.setR0(1000.); } void printValues(float ppm, float temp, float humidity); @@ -24,14 +24,6 @@ void loop() { float value = co2_sensor.getCO2(); Serial.print("co2: "); 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); // if (count >= maxCount || count < 0) { // float temp = bme.readTemperature(); diff --git a/test/main.cpp b/test/main.cpp deleted file mode 100644 index 158386b..0000000 --- a/test/main.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include - -#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++; -} \ No newline at end of file