A library for the MQ2 sensor. Based on https://github.com/labay11 and http://sandboxelectronics.com/?p=165

Dependents:   mq2_example mq2_midtermproject ECE595_Group9_FinalProject mq2_example ... more

Committer:
azazeal88
Date:
Wed Nov 08 10:43:37 2017 +0000
Revision:
7:944051b30179
Parent:
6:c0ebeb4b47b6
RL_VALUE has been changed to 1 to reflect the sensors that we have (ours are used in teaching). Default is commonly around 5K, but check RL for your specific application!

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);
azazeal88 0:a5033edf6975 62 wait_ms(CALIBRATION_SAMPLE_INTERVAL);
azazeal88 0:a5033edf6975 63 }
azazeal88 3:ed294e830904 64 val = val/CALIBARAION_SAMPLE_TIMES; //calculate the average value
azazeal88 3:ed294e830904 65 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 66 return val;
azazeal88 0:a5033edf6975 67 }
azazeal88 0:a5033edf6975 68
azazeal88 2:05d00b8b071d 69 /***************************** MQRead *********************************************
azazeal88 2:05d00b8b071d 70 Input: mq_pin - analog channel
azazeal88 2:05d00b8b071d 71 Output: Rs of the sensor
azazeal88 2:05d00b8b071d 72 Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
azazeal88 2:05d00b8b071d 73 The Rs changes as the sensor is in the different consentration of the target
azazeal88 2:05d00b8b071d 74 gas. The sample times and the time interval between samples could be configured
azazeal88 2:05d00b8b071d 75 by changing the definition of the macros.
azazeal88 2:05d00b8b071d 76 ************************************************************************************/
azazeal88 0:a5033edf6975 77 float MQ2::MQRead() {
azazeal88 0:a5033edf6975 78 int i;
azazeal88 0:a5033edf6975 79 float rs=0;
azazeal88 0:a5033edf6975 80 for (i=0;i<READ_SAMPLE_TIMES;i++) {
azazeal88 6:c0ebeb4b47b6 81 rs += MQResistanceCalculation(_pin.read_u16()>>6);
azazeal88 0:a5033edf6975 82 wait_ms(READ_SAMPLE_INTERVAL);
azazeal88 0:a5033edf6975 83 }
azazeal88 0:a5033edf6975 84 rs = rs/READ_SAMPLE_TIMES;
azazeal88 0:a5033edf6975 85 return rs;
azazeal88 0:a5033edf6975 86 }
azazeal88 0:a5033edf6975 87
azazeal88 2:05d00b8b071d 88 /***************************** MQGetGasPercentage **********************************
azazeal88 2:05d00b8b071d 89 Input: rs_ro_ratio - Rs divided by Ro
azazeal88 2:05d00b8b071d 90 gas_id - target gas type
azazeal88 2:05d00b8b071d 91 Output: ppm of the target gas
azazeal88 2:05d00b8b071d 92 Remarks: This function passes different curves to the MQGetPercentage function which
azazeal88 2:05d00b8b071d 93 calculates the ppm (parts per million) of the target gas.
azazeal88 2:05d00b8b071d 94 ************************************************************************************/
azazeal88 0:a5033edf6975 95 float MQ2::MQGetGasPercentage(float rs_ro_ratio, GasType gas_id) {
azazeal88 0:a5033edf6975 96 switch(gas_id) {
azazeal88 0:a5033edf6975 97 case GAS_LPG: return MQGetPercentage(rs_ro_ratio,LPGCurve);
azazeal88 0:a5033edf6975 98 case GAS_CO: return MQGetPercentage(rs_ro_ratio,COCurve);
azazeal88 0:a5033edf6975 99 case GAS_SMOKE: return MQGetPercentage(rs_ro_ratio,SmokeCurve);
azazeal88 0:a5033edf6975 100 default: return -1.0;
azazeal88 0:a5033edf6975 101 }
azazeal88 0:a5033edf6975 102 }
azazeal88 0:a5033edf6975 103
azazeal88 2:05d00b8b071d 104 /***************************** MQGetPercentage **********************************
azazeal88 2:05d00b8b071d 105 Input: rs_ro_ratio - Rs divided by Ro
azazeal88 2:05d00b8b071d 106 pcurve - pointer to the curve of the target gas
azazeal88 2:05d00b8b071d 107 Output: ppm of the target gas
azazeal88 2:05d00b8b071d 108 Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
azazeal88 2:05d00b8b071d 109 of the line could be derived if y(rs_ro_ratio) is provided. As it is a
azazeal88 2:05d00b8b071d 110 logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
azazeal88 2:05d00b8b071d 111 value.
azazeal88 2:05d00b8b071d 112 ************************************************************************************/
azazeal88 0:a5033edf6975 113 int MQ2::MQGetPercentage(float rs_ro_ratio, float *pcurve) {
azazeal88 0:a5033edf6975 114 return (pow(10,(((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
azazeal88 0:a5033edf6975 115 }