Barómetro Altímetro Termómetro BMP085



Modulo sensor de presión y temperatura BMP085 de la firma BOSCH.
Este es un sensor de prestaciones hogareñas, ya que los límites de presión y temperatura son estándar como para una estación meteorológica.
La presión a medir va de 30kPa a 110kPa
La altura (por conversión) es de -500m a 9000m
Bueno son algunos datos, la realidad es que si se quiere ver en detalle pueden descargar el datasheet donde encontraran una extensa cantidad de datos sobre este sensor.
El protocolo de comunicación es I2C, en este caso se aprovecha el puerto I2C del microcontrolador de forma nativa.
En nuestro ejemplo se ha utilizado un display de LCD pero es posible usar cualquier otra interfase de visualización.
El diagrama de bloques del programa esta detallado en el Datasheet del sensor, para aquellos que no les gusta programar van a tener un poco de problemas ya que Bosch decidió utilizar 11 variables de calibración, que deben calcularse en tiempo real para lograr una representación de la presión.
De todas formas esta todo escrito en el datasheet, las variables, los cálculos, la forma de leer este sensor, los bytes a enviar para accederlo y demás.

Circuito:

Calibración:

Algoritmo y Cálculos:

Programa: 
Nótese que en la rutina de inicialización las variables que poseen una x minúscula son los resultados de los cálculos que se piden en el cuadro de arriba, pero los mismos están directamente como constante, esto se debe a que el hardware del microcontrolador utilizado queda corto para la cantidad de memoria necesaria para realizar todos los cálculos, por ende se han puesto solo los resultados, esto quita exactitud.
Si se utiliza un microcontrolador más potente sería recomendable utilizar los cálculos para que la exactitud sea óptima.


Para ampliar la exactitud debe reemplazar el bloque:

   xC3 = 0.00489*AC3;
   xC4 = 0.0000000306*AC4;
   xC5 = 0.000000191*AC5;
   xC6 = (float)AC6;
   xB1 = 0.0000238*B1;
   xMc = 0.0812*MC;
   xMd = (float)MD/160;  
   xX1 = (float)AC1;
   xX2 = 0.0195*AC2;
   xX3 = 0.000763*B2;  
   xY1 = xC4*32768;
   xY2 = xC4*xC3;
   xY3 = xC4*xB1;

por el bloque:

   xC3 = 160*pow(2,-15)*AC3;
   xC4 = pow(1,-3)*pow(2,-15)*AC4;
   xC5 = (pow(2,-15)/160)*AC5;
   xC6 = (float)AC6;
   xB1 = pow(160,2)*pow(2,-30)*B1;
   xMc = (pow(2,11)/25600)*MC;
   xMd = (float)MD/160; 
   xX1 = (float)AC1;
   xX2 = 160*pow(2,-13)*AC2;
   xX3 = pow(160,2)*pow(2,-25)*B2; 
   xY1 = xC4*pow(2,15);
   xY2 = xC4*xC3;
   xY3 = xC4*xB1;


y debe incluir la librería math.h, esto requiere de un microcontrolador mas potente.


#include <16F883.h>
#use delay(int=4000000)
#use i2c(master,sda=PIN_C4,scl=PIN_C3,FAST,FORCE_HW)
#include <lcd.c>
signed int16 AC1, AC2, AC3, B1, B2, MC, MD, MB;
int16 AC4, AC5, AC6;
float xC3, xC4, xB1, xC5, xC6, xMc, xMd, xX1, xX2;
float xY2, xY3, xS, xX3, xY1;

int8 DescargaByte_BMP085(int8 address){
   int8 datos;
   i2c_Start();
   i2c_write(0xEE);
   i2c_write(address);
   i2c_Start();
   i2c_write(0xEE|0x01);
   datos=i2c_read(0);
   i2c_Stop();
   return(datos);
}
int16 DescargaEntero_BMP085(int8 address){
   int16 ent;
   i2c_Start();
   i2c_write(0xEE);
   i2c_write(address);
   i2c_Start();
   i2c_write(0xEE|0x01);
   ent=make16(i2c_read(),i2c_read(0));
   i2c_Stop();
   return(ent);
}
void inicializa_BMP085(){
   AC1 = DescargaEntero_BMP085(0xAA);
   AC2 = DescargaEntero_BMP085(0xAC);
   AC3 = DescargaEntero_BMP085(0xAE);
   AC4 = DescargaEntero_BMP085(0xB0);
   AC5 = DescargaEntero_BMP085(0xB2);
   AC6 = DescargaEntero_BMP085(0xB4);
   B1  = DescargaEntero_BMP085(0xB6);
   B2  = DescargaEntero_BMP085(0xB8);
   MB  = DescargaEntero_BMP085(0xBA);
   MC  = DescargaEntero_BMP085(0xBC);
   MD  = DescargaEntero_BMP085(0xBE);
   xC3 = 0.00489*AC3;
   xC4 = 0.0000000306*AC4;
   xC5 = 0.000000191*AC5;
   xC6 = (float)AC6;
   xB1 = 0.0000238*B1;
   xMc = 0.0812*MC;
   xMd = (float)MD/160;  
   xX1 = (float)AC1;
   xX2 = 0.0195*AC2;
   xX3 = 0.000763*B2;  
   xY1 = xC4*32768;
   xY2 = xC4*xC3;
   xY3 = xC4*xB1;
} 
int16 DescargaTemp_BMP085(){
   i2c_Start();
   i2c_write(0xEE);
   i2c_write(0xF4);
   i2c_write(0x2E);
   i2c_Stop();
   delay_ms(5);
   return((float)DescargaEntero_BMP085(0xF6));
}
int32 DescargaPres_BMP085(){
   i2c_Start();
   i2c_write(0xEE);
   i2c_write(0xF4);
   i2c_write(0x34+(3<<6));
   i2c_Stop(); 
   delay_ms(26);
   return((256*DescargaByte_BMP085(0xF6))+
               DescargaByte_BMP085(0xF7)+
          (DescargaByte_BMP085(0xF8)/256));
}
float LeeTemperatura_BMP085(float tempeAux){
   float Conversor, Temperatura;
   Conversor=xC5*(tempeAux-xC6);
   Temperatura=Conversor+(xMc/(Conversor+xMd));
   xS=Temperatura-25;
   return(Temperatura);
}  
float LeePresion_BMP085(float presAux){
   float auxA, auxB, auxC;
   float Presion;
   auxA=xX3*xS*xS+xX2*xS+xX1;
   auxB=xY3*xS*xS+xY2*xS+xY1;
   auxC=((float)presAux-auxA)/auxB;
   Presion=0.0000045*auxC*auxC+0.994*auxC+2.37;
   Presion+=4.58;
   return(Presion);
}
void main(){
   lcd_init();
   inicializa_BMP085();
   while(true){
      lcd_gotoxy(1,1);
      printf(lcd_putc,"T[c]: %.1g  \n",LeeTemperatura_BMP085(DescargaTemp_BMP085()));
      lcd_gotoxy(1,2);
      printf(lcd_putc,"P[mBar]: %0.2g  \n",LeePresion_BMP085(DescargaPres_BMP085()));
      delay_ms(500);
   }
}

