Medidor de temperatura pressão e umidade do ar¶
Licença de textos, imagens e esquema dos circuitos: Creative Commons Sharealike
Licença do software: GPL 3.0
Sensores¶
Os dois módulos funcionam em conjunto. O SHT15 fazendo leituras de temperatura e umidade e o BMP085 leituras de temperatura e pressão, nesta aplicação os dados de temperatura foram tomados somente do SHT15 por praticidade. Os dados são processados pelo Arduino e enviados ao LCD. A esquematização e o programa seguem abaixo.
Circuito¶
O BMP085 ainda possui duas outras , XCLR e EOC, que não foram utilizadas neste protótipo.
Potenciômetro - 10k ohm
Resistor - 330 ohm
Código¶
Realiza as medidas e as exibe no mostrador em tempo real. O controle para o SHT15 foi obtido em Wiring.org.co. O controle do módulo BMP085 foi retirado deste link. O programa ainda pode calcular a pressão em atmosferas (atm) e a altitude.
1 //Medidor de temperatura, pressão e umidade do ar (SHT15 & BMP085)
2
3 #include <Wire.h>
4 #include <LiquidCrystal.h>
5 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Cria um objeto LCD e designa os pinos
6
7 #define BMP085_ADDRESS 0x77 // I2C address of BMP085
8
9 const unsigned char OSS = 0; // Oversampling Setting
10
11 // Variáveis BMP085
12
13 // Calibration values
14 int ac1;
15 int ac2;
16 int ac3;
17 unsigned int ac4;
18 unsigned int ac5;
19 unsigned int ac6;
20 int b1;
21 int b2;
22 int mb;
23 int mc;
24 int md;
25
26 // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
27 // so ...Temperature(...) must be called before ...Pressure(...).
28 long b5;
29
30 // Variáveis SHT15
31
32 int temperatureCommand = B00000011; // comando usado pra ler a temp
33 int humidityCommand = B00000101; // comando usado pra ler a umidade
34
35 int clockPin = 8; // pin usado pro sck (clock)
36 int dataPin = 9; // pin usado pro data
37 int ack; // track acknowledgment for errors
38 int val;
39 float temp;
40 float humidity;
41
42 void setup(){
43 lcd.begin(16, 2);
44 lcd.clear();
45 Wire.begin();
46
47 bmp085Calibration();
48 }
49
50 void loop()
51 {
52 float temperature = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
53 float pressure = bmp085GetPressure(bmp085ReadUP());
54 float atm = pressure / 101325; // "standard atmosphere"
55 float altitude = calcAltitude(pressure); //Uncompensated caculation - in Meters
56
57 lcd.setCursor(11, 0);
58 sendCommandSHT(humidityCommand, dataPin, clockPin);
59 waitForResultSHT(dataPin);
60 val = getData16SHT(dataPin, clockPin);
61 skipCrcSHT(dataPin, clockPin);
62 humidity = -4.0 + 0.0405 * val + -0.0000028 * val * val;
63 lcd.print(humidity, 0); //whole number only.
64 lcd.write(B00100101);
65
66 lcd.setCursor(4, 1);
67 //lcd.print("Atmosfera: ");
68 lcd.print(pressure, 0); //display 4 decimal places
69 lcd.print(" Pa");
70
71 lcd.setCursor(1, 0);
72 sendCommandSHT(temperatureCommand, dataPin, clockPin);
73 waitForResultSHT(dataPin);
74 val = getData16SHT(dataPin, clockPin);
75 skipCrcSHT(dataPin, clockPin);
76 temp = (float)val * 0.01 - 40;
77 lcd.print(temp, 1);
78 lcd.write(B11011111);
79 lcd.print("C");
80
81 delay(1000);
82 }
83
84 // Funções BMP085
85
86 // Stores all of the bmp085s calibration values into global variables
87 // Calibration values are required to calculate temp and pressure
88 // This function should be called at the beginning of the program
89 void bmp085Calibration()
90 {
91 ac1 = bmp085ReadInt(0xAA);
92 ac2 = bmp085ReadInt(0xAC);
93 ac3 = bmp085ReadInt(0xAE);
94 ac4 = bmp085ReadInt(0xB0);
95 ac5 = bmp085ReadInt(0xB2);
96 ac6 = bmp085ReadInt(0xB4);
97 b1 = bmp085ReadInt(0xB6);
98 b2 = bmp085ReadInt(0xB8);
99 mb = bmp085ReadInt(0xBA);
100 mc = bmp085ReadInt(0xBC);
101 md = bmp085ReadInt(0xBE);
102 }
103
104 // Calculate temperature in deg C
105 float bmp085GetTemperature(unsigned int ut){
106 long x1, x2;
107
108 x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
109 x2 = ((long)mc << 11)/(x1 + md);
110 b5 = x1 + x2;
111
112 float temp = ((b5 + 8)>>4);
113 temp = temp /10;
114
115 return temp;
116 }
117
118 // Calculate pressure given up
119 // calibration values must be known
120 // b5 is also required so bmp085GetTemperature(...) must be called first.
121 // Value returned will be pressure in units of Pa.
122 long bmp085GetPressure(unsigned long up){
123 long x1, x2, x3, b3, b6, p;
124 unsigned long b4, b7;
125
126 b6 = b5 - 4000;
127 // Calculate B3
128 x1 = (b2 * (b6 * b6)>>12)>>11;
129 x2 = (ac2 * b6)>>11;
130 x3 = x1 + x2;
131 b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
132
133 // Calculate B4
134 x1 = (ac3 * b6)>>13;
135 x2 = (b1 * ((b6 * b6)>>12))>>16;
136 x3 = ((x1 + x2) + 2)>>2;
137 b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
138
139 b7 = ((unsigned long)(up - b3) * (50000>>OSS));
140 if (b7 < 0x80000000)
141 p = (b7<<1)/b4;
142 else
143 p = (b7/b4)<<1;
144
145 x1 = (p>>8) * (p>>8);
146 x1 = (x1 * 3038)>>16;
147 x2 = (-7357 * p)>>16;
148 p += (x1 + x2 + 3791)>>4;
149
150 long temp = p;
151 return temp;
152 }
153
154 // Read 1 byte from the BMP085 at 'address'
155 char bmp085Read(unsigned char address)
156 {
157 unsigned char data;
158
159 Wire.beginTransmission(BMP085_ADDRESS);
160 Wire.write(address);
161 Wire.endTransmission();
162
163 Wire.requestFrom(BMP085_ADDRESS, 1);
164 while(!Wire.available())
165 ;
166
167 return Wire.read();
168 }
169
170 // Read 2 bytes from the BMP085
171 // First byte will be from 'address'
172 // Second byte will be from 'address'+1
173 int bmp085ReadInt(unsigned char address)
174 {
175 unsigned char msb, lsb;
176
177 Wire.beginTransmission(BMP085_ADDRESS);
178 Wire.write(address);
179 Wire.endTransmission();
180
181 Wire.requestFrom(BMP085_ADDRESS, 2);
182 while(Wire.available()<2)
183 ;
184 msb = Wire.read();
185 lsb = Wire.read();
186
187 return (int) msb<<8 | lsb;
188 }
189
190 // Read the uncompensated temperature value
191 unsigned int bmp085ReadUT(){
192 unsigned int ut;
193
194 // Write 0x2E into Register 0xF4
195 // This requests a temperature reading
196 Wire.beginTransmission(BMP085_ADDRESS);
197 Wire.write(0xF4);
198 Wire.write(0x2E);
199 Wire.endTransmission();
200
201 // Wait at least 4.5ms
202 delay(5);
203
204 // Read two bytes from registers 0xF6 and 0xF7
205 ut = bmp085ReadInt(0xF6);
206 return ut;
207 }
208
209 // Read the uncompensated pressure value
210 unsigned long bmp085ReadUP(){
211
212 unsigned char msb, lsb, xlsb;
213 unsigned long up = 0;
214
215 // Write 0x34+(OSS<<6) into register 0xF4
216 // Request a pressure reading w/ oversampling setting
217 Wire.beginTransmission(BMP085_ADDRESS);
218 Wire.write(0xF4);
219 Wire.write(0x34 + (OSS<<6));
220 Wire.endTransmission();
221
222 // Wait for conversion, delay time dependent on OSS
223 delay(2 + (3<<OSS));
224
225 // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
226 msb = bmp085Read(0xF6);
227 lsb = bmp085Read(0xF7);
228 xlsb = bmp085Read(0xF8);
229
230 up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
231
232 return up;
233 }
234
235 void writeRegister(int deviceAddress, byte address, byte val) {
236 Wire.beginTransmission(deviceAddress); // start transmission to device
237 Wire.write(address); // send register address
238 Wire.write(val); // send value to write
239 Wire.endTransmission(); // end transmission
240 }
241
242 int readRegister(int deviceAddress, byte address){
243
244 int v;
245 Wire.beginTransmission(deviceAddress);
246 Wire.write(address); // register to read
247 Wire.endTransmission();
248
249 Wire.requestFrom(deviceAddress, 1); // read a byte
250
251 while(!Wire.available()) {
252 // waiting
253 }
254
255 v = Wire.read();
256 return v;
257 }
258
259 float calcAltitude(float pressure){
260
261 float A = pressure/101325;
262 float B = 1/5.25588;
263 float C = pow(A,B);
264 C = 1 - C;
265 C = C / 0.0000225577;
266
267 return C;
268 }
269
270 // Funções SHT15
271
272 void sendCommandSHT(int command, int dataPin, int clockPin){
273 int ack;
274
275 // transmission start
276 pinMode(dataPin, OUTPUT);
277 pinMode(clockPin, OUTPUT);
278 digitalWrite(dataPin, HIGH);
279 digitalWrite(clockPin, HIGH);
280 digitalWrite(dataPin, LOW);
281 digitalWrite(clockPin, LOW);
282 digitalWrite(clockPin, HIGH);
283 digitalWrite(dataPin, HIGH);
284 digitalWrite(clockPin, LOW);
285
286 // shift out the command (the 3 MSB are address and must be 000, the last 5 bits are the command)
287 shiftOut(dataPin, clockPin, MSBFIRST, command);
288
289 // verify we get the right ACK
290 digitalWrite(clockPin, HIGH);
291 pinMode(dataPin, INPUT);
292 ack = digitalRead(dataPin);
293 if (ack != LOW){
294 lcd.setCursor(0, 0);
295 lcd.print("ACK error 0");}
296 digitalWrite(clockPin, LOW);
297 ack = digitalRead(dataPin);
298 if (ack != HIGH){
299 lcd.setCursor(0, 0);
300 lcd.print("ACK error 1");}
301 }
302
303 void waitForResultSHT(int dataPin){
304 int ack;
305
306 pinMode(dataPin, INPUT);
307 for (int i = 0; i < 100; ++i)
308 {
309 delay(20);
310 ack = digitalRead(dataPin);
311 if (ack == LOW)
312 break;
313 }
314 if (ack == HIGH){
315 lcd.setCursor(0, 0);
316 lcd.print("ACK error 2");}
317 }
318
319 // get data from the SHTx sensor
320 int getData16SHT(int dataPin, int clockPin)
321 {
322 int val;
323
324 // get the MSB (most significant bits)
325 pinMode(dataPin, INPUT);
326 pinMode(clockPin, OUTPUT);
327 val = shiftIn(dataPin, clockPin, 8);
328 val *= 256;
329
330 // send the required ACK
331 pinMode(dataPin, OUTPUT);
332 digitalWrite(dataPin, HIGH);
333 digitalWrite(dataPin, LOW);
334 digitalWrite(clockPin, HIGH);
335 digitalWrite(clockPin, LOW);
336
337 // get the LSB (less significant bits)
338 pinMode(dataPin, INPUT);
339 val |= shiftIn(dataPin, clockPin, 8);
340 return val;
341 }
342
343 // skip CRC data from the SHTx sensor
344 void skipCrcSHT(int dataPin, int clockPin)
345 {
346 pinMode(dataPin, OUTPUT);
347 pinMode(clockPin, OUTPUT);
348 digitalWrite(dataPin, HIGH);
349 digitalWrite(clockPin, HIGH);
350 digitalWrite(clockPin, LOW);
351 }