-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmq7.py
120 lines (97 loc) · 5.98 KB
/
mq7.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# adapted from sandboxelectronics.com/?p=165
import time
import math
from MCP3008 import MCP3008
class MQ7():
######################### Hardware Related Macros #########################
MQ_PIN = 1 # define which analog input channel you are going to use (MCP3008)
RL_VALUE = 5 # define the load resistance on the board, in kilo ohms (MQ7 RL 2-20kOhm)
RO_CLEAN_AIR_FACTOR = 9.83 # RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
# which is derived from the chart in datasheet
######################### Software Related Macros #########################
CALIBARAION_SAMPLE_TIMES = 50 # define how many samples you are going to take in the calibration phase
CALIBRATION_SAMPLE_INTERVAL = 500 # define the time interval(in milisecond) between each samples in the
# cablibration phase
READ_SAMPLE_INTERVAL = 50 # define the time interval(in milisecond) between each samples in
READ_SAMPLE_TIMES = 5 # define how many samples you are going to take in normal operation
# normal operation
######################### Application Related Macros ######################
GAS_CO = 0
def __init__(self, Ro=10, analogPin=0):
self.Ro = Ro
self.MQ_PIN = analogPin
self.adc = MCP3008()
self.COCurve = [2.77815125,-0.698970004,-0.74559379] # two points are taken from the curve.
print("Calibrating...")
self.Ro = self.MQCalibration(self.MQ_PIN)
print("Calibration is done...\n")
print("Ro=%f kohm" % self.Ro)
def MQPercentage(self):
val = {}
read = self.MQRead(self.MQ_PIN)
val["GAS_CO"] = self.MQGetGasPercentage(read/self.Ro, self.GAS_CO)
return val
######################### MQResistanceCalculation #########################
# Input: raw_adc - raw value read from adc, which represents the voltage
# Output: the calculated sensor resistance
# Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
# across the load resistor and its resistance, the resistance of the sensor
# could be derived.
############################################################################
def MQResistanceCalculation(self, raw_adc):
return float(self.RL_VALUE*(1023.0-raw_adc)/float(raw_adc));
######################### MQCalibration ####################################
# Input: mq_pin - analog channel
# Output: Ro of the sensor
# Remarks: This function assumes that the sensor is in clean air. It use
# MQResistanceCalculation to calculates the sensor resistance in clean air
# and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
# 10, which differs slightly between different sensors.
############################################################################
def MQCalibration(self, mq_pin):
val = 0.0
for i in range(self.CALIBARAION_SAMPLE_TIMES): # take multiple samples
val += self.MQResistanceCalculation(self.adc.read(mq_pin))
time.sleep(self.CALIBRATION_SAMPLE_INTERVAL/1000.0)
val = val/self.CALIBARAION_SAMPLE_TIMES # calculate the average value
print("so far: %f" % val)
val = val/self.RO_CLEAN_AIR_FACTOR # divided by RO_CLEAN_AIR_FACTOR yields the Ro
# according to the chart in the datasheet
return val;
######################### MQRead ##########################################
# Input: mq_pin - analog channel
# Output: Rs of the sensor
# Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
# The Rs changes as the sensor is in the different consentration of the target
# gas. The sample times and the time interval between samples could be configured
# by changing the definition of the macros.
############################################################################
def MQRead(self, mq_pin):
rs = 0.0
for i in range(self.READ_SAMPLE_TIMES):
rs += self.MQResistanceCalculation(self.adc.read(mq_pin))
time.sleep(self.READ_SAMPLE_INTERVAL/1000.0)
rs = rs/self.READ_SAMPLE_TIMES
return rs
######################### MQGetGasPercentage ##############################
# Input: rs_ro_ratio - Rs divided by Ro
# gas_id - target gas type
# Output: ppm of the target gas
# Remarks: This function passes different curves to the MQGetPercentage function which
# calculates the ppm (parts per million) of the target gas.
############################################################################
def MQGetGasPercentage(self, rs_ro_ratio, gas_id):
if ( gas_id == self.GAS_CO ):
return self.MQGetPercentage(rs_ro_ratio, self.COCurve)
return 0
######################### MQGetPercentage #################################
# Input: rs_ro_ratio - Rs divided by Ro
# pcurve - pointer to the curve of the target gas
# Output: ppm of the target gas
# Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
# of the line could be derived if y(rs_ro_ratio) is provided. As it is a
# logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
# value.
############################################################################
def MQGetPercentage(self, rs_ro_ratio, pcurve):
return (math.pow(10,( ((math.log(rs_ro_ratio)-pcurve[1])/ pcurve[2]) + pcurve[0])))