Pages: [1]   Go Down
Author Topic: BMP085 not reading correctly  (Read 3202 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I'm trying to get a BMP085 working with an UNO R3 using the code below. The BMP085 is wired up as per instructions with 3.3V and all I'm repeatedly getting back is this:

Temperature: 203.00deg C
Pressure: 322188 Pa
Standard Atmosphere: 3.1797
Altitude: -10914.12 M

....which is obviously wrong. I was under the impression these modules worked straight out of the box so can anyone suggest what is going wrong. I've run the SDA and SCL lines through a logic level converter and nothing seems to change either the temp or pressure readings.


Code:
//Arduino 1.0+ Only
//Arduino 1.0+ Only

/*Based largely on code by  Jim Lindblom

 Get pressure, altitude, and temperature from the BMP085.
 Serial.print it out at 9600 baud to serial monitor.
 */

#include <Wire.h>

#define BMP085_ADDRESS 0x77  // I2C address of BMP085

const unsigned char OSS = 0;  // Oversampling Setting

// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;

void setup(){
  Serial.begin(9600);
  Wire.begin();

  bmp085Calibration();
}

void loop()
{
  float temperature = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
  float pressure = bmp085GetPressure(bmp085ReadUP());
  float atm = pressure / 101325; // "standard atmosphere"
  float altitude = calcAltitude(pressure); //Uncompensated caculation - in Meters

  Serial.print("Temperature: ");
  Serial.print(temperature, 2); //display 2 decimal places
  Serial.println("deg C");

  Serial.print("Pressure: ");
  Serial.print(pressure, 0); //whole number only.
  Serial.println(" Pa");

  Serial.print("Standard Atmosphere: ");
  Serial.println(atm, 4); //display 4 decimal places

  Serial.print("Altitude: ");
  Serial.print(altitude, 2); //display 2 decimal places
  Serial.println(" M");

  Serial.println();//line break

  delay(1000); //wait a second and get values again.
}

// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

// Calculate temperature in deg C
float bmp085GetTemperature(unsigned int ut){
  long x1, x2;

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

  float temp = ((b5 + 8)>>4);
  temp = temp /10;

  return temp;
}

// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  // Calculate B4
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;

  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;

  long temp = p;
  return temp;
}

// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available())
    ;

  return Wire.read();
}

// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2)
    ;
  msb = Wire.read();
  lsb = Wire.read();

  return (int) msb<<8 | lsb;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
  unsigned int ut;

  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();

  // Wait at least 4.5ms
  delay(5);

  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){

  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();

  // Wait for conversion, delay time dependent on OSS
  delay(2 + (3<<OSS));

  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);

  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

  return up;
}

void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress); // start transmission to device
  Wire.write(address);       // send register address
  Wire.write(val);         // send value to write
  Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address){

  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address); // register to read
  Wire.endTransmission();

  Wire.requestFrom(deviceAddress, 1); // read a byte

  while(!Wire.available()) {
    // waiting
  }

  v = Wire.read();
  return v;
}

float calcAltitude(float pressure){

  float A = pressure/101325;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 - C;
  C = C /0.0000225577;

  return C;
}

« Last Edit: October 13, 2012, 04:27:49 am by alext1772 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've also tried the code below from the Sparkfun website link and I get the following:

Reading Calibration Data
AC1: 8540
AC2: -1204
AC3: -14375
AC4: 34203
AC5: 24771
AC6: 21732
B1: 5498
B2: 5498
MB: -32768
MC: -11075
MD: 2432
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
Temperature: -926 Pressure: 84824
.............

Code:
#include <Wire.h>

// From the datasheet the BMP module address LSB distinguishes
// between read (1) and write (0) operations, corresponding to
// address 0xEF (read) and 0xEE (write).
// shift the address 1 bit right (0xEF or 0xEE), the Wire library only needs the 7
// most significant bits for the address 0xEF >> 1 = 0x77
// 0xEE >> 1 = 0x77

int I2C_ADDRESS = 0x77;  // sensor address

// oversampling setting
// 0 = ultra low power
// 1 = standard
// 2 = high
// 3 = ultra high resolution
const unsigned char oversampling_setting = 3; //oversampling for measurement
const unsigned char pressure_conversiontime[4] = {
  5, 8, 14, 26 };  // delays for oversampling settings 0, 1, 2 and 3   

// sensor registers from the BOSCH BMP085 datasheet
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

// variables to keep the values
int temperature = 0;
long pressure = 0;


void setup()

  Serial.begin(9600); 
  Wire.begin();
  getCalibrationData();
}

void loop()
{
  readSensor();
  Serial.print("Temperature: ");
  Serial.print(temperature,DEC);
  Serial.print(" Pressure: ");
  Serial.println(pressure,DEC);
  delay(100);
}


// Below there are the utility functions to get data from the sensor.

