Go Down

Topic: Using 2 BMP085 on I2C (Read 2 times) previous topic - next topic

Krodal

I'm not sure what you mean, but all calibration values are stored in the class (see BMP085.h, the private variables). If you create two classes, they will never overwrite each other. You can use any of the two classes at any time.

Thames

Thanks for your help Krodal, but unfortunately I had the same problem with the new code that I had with the old.  Fortunately, I figured out what was wrong.

In case anyone else has this problem, I think I've found the solution.  Using the calibration values from one sensor to calculate the values for both sensors was one of my problems, so I modified the Sparkfun code to cycle through the sensors and store each variable in an array.
Code: [Select]
#include <Wire.h>

#define BMP085_ADDRESS 0x77  // I2C address of BMP085


int count=0;

const unsigned char OSS = 0;  // Oversampling Setting

// Calibration values
const int numBMP085=3;      //Number of BMP085 sensors being used, used to make array sizes
int BMPpin[numBMP085];

int ac1[numBMP085];
int ac2[numBMP085];
int ac3[numBMP085];
unsigned int ac4[numBMP085];
unsigned int ac5[numBMP085];
unsigned int ac6[numBMP085];
int b1[numBMP085];
int b2[numBMP085];
int mb[numBMP085];
int mc[numBMP085];
int md[numBMP085];

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

short temperature;
long pressure;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
    delay(1000);
   
for(int i=0;i<numBMP085;i++){

   BMPpin[i]=12-i;                    //Set a pin number for each sensor, first is 13, 2nd is 12, etc
   pinMode(BMPpin[i],OUTPUT);         //Use BMPpin[0] to HIGH to turn on sensor 1, attached to pin 13
   //Serial.println(BMPpin[i]);
}                                     
   
  for(int i=0;i<numBMP085;i++){
     
    Serial.print("Calibrate sensor #");
    Serial.println(i);
   
    useSensor(i);
   

    bmp085Calibration(i);                //Calibrate the sensor for pin i
  }   

    delay(500);



 
}

void loop()
{
 
if(count==numBMP085){
  count=0;
}

  int sensor=count;                      //The sensor being used will be determined by loop count,
                                         //reset to 0 at numBMP085
  useSensor(sensor);
  Serial.print("Sensor #");
  Serial.print(sensor);
  Serial.print(": ");
 
 
  delay(5);
  count++;
 
  temperature = bmp085GetTemperature(bmp085ReadUT(),sensor);
  pressure = bmp085GetPressure(bmp085ReadUP(),sensor);
  Serial.print("Temperature: ");
  Serial.print(temperature/10.,1);
  Serial.print(" deg C");
  Serial.print("\tPressure: ");
  Serial.print(pressure, DEC);
  Serial.println(" Pa");
//  Serial.println();
// delay(1000);
}

// 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(int sensorNum)
{
  ac1[sensorNum] = bmp085ReadInt(0xAA);
  ac2[sensorNum] = bmp085ReadInt(0xAC);
  ac3[sensorNum] = bmp085ReadInt(0xAE);
  ac4[sensorNum] = bmp085ReadInt(0xB0);
  ac5[sensorNum] = bmp085ReadInt(0xB2);
  ac6[sensorNum] = bmp085ReadInt(0xB4);
  b1[sensorNum] = bmp085ReadInt(0xB6);
  b2[sensorNum] = bmp085ReadInt(0xB8);
  mb[sensorNum] = bmp085ReadInt(0xBA);
  mc[sensorNum] = bmp085ReadInt(0xBC);
  md[sensorNum] = bmp085ReadInt(0xBE);
/*Serial.print("Sensor number ");
  Serial.println(sensorNum);
  Serial.println(ac1[sensorNum]);
  Serial.println(ac2[sensorNum]);
  Serial.println(ac3[sensorNum]);
  Serial.println(ac4[sensorNum]);
  Serial.println(ac5[sensorNum]);
  Serial.println(ac6[sensorNum]);
  Serial.println(b1[sensorNum]);
  Serial.println(b2[sensorNum]);
  Serial.println(mb[sensorNum]);
  Serial.println(mc[sensorNum]);
  Serial.println(md[sensorNum]);*/
}

// Calculate temperature given ut.
// Value returned will be in units of 0.1 deg C
short bmp085GetTemperature(unsigned int ut, int sensor)
{
  long x1, x2;
 
  x1 = (((long)ut - (long)ac6[sensor])*(long)ac5[sensor]) >> 15;
  x2 = ((long)mc[sensor] << 11)/(x1 + md[sensor]);
  b5 = x1 + x2;

  return ((b5 + 8)>>4); 
}

// 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,int sensor)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
 
  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2[sensor] * (b6 * b6)>>12)>>11;
  x2 = (ac2[sensor] * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1[sensor])*4 + x3)<<OSS) + 2)>>2;
 
  // Calculate B4
  x1 = (ac3[sensor] * b6)>>13;
  x2 = (b1[sensor] * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4[sensor] * (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;
 
  return p;
}

// 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){
  Serial.print(Wire.available()); 
  delay(100); }
;
  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)
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);
 
  // Wait for data to become available
  while(Wire.available() < 3)
    ;
  msb = Wire.read();
  lsb = Wire.read();
  xlsb = Wire.read();
 
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
 
  return up;
}

void useSensor(int sensorNum)
{
 

for(int i=0;i<numBMP085;i++){            //Set all pins to low, turn off all sensors
      digitalWrite(BMPpin[i],LOW);
    }
   
digitalWrite(BMPpin[sensorNum],HIGH);    //Set the pin to be calibrated to high
  delay(1);                              //<-- DON'T REMOVE THIS
                                         //I don't know why, but without this the pressures are too high

}


The other issue I had was that the pressures and temperatures for both sensors would read way too high when I tried switching back and forth between the two sensors, because the XCLR pin wasn't reading as ground even when it should.  The pins for SDA and SCL are set to 5V, and the BMP085 says to have all pins at 3.3V.  Dropping these pins down to 3.3V with this logic level converter http://www.sparkfun.com/products/8745 fixed the problem, although you can also turn off the internal pull up resistors to achieve the same effect.  I also used a voltage divider to make the voltage at the XCLR pin also be 3.3V.

Go Up