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:
Fri Oct 06 07:51:13 2017 +0000
Revision:
3:ed294e830904
Parent:
2:05d00b8b071d
Child:
4:48545e508081
Cleaned up float calculation

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 0:a5033edf6975 22 return MQGetGasPercentage(MQRead()/10,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 0:a5033edf6975 29 return MQGetGasPercentage(MQRead()/10,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 0:a5033edf6975 36 return MQGetGasPercentage(MQRead()/10,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 3:ed294e830904 46 float MQ2::MQResistanceCalculation(float raw_adc) {
azazeal88 3:ed294e830904 47 return (((float)RL_VALUE*(1-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 3:ed294e830904 61 val += MQResistanceCalculation(_pin.read());
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 3:ed294e830904 81 rs += MQResistanceCalculation(_pin.read());
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 }