// read temperature and pressure from sensor
void readSensor() {
  int  ut= readUT();
  long up = readUP();
  long x1, x2, x3, b3, b5, b6, p;
  unsigned long b4, b7;

  //calculate true temperature
  x1 = ((long)ut - ac6) * ac5 >> 15;
  x2 = ((long) mc << 11) / (x1 + md);
  b5 = x1 + x2;
  temperature = (b5 + 8) >> 4;

  //calculate true pressure
  b6 = b5 - 4000;
  x1 = (b2 * (b6 * b6 >> 12)) >> 11;
  x2 = ac2 * b6 >> 11;
  x3 = x1 + x2;
  b3 = (((int32_t) ac1 * 4 + x3)<<oversampling_setting + 2) >> 2;
  x1 = ac3 * b6 >> 13;
  x2 = (b1 * (b6 * b6 >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
  b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting);
  p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;

  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  pressure = p + ((x1 + x2 + 3791) >> 4);
}

// read uncompensated temperature value
unsigned int readUT() {
  writeRegister(0xf4,0x2e);
  delay(5); // the datasheet suggests 4.5 ms
  return readIntRegister(0xf6);
}

// read uncompensated pressure value
long readUP() {
  writeRegister(0xf4,0x34+(oversampling_setting<<6));
  delay(pressure_conversiontime[oversampling_setting]);

  unsigned char msb, lsb, xlsb;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(0xf6);  // register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 3); // request three bytes
  while(!Wire.available()); // wait until data available
  msb = Wire.read();
  while(!Wire.available()); // wait until data available
  lsb |= Wire.read();
  while(!Wire.available()); // wait until data available
  xlsb |= Wire.read();
  return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting);
}

void  getCalibrationData() {
  Serial.println("Reading Calibration Data");
  ac1 = readIntRegister(0xAA);
  Serial.print("AC1: ");
  Serial.println(ac1,DEC);
  ac2 = readIntRegister(0xAC);
  Serial.print("AC2: ");
  Serial.println(ac2,DEC);
  ac3 = readIntRegister(0xAE);
  Serial.print("AC3: ");
  Serial.println(ac3,DEC);
  ac4 = readIntRegister(0xB0);
  Serial.print("AC4: ");
  Serial.println(ac4,DEC);
  ac5 = readIntRegister(0xB2);
  Serial.print("AC5: ");
  Serial.println(ac5,DEC);
  ac6 = readIntRegister(0xB4);
  Serial.print("AC6: ");
  Serial.println(ac6,DEC);
  b1 = readIntRegister(0xB6);
  Serial.print("B1: ");
  Serial.println(b1,DEC);
  b2 = readIntRegister(0xB8);
  Serial.print("B2: ");
  Serial.println(b1,DEC);
  mb = readIntRegister(0xBA);
  Serial.print("MB: ");
  Serial.println(mb,DEC);
  mc = readIntRegister(0xBC);
  Serial.print("MC: ");
  Serial.println(mc,DEC);
  md = readIntRegister(0xBE);
  Serial.print("MD: ");
  Serial.println(md,DEC);
}

void writeRegister(unsigned char r, unsigned char v)
{
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);
  Wire.write(v);
  Wire.endTransmission();
}

// read a 16 bit register
int readIntRegister(unsigned char r)
{
  unsigned char msb, lsb;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);  // register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 2); // request two bytes
  while(!Wire.available()); // wait until data available
  msb = Wire.read();
  while(!Wire.available()); // wait until data available
  lsb = Wire.read();
  return (((int)msb<<8) | ((int)lsb));
}

// read an 8 bit register
/*
unsigned char readRegister(unsigned char r)
{
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(r);  // register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1); // request a byte
  while(!Wire.available()); // wait until data available
  v = Wire.receive();
  return v;
}
*/
Logged

0
Offline Offline
Shannon Member
****
Karma: 214
Posts: 12406
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I'm trying to get a BMP085 working with an UNO R3 using the code below. The BMP085 is wired up as per instructions with 3.3V and all I'm repeatedly getting back is this:

What instructions?
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The ones which tell you to provide 3.3V to the VCC pin. I've connected SDA and SCL both through a logic level converter as I do for the TMP102 and directly to the Arduino and neither method makes any difference to the result. EOC and XCLR are left floating.
Logged

0
Offline Offline
Shannon Member
****
Karma: 214
Posts: 12406
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The ones which tell you to provide 3.3V to the VCC pin. I've connected SDA and SCL both through a logic level converter as I do for the TMP102 and directly to the Arduino and neither method makes any difference to the result. EOC and XCLR are left floating.

Tell us much more about that level converter.  When connected to the Arduino directly what are you doing for pull-up resistors?

Show us the schematic, basically...
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are you using the breakout board or the stand-alone sensor? I'm using the breakout board and there you just need to install the lib, and use the commands bmp.readAltitude(), bmp.readPressure(),...

Make sure SDA and SCL are connected to the correct arduino pins (For uno these are analog 4 and analog5).

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the Sparkfun breakout board. Double checked SDA and SCL are correct way round which they are. Wondering now if the library I've got for it doesn't work properly with this board. Please can you point me to the source of the library you used? I don't recognise the .readAltitude and .readPressure commands from the library I've got....

Thanks.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I guess you are using this breakout board? https://www.sparkfun.com/products/9694
 It's the same one like i am using, and i am using adafruits library that you can find here..

https://github.com/adafruit/Adafruit-BMP085-Library

If you install the lib and open an example that comes with it, you will see the code you can use to read out pressure, altitude, ...

Greetz
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, that's the board. I've downloaded the Adafruit library and I'll give it a go tonight. Looking at the code it's so much simpler than the library I was using before. Hopefully problem solved, will report back.

Thanks
Logged

Pages: [1]   Go Up
Jump to: