Merge pull request #1 from swablab/feature/GrafZ

add own library
This commit is contained in:
Johannes Gaiser 2021-04-11 17:48:25 +02:00 committed by GitHub
commit 17a00f8519
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 212 deletions

View file

@ -1,123 +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;
if (rs < 0) {
@return The sensor resistance in kOhm rs = 0;
*/ }
/**************************************************************************/ return rs;
float MQ135::getResistance() {
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) {
ppm = 0;
@param[in] t The ambient air temperature }
@param[in] h The relative humidity return ppm;
@return The corrected sensor resistance kOhm
*/
/**************************************************************************/
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;
double ppm = pow(10, ppm_log);
@return The ppm of CO2 in the air if (ppm < 0) {
*/ ppm = 0;
/**************************************************************************/ }
float MQ135::getPPM() { return ppm;
return PARA * pow((getResistance()/RZERO), -PARB);
} }
/**************************************************************************/ 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 double MQ135::getCO() {
@param[in] h The relative humidity return getPPM(605.18, -3.937);
}
@return The corrected sensor resistance RZero in kOhm
*/ double MQ135::getNH4() {
/**************************************************************************/ return getPPM(102.2, -2.473);
float MQ135::getCorrectedRZero(float t, float h) { }
return getCorrectedResistance(t, h) * pow((ATMOCO2/PARA), (1./PARB));
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;
} }

View file

@ -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 480
/// 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 for 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

View file

@ -8,7 +8,10 @@
; Please visit documentation for the other options and examples ; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[env:uno] [env:mega]
platform = atmelavr platform = atmelavr
board = uno board = megaatmega2560
framework = arduino framework = arduino
; lib_deps =
; adafruit/Adafruit BME280 Library @ ^2.1.2
; miguel5612/MQUnifiedsensor @ ^2.0.1

View file

@ -1,10 +1,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <MQ135.h> #include <MQ135.h>
#include <dht.h>
#define PIN_MQ135 A0 #define PIN_MQ135 A0
#define PIN_DHT11 A1
#define PIN_LED_GREEN DD2 #define PIN_LED_GREEN DD2
#define PIN_LED_YELLOW DD3 #define PIN_LED_YELLOW DD3
#define PIN_LED_RED DD4 #define PIN_LED_RED DD4
@ -13,93 +10,48 @@
#define MEASURE_DELAY 1000 #define MEASURE_DELAY 1000
#define NOISE_DELAY 100 #define NOISE_DELAY 100
MQ135 co2_sensor = MQ135(PIN_MQ135); const int maxCount = 10;
dht dht_sensor;
const int maxCount = MEASURE_DELAY / NOISE_DELAY;
int count = 0; int count = 0;
float ppm = -1;
bool noise = false; bool noise = false;
bool noiseActive = false;
float ppm;
MQ135 co2_sensor(PIN_MQ135);
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
pinMode(PIN_MQ135, INPUT); co2_sensor.setR0(100);
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() { void printValues(float ppm, float temp, float humidity);
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() { void loop() {
if (count >= maxCount || ppm < 0) { if (count >= maxCount || count < 0) {
ppm = measure(); ppm = co2_sensor.getCO2();
count = 0; count = 0;
if (ppm < 1000) { if (ppm < 1000) {
noiseActive = false;
digitalWrite(PIN_LED_GREEN, 1); digitalWrite(PIN_LED_GREEN, 1);
digitalWrite(PIN_LED_YELLOW, 0); digitalWrite(PIN_LED_YELLOW, 0);
digitalWrite(PIN_LED_RED, 0); digitalWrite(PIN_LED_RED, 0);
} }
else if (ppm <= 2000) { else if (ppm <= 2000) {
noiseActive = false;
digitalWrite(PIN_LED_GREEN, 0); digitalWrite(PIN_LED_GREEN, 0);
digitalWrite(PIN_LED_YELLOW, 1); digitalWrite(PIN_LED_YELLOW, 1);
digitalWrite(PIN_LED_RED, 0); digitalWrite(PIN_LED_RED, 0);
} }
else { else {
noiseActive = true;
digitalWrite(PIN_LED_GREEN, 0); digitalWrite(PIN_LED_GREEN, 0);
digitalWrite(PIN_LED_YELLOW, 0); digitalWrite(PIN_LED_YELLOW, 0);
digitalWrite(PIN_LED_RED, 1); digitalWrite(PIN_LED_RED, 1);
} }
} }
if (ppm > 2000) { if (noiseActive) {
noise = !noise; noise = !noise;
digitalWrite(PIN_NOISE, noise); digitalWrite(PIN_NOISE, noise);
} }