Barometric pressure sensor with I2C does not output expected bit pattern

Dear all,

I am using a barometric pressure sensor with I2C interface.

I wrote this very simple sketch below to get it running.

And indeed I get two bytes returned from the sensor, but the format surprises me.
In the data sheet there is an example of two received bytes

Byte 1:
00101100
Byte 2:
11001101

and the manual states on page 9 of the datasheet
“Taking the last 14 bits of byte 1 and byte 2 the current 14bit digital pressure value is:…”

If I check my serial output, my received bits are:

Byte1:
100110
Byte 2:
1010010

As you can see, there are only 6 bits in the first byte, and 7 bits in the 2nd byte.

So obviously this does not add up to an expected total of 16 bits. I also did the calculation of pressure as stated in the data sheet, but I get 1035mbar pressure while the local weather station reports 1017mbar. So something is off here.

Ideas are much appreciated.

#include <Wire.h>
#define adr 40

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


void loop()
{
  Wire.beginTransmission(adr);
  Wire.requestFrom(adr, 2);
    byte p1 = Wire.read(); // receive a byte
    byte p2 = Wire.read();
    Wire.endTransmission();
    Serial.println(p1,BIN);
    Serial.println(p2,BIN);
delay(1000);
}

The english site :wink: : http://www.amsys.info/products/ams5915.htm

How did you connect the sensor to which Arduino board ? because it is a 3.3V sensor.
Don’t tell it’s good because it works, you have to convince me that you did it right 8)

When printing a BIN value, the zeros at the start are omitted.
Your values are : 0010 0110 and 0101 0010.
That is 0x26 0x52
Glue them together, and use the 14 lower bits makes : 9810 decimal

Your local wheater stations convert it to value to “what it should be” at sea level (zero height).
That means that you have to compensate it for every meter height you are at.

The Wire.requestFrom() is a complete I2C transaction on its own. You don’t need the Wire.beginTransmission() and not the Wire.endTransmission().

Steps to make it work:
1 ) tell me how you have connected it, where the pullup resistors are, and so on.
2 ) run the i2c_scanner ( http://playground.arduino.cc/Main/I2cScanner ) and let it run for a while to see if it is stable.
3 ) Do a Wire.requestFrom() and combine the bytes with word().
http://arduino.cc/en/Reference/WordCast

#include <Wire.h>
#define adr 40

void setup()
{
  Serial.begin(9600);
  Serial.println("\nStarted");
  Wire.begin();
}

void loop()
{
  byte buffer[4];
  
  int n = Wire.requestFrom (adr, 4);
  if (n == 4)
  {
    Wire.readBytes (buffer, 4);
    
    unsigned int rawB = word (buffer[0], buffer[1]);     // word(high,low)
    unsigned int rawT = word (buffer[2], buffer[3]);
  
    // note that the next bit operations works best with "unsigned int", not with "int"
    rawB &= 0x3FFF;    // Keep only the 14 lower bits
    rawT >>= 5 ;       // Use the 11 highest bits, shift them in position
  
    float baromic = (( (float) rawB - 1638.0 ) / ( 13107.0 / 10.0 ) ) - 5.0;
    float temperature = (( (float) rawT * 200.0 ) / 2048.0 ) - 50.0;
  
    Serial.print("rawB = ");
    Serial.print(rawB);
    Serial.print("  --> ");
    Serial.print(baromic, 3);
    Serial.println(" bar");
    Serial.print("rawT = ");
    Serial.print(rawT);
    Serial.print("  --> ");
    Serial.print(temperature);
    Serial.println(" C");
  }
  else
  {
    Serial.println ("Error, no sensor found");
  }
    
  delay(1000);
}

As you can see, I read all 4 bytes, and I use an array for that. The function Wire.readBytes() reads all 4 bytes at once in the array. The way the bits are handled and the formulas are from the datasheet. I checked if I got the same result as the datasheet and it was okay.

Your value of 9810 results into 1235 mbar ? Perhaps the sensor is not calibrated.
Can you get a BMP180 to compare the results ? They are calibrated in the factory and are very accurate.

