From a794de5eb8275690f8d90620cd19ab13829eced6 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Tue, 30 Mar 2021 17:57:27 +0200 Subject: [PATCH 1/8] add bme280 --- lib/MQ135/MQ135.cpp | 17 +------ lib/MQ135/MQ135.h | 2 +- platformio.ini | 6 +-- src/main.cpp | 98 +++++++++++++++++--------------------- test/main.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 76 deletions(-) create mode 100644 test/main.cpp diff --git a/lib/MQ135/MQ135.cpp b/lib/MQ135/MQ135.cpp index 676ed31..1da60a4 100644 --- a/lib/MQ135/MQ135.cpp +++ b/lib/MQ135/MQ135.cpp @@ -3,13 +3,10 @@ @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 */ /**************************************************************************/ @@ -19,7 +16,6 @@ v1.0 - First release /**************************************************************************/ /*! @brief Default constructor - @param[in] pin The analog input pin for the readout of the sensor */ /**************************************************************************/ @@ -32,10 +28,8 @@ MQ135::MQ135(uint8_t pin) { /**************************************************************************/ /*! @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 */ /**************************************************************************/ @@ -46,7 +40,6 @@ float MQ135::getCorrectionFactor(float t, float h) { /**************************************************************************/ /*! @brief Get the resistance of the sensor, ie. the measurement value - @return The sensor resistance in kOhm */ /**************************************************************************/ @@ -59,10 +52,8 @@ float MQ135::getResistance() { /*! @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 */ /**************************************************************************/ @@ -73,7 +64,6 @@ float MQ135::getCorrectedResistance(float t, float h) { /**************************************************************************/ /*! @brief Get the ppm of CO2 sensed (assuming only CO2 in the air) - @return The ppm of CO2 in the air */ /**************************************************************************/ @@ -85,10 +75,8 @@ float MQ135::getPPM() { /*! @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 */ /**************************************************************************/ @@ -99,7 +87,6 @@ float MQ135::getCorrectedPPM(float t, float h) { /**************************************************************************/ /*! @brief Get the resistance RZero of the sensor for calibration purposes - @return The sensor resistance RZero in kOhm */ /**************************************************************************/ @@ -111,13 +98,11 @@ float MQ135::getRZero() { /*! @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 diff --git a/lib/MQ135/MQ135.h b/lib/MQ135/MQ135.h index 1ac6080..9d09441 100644 --- a/lib/MQ135/MQ135.h +++ b/lib/MQ135/MQ135.h @@ -25,7 +25,7 @@ v1.0 - First release #define RLOAD 10.0 /// Calibration resistance at atmospheric CO2 level // #define RZERO 76.63 -#define RZERO 480 +#define RZERO 4000 /// Parameters for calculating ppm of CO2 from sensor resistance #define PARA 116.6020682 #define PARB 2.769034857 diff --git a/platformio.ini b/platformio.ini index ea23b77..f0ece6c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,7 +8,7 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:uno] +[env:mega] platform = atmelavr -board = uno -framework = arduino +board = megaatmega2560 +framework = arduino \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 158386b..5716e7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,9 @@ #include #include -#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 @@ -13,74 +12,38 @@ #define MEASURE_DELAY 1000 #define NOISE_DELAY 100 +#define SEALEVELPRESSURE_HPA (1013.25) + MQ135 co2_sensor = MQ135(PIN_MQ135); -dht dht_sensor; +Adafruit_BME280 bme(10, 11, 12, 13); const int maxCount = MEASURE_DELAY / NOISE_DELAY; -int count = 0; -float ppm = -1; +int count = -1; +float ppm = 0; 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.begin(9600); + + if (!bme.begin()) { + Serial.println(F("Could not find a valid BME280 sensor, check wiring!")); } - 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 printValues(); + void loop() { - if (count >= maxCount || ppm < 0) { - ppm = measure(); + if (count >= maxCount || count < 0) { + ppm = co2_sensor.getPPM(); + Serial.print ("ppm: "); + Serial.println (ppm); + Serial.print ("rzero: "); + Serial.println (co2_sensor.getRZero()); count = 0; if (ppm < 1000) { digitalWrite(PIN_LED_GREEN, 1); @@ -97,6 +60,8 @@ void loop() { digitalWrite(PIN_LED_YELLOW, 0); digitalWrite(PIN_LED_RED, 1); } + + // printValues(); } if (ppm > 2000) { @@ -109,4 +74,25 @@ void loop() { delay(NOISE_DELAY); count++; +} + +void printValues() { + Serial.print("Temperature = "); + Serial.print(bme.readTemperature()); + Serial.println(" *C"); + + Serial.print("Pressure = "); + + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + Serial.print("Approx. Altitude = "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.print("Humidity = "); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.println(); } \ No newline at end of file diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..158386b --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,112 @@ +#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 From 5f9ccca0cf8582d49f632b089dda884937725ab5 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Tue, 30 Mar 2021 19:40:44 +0200 Subject: [PATCH 2/8] use corrected values --- lib/MQ135/MQ135.h | 2 +- platformio.ini | 4 +++- src/main.cpp | 34 +++++++++++++++------------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/lib/MQ135/MQ135.h b/lib/MQ135/MQ135.h index 9d09441..a64e707 100644 --- a/lib/MQ135/MQ135.h +++ b/lib/MQ135/MQ135.h @@ -25,7 +25,7 @@ v1.0 - First release #define RLOAD 10.0 /// Calibration resistance at atmospheric CO2 level // #define RZERO 76.63 -#define RZERO 4000 +#define RZERO 840 /// Parameters for calculating ppm of CO2 from sensor resistance #define PARA 116.6020682 #define PARB 2.769034857 diff --git a/platformio.ini b/platformio.ini index f0ece6c..fa8e979 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,4 +11,6 @@ [env:mega] platform = atmelavr board = megaatmega2560 -framework = arduino \ No newline at end of file +framework = arduino +lib_deps = + adafruit/Adafruit BME280 Library @ ^2.1.2 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5716e7a..8564855 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,15 +35,14 @@ void setup() { } } -void printValues(); +void printValues(float ppm, float temp, float humidity); void loop() { if (count >= maxCount || count < 0) { - ppm = co2_sensor.getPPM(); - Serial.print ("ppm: "); - Serial.println (ppm); - Serial.print ("rzero: "); - Serial.println (co2_sensor.getRZero()); + float temp = bme.readTemperature(); + float humidity = bme.readHumidity(); + ppm = co2_sensor.getCorrectedPPM(temp, humidity); + count = 0; if (ppm < 1000) { digitalWrite(PIN_LED_GREEN, 1); @@ -61,7 +60,7 @@ void loop() { digitalWrite(PIN_LED_RED, 1); } - // printValues(); + printValues(ppm, temp, humidity); } if (ppm > 2000) { @@ -76,23 +75,20 @@ void loop() { count++; } -void printValues() { +void printValues(float ppm, float temp, float humidity) { Serial.print("Temperature = "); - Serial.print(bme.readTemperature()); + Serial.print(temp); Serial.println(" *C"); - Serial.print("Pressure = "); - - Serial.print(bme.readPressure() / 100.0F); - Serial.println(" hPa"); - - Serial.print("Approx. Altitude = "); - Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); - Serial.println(" m"); - Serial.print("Humidity = "); - Serial.print(bme.readHumidity()); + Serial.print(humidity); Serial.println(" %"); + Serial.print ("ppm = "); + Serial.println (ppm); + + Serial.print ("rzero = "); + Serial.println (co2_sensor.getCorrectedRZero(temp, humidity)); + Serial.println(); } \ No newline at end of file From b0ac32d42343f38ecd9ccaa359db6697d5d95801 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Sat, 3 Apr 2021 16:06:39 +0200 Subject: [PATCH 3/8] custom mq135 api --- lib/MQ135New/MQ135New.cpp | 59 ++++++++++++++++++++ lib/MQ135New/MQ135New.h | 31 +++++++++++ platformio.ini | 5 +- src/main.cpp | 112 ++++++++++++++------------------------ 4 files changed, 135 insertions(+), 72 deletions(-) create mode 100644 lib/MQ135New/MQ135New.cpp create mode 100644 lib/MQ135New/MQ135New.h diff --git a/lib/MQ135New/MQ135New.cpp b/lib/MQ135New/MQ135New.cpp new file mode 100644 index 0000000..ef91a11 --- /dev/null +++ b/lib/MQ135New/MQ135New.cpp @@ -0,0 +1,59 @@ +#include "MQ135New.h" + +MQ135::MQ135(uint8_t pin) { + _pin = pin; +} + +double MQ135::getRS() { + double voltage = getVoltage(); + double RS = (double)((double)(VIn * RL) / voltage) - RL; + return RS; +} + +double MQ135::getVoltage() { + int value = analogRead(_pin); + double voltage = (double)(value * VIn) / (double)(Resolution); + return voltage; +} + +double MQ135::getPPM(float a, float b) { + double ratio = getRS() / R0; + // double ppm_log = (log10(ratio) - b) / a; + // double ppm = pow(10, ppm_log); + double ppm = a * pow(ratio, b); + 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(-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 = getRS() / 3.6; + return r0; +} + +void MQ135::setR0(float r0) { + R0 = r0; +} diff --git a/lib/MQ135New/MQ135New.h b/lib/MQ135New/MQ135New.h new file mode 100644 index 0000000..4e1f247 --- /dev/null +++ b/lib/MQ135New/MQ135New.h @@ -0,0 +1,31 @@ +#ifndef MQ135New_H +#define MQ135New_H + +#include "Arduino.h" + +#define RL 10 +#define VIn 5 +#define Resolution 1024 + +#define ATMOCO2 397.13 + +class MQ135 { + private: + uint8_t _pin; + float R0; + double getPPM(float a, float b); + + public: + MQ135(uint8_t pin); + double getAcetona(); + double getAlcohol(); + double getCO(); + double getCO2(); + double getNH4(); + double getTolueno(); + float getR0(); + void setR0(float r0); + double getRS(); + double getVoltage(); +}; +#endif diff --git a/platformio.ini b/platformio.ini index fa8e979..ae5769a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,5 +12,6 @@ platform = atmelavr board = megaatmega2560 framework = arduino -lib_deps = - adafruit/Adafruit BME280 Library @ ^2.1.2 \ No newline at end of file +; lib_deps = +; adafruit/Adafruit BME280 Library @ ^2.1.2 +; miguel5612/MQUnifiedsensor @ ^2.0.1 diff --git a/src/main.cpp b/src/main.cpp index 8564855..1b622b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,5 @@ #include -#include -#include -#include +#include #define PIN_MQ135 A0 #define PIN_LED_GREEN DD2 @@ -12,83 +10,57 @@ #define MEASURE_DELAY 1000 #define NOISE_DELAY 100 -#define SEALEVELPRESSURE_HPA (1013.25) - -MQ135 co2_sensor = MQ135(PIN_MQ135); -Adafruit_BME280 bme(10, 11, 12, 13); -const int maxCount = MEASURE_DELAY / NOISE_DELAY; -int count = -1; -float ppm = 0; -bool noise = false; +MQ135 co2_sensor(PIN_MQ135); void setup() { - pinMode(PIN_MQ135, INPUT); - pinMode(PIN_LED_GREEN, OUTPUT); - pinMode(PIN_LED_YELLOW, OUTPUT); - pinMode(PIN_LED_RED, OUTPUT); - pinMode(PIN_NOISE, OUTPUT); - Serial.begin(9600); - - if (!bme.begin()) { - Serial.println(F("Could not find a valid BME280 sensor, check wiring!")); - } + pinMode(PIN_MQ135, INPUT); + co2_sensor.setR0(66.0); } void printValues(float ppm, float temp, float humidity); void loop() { - if (count >= maxCount || count < 0) { - float temp = bme.readTemperature(); - float humidity = bme.readHumidity(); - ppm = co2_sensor.getCorrectedPPM(temp, humidity); + float value = co2_sensor.getCO2(); + Serial.println(value); + Serial.print("rs: "); + Serial.println(co2_sensor.getRS()); + Serial.print("voltage: "); + Serial.println(co2_sensor.getVoltage()); + delay(500); + // if (count >= maxCount || count < 0) { + // float temp = bme.readTemperature(); + // float humidity = bme.readHumidity(); + // ppm = co2_sensor.getCorrectedPPM(temp, humidity); - 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); - } + // 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); + // } - printValues(ppm, temp, humidity); - } + // printValues(ppm, temp, humidity); + // } - if (ppm > 2000) { - noise = !noise; - digitalWrite(PIN_NOISE, noise); - } - else { - digitalWrite(PIN_NOISE, 0); - } + // if (ppm > 2000) { + // noise = !noise; + // digitalWrite(PIN_NOISE, noise); + // } + // else { + // digitalWrite(PIN_NOISE, 0); + // } - delay(NOISE_DELAY); - count++; -} - -void printValues(float ppm, float temp, float humidity) { - Serial.print("Temperature = "); - Serial.print(temp); - Serial.println(" *C"); - - Serial.print("Humidity = "); - Serial.print(humidity); - Serial.println(" %"); - - Serial.print ("ppm = "); - Serial.println (ppm); - - Serial.print ("rzero = "); - Serial.println (co2_sensor.getCorrectedRZero(temp, humidity)); - - Serial.println(); + // delay(NOISE_DELAY); + // count++; } \ No newline at end of file From 360211d2c20d9fbda6703827cfc41754d0d478c7 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Sat, 3 Apr 2021 19:21:52 +0200 Subject: [PATCH 4/8] remove comments --- lib/MQ135New/MQ135New.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/MQ135New/MQ135New.cpp b/lib/MQ135New/MQ135New.cpp index ef91a11..9e6adf0 100644 --- a/lib/MQ135New/MQ135New.cpp +++ b/lib/MQ135New/MQ135New.cpp @@ -12,14 +12,12 @@ double MQ135::getRS() { double MQ135::getVoltage() { int value = analogRead(_pin); - double voltage = (double)(value * VIn) / (double)(Resolution); + double voltage = (double)(value * VIn) / (double)(Resolution - 1); return voltage; } double MQ135::getPPM(float a, float b) { double ratio = getRS() / R0; - // double ppm_log = (log10(ratio) - b) / a; - // double ppm = pow(10, ppm_log); double ppm = a * pow(ratio, b); return ppm; } @@ -33,7 +31,6 @@ double MQ135::getAlcohol() { } double MQ135::getCO2() { - // return getPPM(-0.3525, 0.7142) + ATMOCO2; return getPPM(110.47, -2.862) + ATMOCO2; } From ce1a6273eed3f28b77bae26c0c1666dad6c8cb4d Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Sat, 3 Apr 2021 23:40:27 +0200 Subject: [PATCH 5/8] optimizations --- lib/MQ135New/MQ135New.cpp | 29 +++++++++++++++++++---------- lib/MQ135New/MQ135New.h | 15 ++++++++++----- src/main.cpp | 13 +++++++++---- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/MQ135New/MQ135New.cpp b/lib/MQ135New/MQ135New.cpp index 9e6adf0..b81301d 100644 --- a/lib/MQ135New/MQ135New.cpp +++ b/lib/MQ135New/MQ135New.cpp @@ -4,21 +4,25 @@ MQ135::MQ135(uint8_t pin) { _pin = pin; } -double MQ135::getRS() { - double voltage = getVoltage(); - double RS = (double)((double)(VIn * RL) / voltage) - RL; - return RS; +double MQ135::getVoltage() { + return (double)analogRead(_pin) * VStep; } -double MQ135::getVoltage() { - int value = analogRead(_pin); - double voltage = (double)(value * VIn) / (double)(Resolution - 1); - return voltage; +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 = getRS() / R0; + double ratio = getResistance() / R0; double ppm = a * pow(ratio, b); + if (ppm < 0) { + ppm = 0; + } return ppm; } @@ -47,10 +51,15 @@ double MQ135::getTolueno() { } float MQ135::getR0() { - double r0 = getRS() / 3.6; + 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 index 4e1f247..46da745 100644 --- a/lib/MQ135New/MQ135New.h +++ b/lib/MQ135New/MQ135New.h @@ -9,23 +9,28 @@ #define ATMOCO2 397.13 +const double VStep = (double)VIn / (Resolution - 1); + class MQ135 { private: uint8_t _pin; float R0; - double getPPM(float a, float b); 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(); - float getR0(); - void setR0(float r0); - double getRS(); - double getVoltage(); }; #endif diff --git a/src/main.cpp b/src/main.cpp index 1b622b4..b3067b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include "MQ135New.h" #define PIN_MQ135 A0 #define PIN_LED_GREEN DD2 @@ -22,12 +22,17 @@ void printValues(float ppm, float temp, float humidity); void loop() { float value = co2_sensor.getCO2(); + Serial.print("co2: "); Serial.println(value); - Serial.print("rs: "); - Serial.println(co2_sensor.getRS()); + Serial.print("resistance: "); + Serial.println(co2_sensor.getResistance()); Serial.print("voltage: "); Serial.println(co2_sensor.getVoltage()); - delay(500); + 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(); // float humidity = bme.readHumidity(); From fac08df3d143ec391a9a745dd4b4b8d08c462004 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Mon, 5 Apr 2021 16:06:32 +0200 Subject: [PATCH 6/8] 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 From 703f5e6d1aa0f2d3cc8355c4cd9254da21cff1c0 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Mon, 5 Apr 2021 17:25:15 +0200 Subject: [PATCH 7/8] typo --- lib/MQ135/MQ135.h | 2 +- src/main.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/MQ135/MQ135.h b/lib/MQ135/MQ135.h index c9d980c..4f3d0fe 100644 --- a/lib/MQ135/MQ135.h +++ b/lib/MQ135/MQ135.h @@ -36,7 +36,7 @@ class MQ135 { /// 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. + /// Set R0 Value for calibration. void setR0(float r0); /// Gets the resolved sensor voltage diff --git a/src/main.cpp b/src/main.cpp index 9d02e87..ace9e9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ #include -#include "MQ135.h" +#include #define PIN_MQ135 A0 #define PIN_LED_GREEN DD2 @@ -14,8 +14,7 @@ MQ135 co2_sensor(PIN_MQ135); void setup() { Serial.begin(9600); - pinMode(PIN_MQ135, INPUT); - co2_sensor.setR0(1000.); + // co2_sensor.setR0(1000.); } void printValues(float ppm, float temp, float humidity); From 69895ad82481e3c88697cbc32bc3737579966717 Mon Sep 17 00:00:00 2001 From: GrafZeppelin Date: Thu, 8 Apr 2021 17:59:50 +0200 Subject: [PATCH 8/8] complete program --- src/main.cpp | 76 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ace9e9e..133cbca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,53 +10,55 @@ #define MEASURE_DELAY 1000 #define NOISE_DELAY 100 +const int maxCount = 10; +int count = 0; +bool noise = false; +bool noiseActive = false; + +float ppm; + MQ135 co2_sensor(PIN_MQ135); void setup() { Serial.begin(9600); - // co2_sensor.setR0(1000.); + co2_sensor.setR0(100); } void printValues(float ppm, float temp, float humidity); void loop() { - float value = co2_sensor.getCO2(); - Serial.print("co2: "); - Serial.println(value); - delay(2000); - // if (count >= maxCount || count < 0) { - // float temp = bme.readTemperature(); - // float humidity = bme.readHumidity(); - // ppm = co2_sensor.getCorrectedPPM(temp, humidity); + if (count >= maxCount || count < 0) { + ppm = co2_sensor.getCO2(); - // 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); - // } + count = 0; + if (ppm < 1000) { + noiseActive = false; + digitalWrite(PIN_LED_GREEN, 1); + digitalWrite(PIN_LED_YELLOW, 0); + digitalWrite(PIN_LED_RED, 0); + } + else if (ppm <= 2000) { + noiseActive = false; + digitalWrite(PIN_LED_GREEN, 0); + digitalWrite(PIN_LED_YELLOW, 1); + digitalWrite(PIN_LED_RED, 0); + } + else { + noiseActive = true; + digitalWrite(PIN_LED_GREEN, 0); + digitalWrite(PIN_LED_YELLOW, 0); + digitalWrite(PIN_LED_RED, 1); + } + } - // printValues(ppm, temp, humidity); - // } + if (noiseActive) { + noise = !noise; + digitalWrite(PIN_NOISE, noise); + } + else { + digitalWrite(PIN_NOISE, 0); + } - // if (ppm > 2000) { - // noise = !noise; - // digitalWrite(PIN_NOISE, noise); - // } - // else { - // digitalWrite(PIN_NOISE, 0); - // } - - // delay(NOISE_DELAY); - // count++; + delay(NOISE_DELAY); + count++; } \ No newline at end of file