1/*
2 * Arduino Weather Station - Transmitter Unit
3 * Code by Andrew Lorimer (http://lorimer.id.au)
4 * Credit to @bram2202 (Instructables) and Leo Nutz (http://altduino.de)
5 */
6
7
8// Libraries
9#include <Wire.h> // Used for BMP180
10#include <VirtualWire.h> // Used for 433 MHz transmitter
11#include "DHT.h" // Adafruit DHTxx lib
12
13
14// Sensor setup
15
16DHT dht(2, DHT22); // Set up DHT22 object on digital pin 2
17#define bmppin 0x77 // I2C address of BMP180
18const unsigned char OSS = 0; // Oversampling Setting for BMP180
19
20// Calibration values for BMP180
21int ac1, ac2, ac3, b1, b2, mb, mc, md;
22unsigned int ac4, ac5, ac6;
23long b5;
24
25// Transmitter setup
26#define INTEGER_MAX (powx(2,31)-1)
27#define E_MAX (pow(10, 7))
28#define E_MIN (pow(10, -6))
29#define EPSILON 0.000000119209
30int txpin = 12; // Transmit pin of 433 MHz transmitter
31int linenumber = 0; // Tracks how many lines of data sent (0-3)
32
33
34
35void setup()
36{
37 Serial.begin(9600);
38 Serial.println("Entering setup routine...");
39
40 // DHT22 (humidity & temp)
41 dht.begin();
42 Serial.println("> Successfully started DHT22");
43
44 //Pressure sensor
45 Wire.begin();
46 CalibratePressure();
47 Serial.println("> Successfully started BMP180");
48
49 // Setup transmitter
50 pinMode('D12', OUTPUT);
51 vw_set_tx_pin(txpin);
52 vw_setup(2000); //
53 Serial.println("> Successfully started 433 MHz transmitter");
54
55 Serial.println("Finished setup routine.\n");
56}
57
58
59
60
61void loop() {
62
63 // Humidity (DHT22)
64 float humidity = dht.readHumidity(); // Read humidity
65 if (isnan(humidity)) {Serial.println("ERROR: Failed to read humidity from DHT22.");}
66 SendData("#H"+ ((String)humidity)); // Send humidity data
67 Serial.println(" Humidity: " + String(humidity) + " % (sent)");
68
69 // Temperature (BMP180)
70 float temperature = GetTemp(); // Read temperature
71 if (isnan(temperature)) {Serial.println("ERROR: Failed to read temperature from BMP180.");}
72 SendData("#C"+(String(temperature,2))); // Send temperature data
73 Serial.println("Temperature: " + String(temperature) + " " + char(176) + "C (sent)");
74
75 // Barometric pressure (BMP180)
76 float pressure = GetPressure(); // Read pressure
77 if (isnan(pressure)) {Serial.println("ERROR: Failed to read pressure from BMP180.");}
78 SendData("#P"+(String(pressure/100,2)));
79 Serial.println(" Pressure: " + String(temperature) + " hPa (sent)");
80
81 Serial.println();
82
83 delay(5000); //Wait for next loop
84
85}
86
87
88
89
90void SendData(String data) { // Transmit data over 433 MHz
91 const char* rawdata = data.c_str(); // Convert input string to char array
92 digitalWrite(13, true); // Flash onboard TX light
93 vw_send((uint8_t *)rawdata, strlen(rawdata)); //Send Data
94 vw_wait_tx(); // Wait until the whole message is gone
95 digitalWrite(13, false);
96}
97
98
99
100
101void CalibratePressure() {
102 ac1 = BMP180ReadInt(0xAA);
103 ac2 = BMP180ReadInt(0xAC);
104 ac3 = BMP180ReadInt(0xAE);
105 ac4 = BMP180ReadInt(0xB0);
106 ac5 = BMP180ReadInt(0xB2);
107 ac6 = BMP180ReadInt(0xB4);
108 b1 = BMP180ReadInt(0xB6);
109 b2 = BMP180ReadInt(0xB8);
110 mb = BMP180ReadInt(0xBA);
111 mc = BMP180ReadInt(0xBC);
112 md = BMP180ReadInt(0xBE);
113}
114
115
116
117
118float GetTemp(){ // Calculate temperature (deg C) based on calibration data
119
120 unsigned int ut;
121
122 // Write 0x2E into Register 0xF4
123 // This requests a temperature reading
124 Wire.beginTransmission(bmppin);
125 Wire.write(0xF4);
126 Wire.write(0x2E);
127 Wire.endTransmission();
128
129 delay(5); // Must be >4.5 ms
130
131 ut = BMP180ReadInt(0xF6); // Read two bytes from registers 0xF6 and 0xF7
132
133 long x1, x2;
134 x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
135 x2 = ((long)mc << 11)/(x1 + md);
136 b5 = x1 + x2;
137 float temp = ((b5 + 8)>>4);
138 temp = temp /10;
139
140 return temp;
141}
142
143
144
145
146long GetPressure(){ // Calculate pressure based on calibration data
147unsigned char msb, lsb, xlsb;
148 unsigned long up = 0;
149
150 // Write 0x34+(OSS<<6) into register 0xF4
151 // Request a pressure reading w/ oversampling setting
152 Wire.beginTransmission(bmppin);
153 Wire.write(0xF4);
154 Wire.write(0x34 + (OSS<<6));
155 Wire.endTransmission();
156
157 // Wait for conversion, delay time dependent on OSS
158 delay(2 + (3<<OSS));
159
160 // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
161 msb = BMP180Read(0xF6);
162 lsb = BMP180Read(0xF7);
163 xlsb = BMP180Read(0xF8);
164
165 up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
166
167
168 long x1, x2, x3, b3, b6, p;
169 unsigned long b4, b7;
170
171 b6 = b5 - 4000;
172 // Calculate B3
173 x1 = (b2 * (b6 * b6)>>12)>>11;
174 x2 = (ac2 * b6)>>11;
175 x3 = x1 + x2;
176 b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
177
178 // Calculate B4
179 x1 = (ac3 * b6)>>13;
180 x2 = (b1 * ((b6 * b6)>>12))>>16;
181 x3 = ((x1 + x2) + 2)>>2;
182 b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
183
184 b7 = ((unsigned long)(up - b3) * (50000>>OSS));
185 if (b7 < 0x80000000)
186 p = (b7<<1)/b4;
187 else
188 p = (b7/b4)<<1;
189
190 x1 = (p>>8) * (p>>8);
191 x1 = (x1 * 3038)>>16;
192 x2 = (-7357 * p)>>16;
193 p += (x1 + x2 + 3791)>>4;
194
195 long temp = p;
196 return temp;
197}
198
199
200
201
202char BMP180Read(unsigned char address) { // Read 1 byte
203 unsigned char data;
204
205 Wire.beginTransmission(bmppin);
206 Wire.write(address);
207 Wire.endTransmission();
208
209 Wire.requestFrom(bmppin, 1);
210 while(!Wire.available());
211
212 return Wire.read();
213}
214
215int BMP180ReadInt(unsigned char address) { // Read 2 bytes - first from 'address', second from 'address' + 1
216 unsigned char msb, lsb;
217
218 Wire.beginTransmission(bmppin);
219 Wire.write(address);
220 Wire.endTransmission();
221
222 Wire.requestFrom(bmppin, 2);
223 while(Wire.available()<2)
224 ;
225 msb = Wire.read();
226 lsb = Wire.read();
227
228 return (int) msb<<8 | lsb;
229}