Adafruit has also a library for it, so you don’t have to read the datasheet of the BMP180.

Hi,

thanks for you reply.

It is my first time using I2C, so thanks for clearing up the code. I'll give that a go.

I use a MOSFET circuit to do the level shifting between 5V and 3.3V based on a NXP add note

I'm clueless but not stupid, haha :wink:

The sensor should be calibrated and temperature compensated from factory and measure the absolute pressure against a vacuum that is separated from the atmosphere with a gas tight membrane.

I'll report back as soon as I changed the code and did some testing.

Cheers

Did you know that if you pay 1 dollar, someone will bring a level shifter with mosfets to your door for you ?

I use these 1 dollar level shifters : http://www.ebay.com/sch/i.html?_sop=15&_nkw=i2c+level&LH_BIN=1

This is a level shifter with mosfets : 4-channel I2C-safe Bi-directional Logic Level Converter [BSS138] : ID 757 : $3.95 : Adafruit Industries, Unique & fun DIY electronics and kits

This is also such a level shifter : https://www.sparkfun.com/products/12009

That level shifter needs pullup resistors on both sides (those modules have often 10k on both sides).
If you level shifter is a problem, you can lower the I2C speed: Wire.setClock ( 100000 ) ; // default 200000

Hi,

yes I do :slight_smile: I found the level shifter app note through adafruit. But I got the sensors in and thought I give it a go right away, just because I’m impatient and had the parts around anyway.

I use 10K pull-ups and N-Channel MOSFETS. For voltage conversion I use an LM317 with 330Ohm + a potentiometer to trim to 3.3V.

Because the sensor used only a few mA, I can run the whole thing from the Arduino 5V pin.

I attached a picture. There are two of the sensors on the picture, so the circuit is just duplicated. I only run one of them at the moment because they have the same I2C address. I’ll either have to bit bang another I2c bus or buy a chip that does the switching.

For pressure I do not need very high speeds, so I could also decrease the bus speed, but for the last couple minutes it seemed to work nice and stable.

I guess next step is to get in the lift and ride my sensor up and down and log the change in pressure :slight_smile:

A LM317 needs capacitors on both sides. You could remove the LM317, and use the 3.3V pin of the Arduino board.

I don't know if the mosfets that you use are good. Most mosfets turn on at 9V gate voltage, but a for a level shifter they need to turn on at 2V.

Hi,

For low currents you get away without capacitors on the LM317T.
And the device is pretty tolerant with 3…3.6V input voltage.

As it turns out, there was an error in the manufacturers data sheet in the equation to calculate the pressure. The lower calibrated pressure range was written to be 750mbar, but it is 700mbar.

They will correct this in the near future and now I am 2mbar away from the pressure reported by the local weather station. It seems as those 2mbar are a consistent offset, so probably a systematic error in calibration or something…

An error in the datasheet :o :o
Did you compensate for the height ?

I contacted the manufacturer and they got back to me, telling me that they found an error in the datasheet. So yes, those can be wrong sometimes.

I do not need to compensate for height.

The sensor I have (they do have different ones, relative and absolute in the product series) is an absolute one, so it measures pressure against a vacuum. Same principle as for all the sensors used for altimeters in GPS or other devices.

So the pressure you measure (good rhyme), is the current absolute pressure at your altitude. This should be equal to the barometric pressure reported by the weather station.

The accuracy of the sensor is dependent on the quality of the vacuum and of course AD conversion and factory linearisation etc.

I will use it not for weather related stuff, but for an application in gas sensing. Knowing temperature and pressure one can use the ideal gas law to calculate the number of moles of a gas in a given volume.

Very cool application.
The BMP085 and BMP180 are often used with Arduino, they also measure the absolute (baromic) pressure.

Do you live exactly at sea level ? having wet feet then ?
I live a few meters above sea level, and I have to compensate for the height. I even have to use different values for downstairs or upstairs in my house.

Every wheater station has the baromic value compensated for height, they really have.