This simple program read data from pressure sensor bmp085 and calculating the temperature and real pressure using integer math. The microcontroler is Microchip's DSPIC33FJ256MC710, but it may work with any other.
#include "./dspic33.h"
#INCLUDE <math.h>
#use delay(clock=20000000)
//#use rs232(UART1,baud=19200,parity=N,bits=8,stream=uart1)
#use i2c(Master,Fast,sda=PIN_G3,scl=PIN_G2)
#define LCD_RS_PIN PIN_D1////
#define LCD_RW_PIN PIN_D2
#define LCD_ENABLE_PIN PIN_D3 ////
#define LCD_DATA4 PIN_D12 ////
#define LCD_DATA5 PIN_D13 ////
#define LCD_DATA6 PIN_D4 ////
#define LCD_DATA7 PIN_D5
#include <LCD.C>
int oss=0; //oversampling 0-low current 1-standart, 2,3- precision
signed int32 UT ;
unsigned int32 UP;
signed int16 AC1,AC2,AC3;
unsigned int16 AC4,AC5,AC6;
signed int16 B1,B2,MB,MC,MD;
signed int32 X1,X2,B5,temperature,B6,X3,B3, pressure;
unsigned int32 B4,B7;
float altitude;
signed int16 bmp085_read(int reg_address);
void bmp085_write_control(int data);
void main()
{
lcd_init();
lcd_putc("\fDesigned by\n");
lcd_putc("Martin Nikiforov");
delay_ms(1000);
lcd_putc("\f");
AC1=bmp085_read(0xAA); // read parameters from bmp085's eeprom
AC2=bmp085_read(0xAC);
AC3=bmp085_read(0xAE);
AC4=bmp085_read(0xB0);
AC5=bmp085_read(0xB2);
AC6=bmp085_read(0xB4);
B1=bmp085_read(0xB6);
B2=bmp085_read(0xB8);
MB=bmp085_read(0xBA);
MC=bmp085_read(0xBC);
MD=bmp085_read(0xBE);
oss=3;//0-low current for more accuracy 1,2,3
while(true)
{
bmp085_write_control(0x2E); //0x2E set to measure temperature 4,5ms
delay_ms(5);
UT=(unsigned int16)bmp085_read(0xF6); //read 0xF6 register temperature
bmp085_write_control(0x34+(0x40*oss)); //0x34 - oss=0 set to measure pressure 4,5ms conv
//oss=1 the value must be 0x74 oss =2 0xb4 , oss=3 0xF4
delay_ms(7*(oss+1));
UP=(unsigned int16)bmp085_read(0xF6);//pressure
UP<<=8;
UP=(UP+(((unsigned int16)bmp085_read(0xF8))>>8))>>(8-oss);//XLSB extra precision byte
X1=((UT-AC6)*AC5)>>15;
X2=(((signed int32)MC)<<11)/(X1+MD);
B5=X1+X2;
temperature=(B5+8)>>4;
B6=B5-4000;
X1=(((signed int32)B2)*((B6*B6)/4096))/2048;
X2=(((signed int32)AC2)*B6)/2048;
X3=X1+X2;
B3=((((((signed int32)AC1)*4)+X3)*((int)pow(2,oss)))+2)/4;
X1=(((signed int32)AC3)*B6)/8192;
X2=(((signed int32)B1)*((B6*B6)/4096))/65536;
X3=((X1+X2)+2)/4;
B4=(((unsigned int32)AC4)*(unsigned int32)(X3+32768))>>15;
B7=(unsigned int32)(((unsigned int32)UP)-B3)*(50000>>oss);
if(B7<0x80000000){pressure=(B7<<1)/B4;}
else {pressure=(B7/B4)*2;}
X1=(pressure>>8)*(pressure>>8);
X1=(((unsigned int32)X1)*3038)/65536;
X2=(-7357*pressure)/65536;
pressure=pressure+(X1+X2+3791)/16;
altitude= 44330.0*(1.0-pow((pressure/102325.0),(1/5.255)));
//calculate altitude 102325.0 must be 101325.0 but where i live give me negative altitude
printf(lcd_putc,"\aT=%4.1gC P=%5.1g\nAltitude%6.1g m\n",temperature/10.0,pressure/100.0,altitude);
// screen refresh slowly when using \f
delay_ms(200);
}
}
signed int16 bmp085_read(int reg_address)
{
int msb,lsb;
int16 data=0;
i2c_start();
i2c_write(0b11101110); // Device address
i2c_write(reg_address); // Data to device
i2c_start(); // Restart
i2c_write(0b11101111); // to change data direction
msb=i2c_read(1); // Now read from slave
lsb=i2c_read(0);
i2c_stop();
data=msb;
data<<=8;
data=data|lsb;
return (data);
}
void bmp085_write_control(int data)
{
i2c_start();
i2c_write(0b11101110);// // Device address
i2c_write(0xF4); //control reg address
i2c_write(data); //write the data
i2c_stop();
}
Comments
Pedro (not verified)
22. March 2015 - 19:30
Permalink
Thank You
Thank you for your program.
my project does not work properly
but now perfect
Add new comment