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 }

prototipo_sht15_bmp085.png (209.8 kB) Lucas Leal, 14/03/2013 20:36