12 comentarios:

  1. hello, so thanks you for your sharing. but i'm just beginning to learn about ccs, can you answer to me for code "lcd.c"?

    ResponderBorrar
    Respuestas
    1. Hello, the libraries that are included in the program include default within the CCS compiler files, I use the IDE PCWH with CCS compiler, it has the libraries. (The libraries can not include in the post because they own CCS).
      Greetings.

      Borrar
    2. I would like to thank u, my English is not too good.Hopefully u can understand. I wanna ask your help a bit.How to make it active between pic and lcd or how to show up between pic and lcd?I cant handle at the temperature at decimal number.
      This is code which based on ur assignment. Because i have learnt ccs for a short time, can you help me to correct it at decimal point/part

      #define RS RE0
      #define RW RE1
      #define E RE2
      #define LCD PORTD
      int32 T;
      Int T_C,T_DV;
      Int T_TP;

      void GDK()
      {
      RS = 0;
      RW = 0;
      E = 1;
      E = 0;
      delay_ms(1);
      }
      void GHT()
      {
      RS = 1;
      RW = 0;
      E = 1;
      E = 0;
      delay_ms(1);
      }

      void doc_nhietdo()
      {
      T=LeeTemperatura_BMP085(DescargaTemp_BMP085());
      T_C=T/10;
      T_DV=T%10;
      T_TP=(T*10)%10;
      }
      void main(){
      //lcd_init();
      inicializa_BMP085();
      TRISE=0;
      TRISD=0;

      LCD = 0x01;
      GDK();
      LCD = 0x38;
      GDK();
      LCD = 0x0C;
      GDK();
      LCD = 0x84;
      GDK();

      LCD = 'T'; GHT();
      LCD = ' '; GHT();
      LCD = '='; GHT();
      LCD = ' '; GHT();
      while(true){
      doc_nhietdo();
      LCD = 0x88; GDK();
      LCD = T_C+48; GHT();
      LCD = T_DV+48; GHT();
      LCD = '.'; GHT();
      LCD = T_TP+48; GHT();
      delay_ms(500);
      }
      }

      Borrar
    3. this is link contains my problems and photos of electric circuit. I use pic 16f877a i look forward for getting your kindly help

      http://imgur.com/8lcce9C

      Borrar
    4. Hello , Thanks ! ,
      Here https://gist.github.com/ARod/1782270 I leave a place site LCD.C download the library , including library can the manipulate the comma or floating point simply site as seen in the schedule to this post , sin need to handle each character separately.
      Greetings.
      PD: my english is bad....

      Borrar
    5. Thanks for your sharing. I have finished the decimal part of the temperature . Now i would like to learn more about how to compute the height and pressure. Can you give me an exercise as an example ?

      i wanna ask a bit that where may i can learn algorithm communication with bmp085 ? how to get it
      xC3 = 160*pow(2,-15)*AC3;
      xC4 = pow(1,-3)*pow(2,-15)*AC4;
      xC5 = (pow(2,-15)/160)*AC5;
      xC6 = (float)AC6;
      xB1 = pow(160,2)*pow(2,-30)*B1;
      ...
      ? Im looking forward to hearing from you soon. Thanks a lot.

      Borrar
    6. Hello , the calculations are in datasheet https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf Provides Bosch sheet , on page 14 of this sheet you can see the exponential calculation That Suggests to Calculate the height function of the atmospheric pressure .
      Greetings.

      Borrar
    7. hello S.C
      thanks you very much one more time.
      i will seek more information about datasheet, it would be great to get your kindly support if I meet any difficultis. But, can you please give me an example or a sample code about how to compute the height and pressure of this bmp?

      Borrar
    8. Hello , the formula is:
      float altitude, pressure
      altitude = 44330 * (1 - pow((pressure/1013.25),0.19))
      is the altitude in meters.

      Borrar
    9. ok thanks you very much :D
      one more time :D

      Borrar
  2. Este comentario ha sido eliminado por el autor.

    ResponderBorrar