Lovkesh Chauhan / MQ2

Dependents:   SmartKitchen_MiniProject SmartKitchen_MiniProject_RTES

Committer:
emelinegen
Date:
Tue Jun 22 12:34:07 2021 +0000
Revision:
8:6eba34552ceb
Parent:
6:c0ebeb4b47b6
Child:
9:54c2e1d69508
d

Who changed what in which revision?

UserRevisionLine numberNew contents of line
azazeal88 0:a5033edf6975 1 #include "MQ2.h"
azazeal88 0:a5033edf6975 2
azazeal88 0:a5033edf6975 3 void MQ2::begin(){
azazeal88 0:a5033edf6975 4 Ro = MQCalibration();
azazeal88 0:a5033edf6975 5 }
azazeal88 0:a5033edf6975 6
azazeal88 0:a5033edf6975 7 /*
azazeal88 0:a5033edf6975 8 * Reads data from MQ2.
azazeal88 0:a5033edf6975 9 *
azazeal88 0:a5033edf6975 10 * Param data: the pointer to fill.
azazeal88 0:a5033edf6975 11 */
azazeal88 0:a5033edf6975 12 void MQ2::read(MQ2_data_t *data){
azazeal88 0:a5033edf6975 13 data->lpg = MQGetGasPercentage(MQRead()/Ro,GAS_LPG);
azazeal88 0:a5033edf6975 14 data->co = MQGetGasPercentage(MQRead()/Ro,GAS_CO);
azazeal88 0:a5033edf6975 15 data->smoke = MQGetGasPercentage(MQRead()/Ro,GAS_SMOKE);
azazeal88 0:a5033edf6975 16 }
azazeal88 0:a5033edf6975 17
azazeal88 0:a5033edf6975 18 /*
azazeal88 0:a5033edf6975 19 * reads data, returns LPG value in ppm
azazeal88 0:a5033edf6975 20 */
azazeal88 0:a5033edf6975 21 float MQ2::readLPG(){
azazeal88 4:48545e508081 22 return MQGetGasPercentage(MQRead()/Ro,GAS_LPG);
azazeal88 0:a5033edf6975 23 }
azazeal88 0:a5033edf6975 24
azazeal88 0:a5033edf6975 25 /*
azazeal88 0:a5033edf6975 26 * reads data, returns CO value in ppm
azazeal88 0:a5033edf6975 27 */
azazeal88 0:a5033edf6975 28 float MQ2::readCO(){
azazeal88 4:48545e508081 29 return MQGetGasPercentage(MQRead()/Ro,GAS_CO);
azazeal88 0:a5033edf6975 30 }
azazeal88 0:a5033edf6975 31
azazeal88 0:a5033edf6975 32 /*
azazeal88 0:a5033edf6975 33 * reads data, returns Smoke value in ppm
azazeal88 0:a5033edf6975 34 */
azazeal88 0:a5033edf6975 35 float MQ2::readSmoke(){
azazeal88 4:48545e508081 36 return MQGetGasPercentage(MQRead()/Ro,GAS_SMOKE);
azazeal88 0:a5033edf6975 37 }
azazeal88 0:a5033edf6975 38
azazeal88 2:05d00b8b071d 39 /****************** MQResistanceCalculation ****************************************
azazeal88 2:05d00b8b071d 40 Input: raw_adc - raw value read from adc, which represents the voltage
azazeal88 2:05d00b8b071d 41 Output: the calculated sensor resistance
azazeal88 2:05d00b8b071d 42 Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
azazeal88 2:05d00b8b071d 43 across the load resistor and its resistance, the resistance of the sensor
azazeal88 2:05d00b8b071d 44 could be derived.
azazeal88 2:05d00b8b071d 45 ************************************************************************************/
azazeal88 5:8b7ba76a7a76 46 float MQ2::MQResistanceCalculation(int raw_adc) {
azazeal88 5:8b7ba76a7a76 47 return (((float)RL_VALUE*(1023-raw_adc)/raw_adc));
azazeal88 0:a5033edf6975 48 }
azazeal88 0:a5033edf6975 49
azazeal88 2:05d00b8b071d 50 /***************************** MQCalibration ****************************************
azazeal88 2:05d00b8b071d 51 Input: mq_pin - analog channel
azazeal88 2:05d00b8b071d 52 Output: Ro of the sensor
azazeal88 2:05d00b8b071d 53 Remarks: This function assumes that the sensor is in clean air. It use
azazeal88 2:05d00b8b071d 54 MQResistanceCalculation to calculates the sensor resistance in clean air
azazeal88 2:05d00b8b071d 55 and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
azazeal88 2:05d00b8b071d 56 10, which differs slightly between different sensors.
azazeal88 2:05d00b8b071d 57 ************************************************************************************/
azazeal88 3:ed294e830904 58 float MQ2::MQCalibration() { // This should be done in 'clean air'
azazeal88 0:a5033edf6975 59 float val=0;
azazeal88 3:ed294e830904 60 for (int i=0;i<CALIBARAION_SAMPLE_TIMES;i++) { //take multiple samples
azazeal88 5:8b7ba76a7a76 61 val += MQResistanceCalculation(_pin.read_u16()>>6);
emelinegen 8:6eba34552ceb 62 //wait_ms(CALIBRATION_SAMPLE_INTERVAL);
emelinegen 8:6eba34552ceb 63 ThisThread::sleep_for(50ms);
azazeal88 0:a5033edf6975 64 }
azazeal88 3:ed294e830904 65 val = val/CALIBARAION_SAMPLE_TIMES; //calculate the average value
azazeal88 3:ed294e830904 66 val = val/RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro according to the chart in the datasheet
azazeal88 0:a5033edf6975 67 return val;
azazeal88 0:a5033edf6975 68 }
azazeal88 0:a5033edf6975 69
azazeal88 2:05d00b8b071d 70 /***************************** MQRead *********************************************
azazeal88 2:05d00b8b071d 71 Input: mq_pin - analog channel
azazeal88 2:05d00b8b071d 72 Output: Rs of the sensor
azazeal88 2:05d00b8b071d 73 Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
azazeal88 2:05d00b8b071d 74 The Rs changes as the sensor is in the different consentration of the target
azazeal88 2:05d00b8b071d 75 gas. The sample times and the time interval between samples could be configured
azazeal88 2:05d00b8b071d 76 by changing the definition of the macros.
azazeal88 2:05d00b8b071d 77 ************************************************************************************/
azazeal88 0:a5033edf6975 78 float MQ2::MQRead() {
azazeal88 0:a5033edf6975 79 int i;
azazeal88 0:a5033edf6975 80 float rs=0;
azazeal88 0:a5033edf6975 81 for (i=0;i<READ_SAMPLE_TIMES;i++) {
azazeal88 6:c0ebeb4b47b6 82 rs += MQResistanceCalculation(_pin.read_u16()>>6);
emelinegen 8:6eba34552ceb 83 //wait_ms(READ_SAMPLE_INTERVAL);
emelinegen 8:6eba34552ceb 84 ThisThread::sleep_for(50ms);
azazeal88 0:a5033edf6975 85 }
azazeal88 0:a5033edf6975 86 rs = rs/READ_SAMPLE_TIMES;
azazeal88 0:a5033edf6975 87 return rs;
azazeal88 0:a5033edf6975 88 }
azazeal88 0:a5033edf6975 89
azazeal88 2:05d00b8b071d 90 /***************************** MQGetGasPercentage **********************************
azazeal88 2:05d00b8b071d 91 Input: rs_ro_ratio - Rs divided by Ro
azazeal88 2:05d00b8b071d 92 gas_id - target gas type
azazeal88 2:05d00b8b071d 93 Output: ppm of the target gas
azazeal88 2:05d00b8b071d 94 Remarks: This function passes different curves to the MQGetPercentage function which
azazeal88 2:05d00b8b071d 95 calculates the ppm (parts per million) of the target gas.
azazeal88 2:05d00b8b071d 96 ************************************************************************************/
azazeal88 0:a5033edf6975 97 float MQ2::MQGetGasPercentage(float rs_ro_ratio, GasType gas_id) {
azazeal88 0:a5033edf6975 98 switch(gas_id) {
azazeal88 0:a5033edf6975 99 case GAS_LPG: return MQGetPercentage(rs_ro_ratio,LPGCurve);
azazeal88 0:a5033edf6975 100 case GAS_CO: return MQGetPercentage(rs_ro_ratio,COCurve);
azazeal88 0:a5033edf6975 101 case GAS_SMOKE: return MQGetPercentage(rs_ro_ratio,SmokeCurve);
azazeal88 0:a5033edf6975 102 default: return -1.0;
azazeal88 0:a5033edf6975 103 }
azazeal88 0:a5033edf6975 104 }
azazeal88 0:a5033edf6975 105
azazeal88 2:05d00b8b071d 106 /***************************** MQGetPercentage **********************************
azazeal88 2:05d00b8b071d 107 Input: rs_ro_ratio - Rs divided by Ro
azazeal88 2:05d00b8b071d 108 pcurve - pointer to the curve of the target gas
azazeal88 2:05d00b8b071d 109 Output: ppm of the target gas
azazeal88 2:05d00b8b071d 110 Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
azazeal88 2:05d00b8b071d 111 of the line could be derived if y(rs_ro_ratio) is provided. As it is a
azazeal88 2:05d00b8b071d 112 logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
azazeal88 2:05d00b8b071d 113 value.
azazeal88 2:05d00b8b071d 114 ************************************************************************************/
azazeal88 0:a5033edf6975 115 int MQ2::MQGetPercentage(float rs_ro_ratio, float *pcurve) {
azazeal88 0:a5033edf6975 116 return (pow(10,(((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
azazeal88 0:a5033edf6975 117 }