9358d3dfdf448d4c8216adb010d6e9b6e8530ab1
[weathermon.git] / Weather_Station.ino
1 /* SFE_BMP180 library example sketch
2
3 This sketch shows how to use the SFE_BMP180 library to read the
4 Bosch BMP180 barometric pressure sensor.
5 https://www.sparkfun.com/products/11824
6
7 Like most pressure sensors, the BMP180 measures absolute pressure.
8 This is the actual ambient pressure seen by the device, which will
9 vary with both altitude and weather.
10
11 Before taking a pressure reading you must take a temparture reading.
12 This is done with startTemperature() and getTemperature().
13 The result is in degrees C.
14
15 Once you have a temperature reading, you can take a pressure reading.
16 This is done with startPressure() and getPressure().
17 The result is in millibar (mb) aka hectopascals (hPa).
18
19 If you'll be monitoring weather patterns, you will probably want to
20 remove the effects of altitude. This will produce readings that can
21 be compared to the published pressure readings from other locations.
22 To do this, use the sealevel() function. You will need to provide
23 the known altitude at which the pressure was measured.
24
25 If you want to measure altitude, you will need to know the pressure
26 at a baseline altitude. This can be average sealevel pressure, or
27 a previous pressure reading at your altitude, in which case
28 subsequent altitude readings will be + or - the initial baseline.
29 This is done with the altitude() function.
30
31 Hardware connections:
32
33 - (GND) to GND
34 + (VDD) to 3.3V
35
36 (WARNING: do not connect + to 5V or the sensor will be damaged!)
37
38 You will also need to connect the I2C pins (SCL and SDA) to your
39 Arduino. The pins are different on different Arduinos:
40
41 Any Arduino pins labeled:  SDA  SCL
42 Uno, Redboard, Pro:        A4   A5
43 Mega2560, Due:             20   21
44 Leonardo:                   2    3
45
46 Leave the IO (VDDIO) pin unconnected. This pin is for connecting
47 the BMP180 to systems with lower logic levels such as 1.8V
48
49 Have fun! -Your friends at SparkFun.
50
51 The SFE_BMP180 library uses floating-point equations developed by the
52 Weather Station Data Logger project: http://wmrx00.sourceforge.net/
53
54 Our example code uses the "beerware" license. You can do anything
55 you like with this code. No really, anything. If you find it useful,
56 buy me a beer someday.
57
58 V10 Mike Grusin, SparkFun Electronics 10/24/2013
59 */
60
61 // Your sketch must #include this library, and the Wire library.
62 // (Wire is a standard library included with Arduino.):
63
64 #include <SFE_BMP180.h>
65 #include <Wire.h>
66 #include "DHT.h"
67
68 // You will need to create an SFE_BMP180 object, here called "pressure":
69
70 SFE_BMP180 pressure;
71
72 // DHT object for humidity sensor
73 DHT dht;
74
75 #define CO2_PIN A1
76 #define DHT_PIN 4
77 #define GAS_PIN A0
78 #define START_DELAY 20000
79 #define DELAY 50000
80
81 byte HasBaro;
82
83 #define READ_SAMPLE_INTERVAL 50
84 #define READ_SAMPLE_TIMES 5
85
86 #define MQ135_RES 1000
87
88 float MQRead(int mq_pin)
89 {
90
91   int i;
92   float rs=0;
93   float rr;
94
95   for (i=0;i<READ_SAMPLE_TIMES;i++) {
96     rr = analogRead(mq_pin);
97     rs += rr;
98     delay(READ_SAMPLE_INTERVAL);
99   }
100  
101   rs = rs/READ_SAMPLE_TIMES;
102   return rs;
103
104 }
105
106 /// Parameters to model temperature and humidity dependence
107
108 #define CORA 0.00035
109 #define CORB 0.02718
110 #define CORC 1.39538
111 #define CORD 0.0018
112
113 float getMQ135CorrectionFactor(float t, float h) {
114   return CORA * t * t - CORB * t + CORC - (h-33.)*CORD;
115 }
116
117 #define RZERO 25300
118 #define PARA 116.6020682
119 #define PARB 2.769034857
120
121 float getMQ135ppm(float Resistance) {
122   return PARA * pow((Resistance/RZERO), -PARB);  
123 }
124
125 void setup()
126 {
127   delay(START_DELAY);
128
129   Serial1.begin(57600);
130   Serial1.println("START");
131
132   // Initialize the sensor (it is important to get calibration values stored on the device).
133
134   if (pressure.begin()) {
135     Serial1.println("BMP180 init success");
136     HasBaro = 1;
137   } else {
138     Serial1.println("BMP180 init fail\n\n");
139     HasBaro = 0;
140   }
141   
142   dht.setup(DHT_PIN);
143   
144   pinMode(GAS_PIN,INPUT);
145   pinMode(CO2_PIN,INPUT);
146   
147   digitalWrite(GAS_PIN, LOW);
148   digitalWrite(CO2_PIN, LOW);
149 }
150
151 void loop()
152 {
153   char status;
154   double T,P;
155   double DHT_T,DHT_H;
156   int DHTStatus;
157   int Gas;
158
159   double LastTemp;
160   byte GotTemperature,GotPressure;
161
162   // Loop here getting pressure readings every 60 seconds.
163
164   GotTemperature = 0;
165   GotPressure = 0;
166
167   if (HasBaro) {
168     
169     status = pressure.startTemperature();
170     if (status != 0) {
171       // Wait for the measurement to complete:
172       delay(status);
173
174       // Retrieve the completed temperature measurement:
175       // Note that the measurement is stored in the variable T.
176       // Function returns 1 if successful, 0 if failure.
177
178       status = pressure.getTemperature(T);
179       if (status = !0) {
180         LastTemp=T;
181         GotTemperature=1;
182       } else {  
183         Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE TEMPERATURE\n");
184       }  
185     } else {
186       Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START TEMPERATURE MEASUREMENT\n");
187     }
188     
189     // Start a pressure measurement:
190     // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
191     // If request is successful, the number of ms to wait is returned.
192     // If request is unsuccessful, 0 is returned.
193
194     status = pressure.startPressure(3);
195     if (status != 0) {
196       // Wait for the measurement to complete:
197       delay(status);
198
199       // Retrieve the completed pressure measurement:
200       // Note that the measurement is stored in the variable P.
201       // Note also that the function requires the previous temperature measurement (T).
202       // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
203       // Function returns 1 if successful, 0 if failure.
204
205       status = pressure.getPressure(P,LastTemp);
206       if (status != 0) {
207           // Print out the measurement:
208           GotPressure=1;
209
210       } else {
211         Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE PRESSURE\n");
212       }  
213     } else {
214       Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START PRESSURE MEASUREMENT\n");
215     }  
216     if (GotPressure || GotTemperature) {
217       Serial1.print("SENSOR:TYPE=BMP180");
218       if (GotPressure) { Serial1.print(",PRESSURE="); Serial1.print(P); }
219       if (GotTemperature) { Serial1.print(",TEMPERATURE="); Serial1.print(T); }
220       Serial1.println();
221     }
222   }
223
224   delay(dht.getMinimumSamplingPeriod());
225
226   DHT_H = dht.getHumidity();
227   DHT_T = dht.getTemperature();
228
229   DHTStatus=dht.getStatus();
230  
231   if (DHTStatus == 0) {
232     Serial1.print("SENSOR:TYPE=DHT22,TEMPERATURE=");
233     Serial1.print(DHT_T);
234     Serial1.print(",HUMIDITY=");
235     Serial1.println(DHT_H);
236   } else {
237     Serial1.print("ERROR:TYPE=DHT22,MESSAGE=");
238     Serial1.println(dht.getStatusString());
239   }
240   
241   Gas = MQRead(GAS_PIN);
242   
243   Serial1.print("SENSOR:TYPE=MQ4,VALUE=");
244   Serial1.println(Gas);
245
246   float MQ135_Resistance;
247   float CO2_raw;
248   float CO2_ppm;
249
250   float CO2_resistance;
251
252   CO2_raw = MQRead(CO2_PIN);
253   Serial1.print("DEBUG:RAW=");
254   Serial1.println(CO2_raw);
255
256   MQ135_Resistance=MQ135_RES*(1023./CO2_raw-1);
257   
258   Serial1.print("DEBUG:RESISTANCE=");
259   Serial1.println(MQ135_Resistance);
260   
261   MQ135_Resistance=MQ135_Resistance/getMQ135CorrectionFactor(DHT_T,DHT_H);
262   Serial1.print("DEBUG:CORR_RESISTANCE=");
263   Serial1.println(MQ135_Resistance);  
264
265   CO2_ppm = getMQ135ppm(MQ135_Resistance);  
266   
267   Serial1.print("SENSOR:TYPE=MQ135,VALUE=");
268   Serial1.println(CO2_ppm);
269   
270   delay(DELAY);  // Pause for 50 seconds.
271 }
272