From e3f5e2ec0c808ec4fecd760382061af871df202b Mon Sep 17 00:00:00 2001 From: miguel5612 Date: Mon, 21 Mar 2022 14:32:37 -0500 Subject: [PATCH] Added unit tests! to validate library calculations --- examples/MQ-303A/{MQ303.ino => MQ-303A.ino} | 0 examples/MQ-309A/{MQ-309.ino => MQ-309A.ino} | 0 examples/UnitTesting/UnitTesting.ino | 272 +++++++++++++++++++ src/MQUnifiedsensor.cpp | 26 +- src/MQUnifiedsensor.h | 11 +- 5 files changed, 301 insertions(+), 8 deletions(-) rename examples/MQ-303A/{MQ303.ino => MQ-303A.ino} (100%) rename examples/MQ-309A/{MQ-309.ino => MQ-309A.ino} (100%) create mode 100644 examples/UnitTesting/UnitTesting.ino diff --git a/examples/MQ-303A/MQ303.ino b/examples/MQ-303A/MQ-303A.ino similarity index 100% rename from examples/MQ-303A/MQ303.ino rename to examples/MQ-303A/MQ-303A.ino diff --git a/examples/MQ-309A/MQ-309.ino b/examples/MQ-309A/MQ-309A.ino similarity index 100% rename from examples/MQ-309A/MQ-309.ino rename to examples/MQ-309A/MQ-309A.ino diff --git a/examples/UnitTesting/UnitTesting.ino b/examples/UnitTesting/UnitTesting.ino new file mode 100644 index 0000000..94ab895 --- /dev/null +++ b/examples/UnitTesting/UnitTesting.ino @@ -0,0 +1,272 @@ +/* + MQUnifiedsensor Library - testing library + + Library originally added 01 may 2019 + by Miguel A Califa, Yersson Carrillo, Ghiordy Contreras, Mario Rodriguez + + Added example + modified 21 March 2022 + by Miguel Califa + + This example code is in the public domain. + +*/ + +//Include the library +#include +#line 2 "basic.ino" +#include + +/************************Hardware Related Macros************************************/ +#define Board ("Arduino Mega") +#define Pin2 (A2) //Analog input 2 of your arduino +#define Pin3 (A3) //Analog input 3 of your arduino +#define Pin4 (A4) //Analog input 4 of your arduino +#define Pin5 (A5) //Analog input 5 of your arduino +#define Pin6 (A6) //Analog input 6 of your arduino +#define Pin7 (A7) //Analog input 7 of your arduino +#define Pin8 (A8) //Analog input 8 of your arduino +#define Pin9 (A9) //Analog input 9 of your arduino +#define Pin10 (A10) //Analog input 9 of your arduino +#define Pin11 (A11) //Analog input 9 of your arduino +#define Pin12 (A12) //Analog input 9 of your arduino +#define Pin13 (A13) //Analog input 9 of your arduino +#define Pin14 (A14) //Analog input 9 of your arduino +#define PWMPin (5) // Pin connected to mosfet +/***********************Software Related Macros************************************/ +#define RatioMQ2CleanAir (9.83) //RS / R0 = 9.83 ppm +#define RatioMQ3CleanAir (60) //RS / R0 = 60 ppm +#define RatioMQ4CleanAir (4.4) //RS / R0 = 4.4 ppm +#define RatioMQ5CleanAir (6.5) //RS / R0 = 6.5 ppm +#define RatioMQ6CleanAir (10) //RS / R0 = 10 ppm +#define RatioMQ7CleanAir (27.5) //RS / R0 = 27.5 ppm +#define RatioMQ8CleanAir (70) //RS / R0 = 70 ppm +#define RatioMQ9CleanAir (9.6) //RS / R0 = 9.6 ppm +#define RatioMQ136CleanAir (3.6) //RS / R0 = 9.6 ppm +#define ADC_Bit_Resolution (10) // 10 bit ADC +#define Voltage_Resolution (5) // Volt resolution to calc the voltage +#define Type ("Arduino Mega 2560") //Board used +/*****************************Globals***********************************************/ +//Declare Sensor +MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin2, Type); +MQUnifiedsensor MQ3(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin3, Type); +MQUnifiedsensor MQ4(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin4, Type); +MQUnifiedsensor MQ5(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin5, Type); +MQUnifiedsensor MQ6(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin6, Type); +MQUnifiedsensor MQ7(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin7, Type); +MQUnifiedsensor MQ8(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin8, Type); +MQUnifiedsensor MQ9(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin9, Type); +MQUnifiedsensor MQ131(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin10, Type); //mq131 +MQUnifiedsensor MQ135(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin11, Type); //mq135 +MQUnifiedsensor MQ136(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin12, Type); //mq136 +MQUnifiedsensor MQ303A(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin13, Type); //mq303 +MQUnifiedsensor MQ309A(Board, Voltage_Resolution, ADC_Bit_Resolution, Pin14, Type); //mq309 + + +test(adcMaxValue) +{ + int adcVal=1023; + int volt = MQ2.getVoltage(false, true, adcVal); + int expVolt = 5; + assertEqual(volt,expVolt); +} + +test(adcMinValue) +{ + int adcVal=0; + int volt = MQ2.getVoltage(false, true, adcVal); + int expVolt = 0; + assertEqual(volt,expVolt); +} + +test(adcMidValue) +{ + int adcVal=410; + int volt = MQ2.getVoltage(false, true, adcVal); + int expVolt = 2; + assertEqual(volt,expVolt); +} + +test(MQ2_LPG) +{ + MQ2.setRegressionMethod(1); //_PPM = a*ratio^b + MQ2.setA(574.25); MQ2.setB(-2.222); // Configure the equation to to calculate LPG concentration + MQ2.init(); + MQ2.setR0(10); + + int ppmExp=464; + int PPM = MQ2.setRsR0RatioGetPPM(1.1); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ3_Alcohol) +{ + MQ3.setRegressionMethod(1); //_PPM = a*ratio^b + MQ3.setA(0.3934); MQ3.setB(-1.504); // Configure the equation to to calculate Alcohol concentration + MQ3.init(); + MQ3.setR0(10); + + int ppmExp=4; + int PPM = MQ3.setRsR0RatioGetPPM(0.2); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + + +test(MQ4_Smoke) +{ + MQ4.setRegressionMethod(1); //_PPM = a*ratio^b + MQ4.setA(30000000); MQ4.setB(-8.31); // Configure the equation to to calculate Smoke concentration + MQ4.init(); + MQ4.setR0(10); + + int ppmExp=297; + int PPM = MQ4.setRsR0RatioGetPPM(4); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ5_LPG) +{ + MQ5.setRegressionMethod(1); //_PPM = a*ratio^b + MQ5.setA(80.897); MQ5.setB(-2.431); // Configure the equation to to calculate LPG concentration + MQ5.init(); + MQ5.setR0(10); + + int ppmExp=192; + int PPM = MQ5.setRsR0RatioGetPPM(0.7); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ6_CH4) +{ + MQ6.setRegressionMethod(1); //_PPM = a*ratio^b + MQ6.setA(2127.2); MQ6.setB(-2.526); // Configure the equation to to calculate CH4 concentration + MQ6.init(); + MQ6.setR0(10); + + int ppmExp=2127; + int PPM = MQ6.setRsR0RatioGetPPM(1); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ7_CH4) +{ + MQ7.setRegressionMethod(1); //_PPM = a*ratio^b + MQ7.setA(99.042); MQ7.setB(-1.518); // Configure the equation to to calculate CH4 concentration + MQ7.init(); + MQ7.setR0(10); + + int ppmExp=1139; + int PPM = MQ7.setRsR0RatioGetPPM(0.2); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ8_H2) +{ + MQ8.setRegressionMethod(1); //_PPM = a*ratio^b + MQ8.setA(976.97); MQ8.setB(-0.688); // Configure the equation to to calculate H2 concentration + MQ8.init(); + MQ8.setR0(10); + + int ppmExp=2956; + int PPM = MQ8.setRsR0RatioGetPPM(0.2); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + + +test(MQ9_CO) +{ + MQ9.setRegressionMethod(1); //_PPM = a*ratio^b + MQ9.setA(599.65); MQ9.setB(-2.244); // Configure the equation to to calculate CO concentration + MQ9.init(); + MQ9.setR0(10); + + int ppmExp=989; + int PPM = MQ9.setRsR0RatioGetPPM(0.8); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ131_O3) +{ + MQ131.setRegressionMethod(1); //_PPM = a*ratio^b + MQ131.setA(23.943); MQ131.setB(-1.11); // Configure the equation to to calculate O3 concentration + MQ131.init(); + MQ131.setR0(10); + + int ppmExp=11; + int PPM = MQ131.setRsR0RatioGetPPM(2); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + + +test(MQ135_CO2) +{ + MQ135.setRegressionMethod(1); //_PPM = a*ratio^b + MQ135.setA(110.47); MQ135.setB(-2.862); // Configure the equation to to calculate CO2 concentration + MQ135.init(); + MQ135.setR0(10); + + int ppmExp=110; + int PPM = MQ135.setRsR0RatioGetPPM(1); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ136_H2S) +{ + MQ136.setRegressionMethod(1); //_PPM = a*ratio^b + MQ136.setA(36.737); MQ136.setB(-3.536); // Configure the equation to to calculate H2S concentration + MQ136.init(); + MQ136.setR0(10); + + int ppmExp=223; + int PPM = MQ136.setRsR0RatioGetPPM(0.6); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ303A_Ethanol) +{ + MQ303A.setRegressionMethod(1); //_PPM = a*ratio^b + MQ303A.setA(3.4916); MQ303A.setB(-2.432); // Configure the equation to to calculate Ethanol concentration + MQ303A.init(); + MQ303A.setR0(10); + + int ppmExp=944; + int PPM = MQ303A.setRsR0RatioGetPPM(0.1); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + +test(MQ309A_CO) +{ + MQ309A.setRegressionMethod(1); //_PPM = a*ratio^b + MQ309A.setA(1000000); MQ309A.setB(-4.01); // Configure the equation to to calculate CO concentration + MQ309A.init(); + MQ309A.setR0(10); + + int ppmExp=757; + int PPM = MQ309A.setRsR0RatioGetPPM(6); // Send and Rs/R0 and return PPM (Using datasheet) + + assertEqual(PPM,ppmExp); +} + + +void setup() +{ + Serial.begin(9600); + while(!Serial) {} // Portability for Leonardo/Micro +} + +void loop() +{ + Test::run(); +} diff --git a/src/MQUnifiedsensor.cpp b/src/MQUnifiedsensor.cpp index 3620ede..838521e 100644 --- a/src/MQUnifiedsensor.cpp +++ b/src/MQUnifiedsensor.cpp @@ -133,7 +133,7 @@ float MQUnifiedsensor::validateEcuation(float ratioInput) //Serial.println("Result: "); Serial.println(_PPM); return _PPM; } -float MQUnifiedsensor::readSensor(bool isMQ303A, float correctionFactor) +float MQUnifiedsensor::readSensor(bool isMQ303A, float correctionFactor, bool injected) { //More explained in: https://jayconsystems.com/blog/understanding-a-gas-sensor if(isMQ303A) { @@ -141,7 +141,7 @@ float MQUnifiedsensor::readSensor(bool isMQ303A, float correctionFactor) } _RS_Calc = ((_VOLT_RESOLUTION*_RL)/_sensor_volt)-_RL; //Get value of RS in a gas if(_RS_Calc < 0) _RS_Calc = 0; //No negative values accepted. - _ratio = _RS_Calc / this->_R0; // Get ratio RS_gas/RS_air + if(!injected) _ratio = _RS_Calc / this->_R0; // Get ratio RS_gas/RS_air _ratio += correctionFactor; if(_ratio <= 0) _ratio = 0; //No negative values accepted or upper datasheet recomendation. if(_regressionMethod == 1) _PPM= _a*pow(_ratio, _b); // <- Source excel analisis https://github.com/miguel5612/MQSensorsLib_Docs/tree/master/Internal_design_documents @@ -194,7 +194,7 @@ float MQUnifiedsensor::calibrate(float ratioInCleanAir) { if(R0 < 0) R0 = 0; //No negative values accepted. return R0; } -float MQUnifiedsensor::getVoltage(int read) { +float MQUnifiedsensor::getVoltage(bool read, bool injected, int value) { float voltage; if(read) { @@ -206,12 +206,30 @@ float MQUnifiedsensor::getVoltage(int read) { } voltage = (avg/ retries) * _VOLT_RESOLUTION / ((pow(2, _ADC_Bit_Resolution)) - 1); } - else + else if(!injected) { voltage = _sensor_volt; } + else + { + voltage = (value) * _VOLT_RESOLUTION / ((pow(2, _ADC_Bit_Resolution)) - 1); + _sensor_volt = voltage; //to work on testing + } return voltage; } +float MQUnifiedsensor:: setRsR0RatioGetPPM(float value) +{ + _ratio = value; + return readSensor(false, 0, true); +} +float MQUnifiedsensor::getRS() +{ + //More explained in: https://jayconsystems.com/blog/understanding-a-gas-sensor + _RS_Calc = ((_VOLT_RESOLUTION*_RL)/_sensor_volt)-_RL; //Get value of RS in a gas + if(_RS_Calc < 0) _RS_Calc = 0; //No negative values accepted. + return _RS_Calc; +} + float MQUnifiedsensor::stringTofloat(String & str) { return atof( str.c_str() ); diff --git a/src/MQUnifiedsensor.h b/src/MQUnifiedsensor.h index 987d540..dd155bd 100644 --- a/src/MQUnifiedsensor.h +++ b/src/MQUnifiedsensor.h @@ -31,7 +31,7 @@ class MQUnifiedsensor //user functions float calibrate(float ratioInCleanAir); - float readSensor(bool isMQ303A = false, float correctionFactor = 0.0); + float readSensor(bool isMQ303A = false, float correctionFactor = 0.0, bool injected=false); float readSensorR0Rs(); float validateEcuation(float ratioInput = 0); @@ -42,9 +42,12 @@ class MQUnifiedsensor float getRL(); float getVoltResolution(); String getRegressionMethod(); - float getVoltage(int read = true); - - float stringTofloat(String & str); + float getVoltage(bool read = true, bool injected = false, int value = 0); + float stringTofloat(String & str); + + // functions for testing + float getRS(); + float setRsR0RatioGetPPM(float value); private: /************************Private vars************************************/