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
MQ2.cpp@5:8b7ba76a7a76, 2017-10-06 (annotated)
- Committer:
- azazeal88
- Date:
- Fri Oct 06 08:57:00 2017 +0000
- Revision:
- 5:8b7ba76a7a76
- Parent:
- 4:48545e508081
- Child:
- 6:c0ebeb4b47b6
RC1
Who changed what in which revision?
User | Revision | Line number | New 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 | 5:8b7ba76a7a76 | 81 | rs += MQResistanceCalculation(_pin.read_16>>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 | } |