Pressure Sensors MS5611 MS5803

Hi,
I have been trying to get realistic results from 2 pressure sensors, the MS5611 and the MS5803. I have had no problem with the Bosch BMP085 which works fine.
(http://www.meas-spec.com/downloads/ms5611-01ba01.pdf
http://www.meas-spec.com/downloads/MS5803-01BA.pdf)
I have tried two breakout boards for the 5611 and 1 for the 5803.
I am getting incorrect results on all 3 boards so I must be doing something fundamentally wrong.
I am using them both in I2C mode.
The pressure and temperature calculations are the same for both boards but the second order corrections differ and have not been used.
The results I get are:

Actual TEMP= 1908 (=19.08C) Actual PRESSURE= 6

RAW Temp D2= 8004242 RAW Pressure D1= 8028974

dT= 7955602

C0/1= 53520
C1/2= 53270
C2/3= 34137
C3/4= 31191
C4/5= 31166
C5/6= 29055

C6/7= 64770
C7/8= 8826

The temperature does not change when I touch the board unlike the Bosch which is very responsive. So perhaps this says what I am doing wrong.
In the temperature calculation I get a value of 7955602 for dT when the example / typical value should be 2366. So as dT=D2-C5*2^8 the error must lie in either D2 or C5. For both sensors the example value for D2 is 8569150 / 8387300 respectively. I obtain 7955602 here for the 5611 so the error is either in C5 or D2. D2 is measured at 8004242 and C4 is 31191 which when multiplied by 256 gives 7984896 and a difference 19346 still far from the typical value of 2366 but far from 7955602 from the serial.print D2 which I get.
Given that I cannot have 3 faulty sensors unless I over cooked them I am lost, please help.

#include <Wire.h>
#define ADDRESS 0x77 //0x76

uint32_t D1 = 0;
uint32_t D2 = 0;
int32_t dT = 0;
int32_t TEMP = 0;
int64_t OFF = 0; 
int64_t SENS = 0; 
int32_t P = 0;
uint16_t C[7];

void setup() {
// Disable internal pullups, 10Kohms are on the breakout
 PORTC |= (1 << 4);
 PORTC |= (1 << 5);

  Wire.begin();
  Serial.begin(9600); //9600 changed 'cos of timing?
  delay(100);
  initial(ADDRESS);

}

void loop()
{
  D1 = getVal(ADDRESS, 0x48); // Pressure raw
  D2 = getVal(ADDRESS, 0x58);// Temperature raw

  dT = D2 - (C[4]*256);
  TEMP = 2000 + ((dT * C[5])/8388608);
  OFF  = ((C[1])<<16) + ((C[3] * dT) >> 7);
  SENS = ((C[0])<<15) + ((C[2] * dT) >> 8);
  P = ((D1 * SENS/2097152 - OFF)/32768)/100;


  Serial.print("     Actual TEMP= ");
  Serial.print(TEMP);
  Serial.print("      Actual PRESSURE= ");
  Serial.print(P);

  Serial.println();  
  Serial.print(" RAW Temp D2=  ");
  Serial.print(D2);
  Serial.print(" RAW Pressure D1=  ");
  Serial.println(D1);
  Serial.println();

  Serial.print(" dT=  ");
  Serial.println(dT);
  Serial.println();
  Serial.print(" C0/1=  ");
  Serial.println(C[0]);
  Serial.print(" C1/2=  ");
  Serial.println(C[1]);
  Serial.print(" C2/3=  ");
  Serial.println(C[2]); 
  Serial.print(" C3/4=  ");
  Serial.println(C[3]); 
  Serial.print(" C4/5=  ");
  Serial.println(C[4]); 
  Serial.print(" C5/6=  ");
  Serial.println(C[5]); 
  Serial.print(" C6/7=  ");
  Serial.println(C[6]); 
  Serial.print(" C7/8=  ");
  Serial.println(C[7]);
  Serial.println();

  delay(1000

    );
}

long getVal(int address, byte code)
{
  unsigned long ret = 0;
  Wire.beginTransmission(address);
  Wire.write(code);
  Wire.endTransmission();
  delay(10);
  // start read sequence
  Wire.beginTransmission(address);
  Wire.write((byte) 0x00);
  Wire.endTransmission();
  Wire.beginTransmission(address);
  Wire.requestFrom(address, (int)3);
  if(Wire.available()) {
    //    ret = ((uint32_t)Wire.read() << 16) | ((uint32_t)Wire.read() << 8) | Wire.read();
    ret = Wire.read() * 65536 + Wire.read() * 256 + Wire.read();
  }
  else {
    ret = -1;
  }
  Wire.endTransmission();
  return ret;
}

void initial(uint8_t address)
{

  Serial.println();
  Serial.println("PROM COEFFICIENTS ivan");

  Wire.beginTransmission(address);
  Wire.write(0x1E); // reset
  Wire.endTransmission();
  delay(10);


  for (int i=0; i<7  ; i++) {

    Wire.beginTransmission(address);
    Wire.write(0xA2 + (i * 2));
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.requestFrom(address, (uint8_t) 6);
    delay(1);
    if(Wire.available()) {

      C[i] = Wire.read() *256 + Wire.read();
    }
    else {
      Serial.println("Error reading PROM 1"); // error reading the PROM or communicating with the device
    }
    Serial.println(C[i]);
  }
  Serial.println();
}

Circuit? datasheet for the breakout boards?

Please modify the post, select the code and press the # button to get the code proper tagged. Looks so much better, thank you.

Hi and thanks,
The MS5611 was supplied by Drotek
http://www.drotek.fr/shop/en/44-ms5611-pressure-barometric-board.html
It has on board resistors and I disabled the ones on the Uno in the sketch.
MS5611 SDA SCL / A5 clock and A4 data on Uno CSB high or low depending on the address I use.
With the MS5803 1 and 7 to ground via a 10K resistor and 100nF cap across 2 and 5 as on p14 of the datasheet.
On the MS5803 the same except pin 6 PS is high for I2C.
I was wondering as I am using 3.3V directly from the Uno then the frequency is lower than at 5V, does this effect anything? as in increasing any delays in the code?
best

I modified your code a little bit but did no clean-up work.

It runs with my setup (same as yours) showing correct temperature and pressure readings.

Give it a try.

#include <Wire.h>
#define ADDRESS 0x77 //0x76

uint32_t D1 = 0;
uint32_t D2 = 0;
int64_t dT = 0;
int32_t TEMP = 0;
int64_t OFF = 0; 
int64_t SENS = 0; 
int32_t P = 0;
uint16_t C[7];

float Temperature;
float Pressure;


void setup() {
// Disable internal pullups, 10Kohms are on the breakout
 PORTC |= (1 << 4);
 PORTC |= (1 << 5);

  Wire.begin();
  Serial.begin(9600); //9600 changed 'cos of timing?
  delay(100);
  initial(ADDRESS);

}

void loop()
{
  D1 = getVal(ADDRESS, 0x48); // Pressure raw
  D2 = getVal(ADDRESS, 0x58);// Temperature raw

  dT   = D2 - ((uint32_t)C[5] << 8);
  OFF  = ((int64_t)C[2] << 16) + ((dT * C[4]) >> 7);
  SENS = ((int32_t)C[1] << 15) + ((dT * C[3]) >> 8);

  TEMP = (int64_t)dT * (int64_t)C[6] / 8388608 + 2000;

  Temperature = (float)TEMP / 100; 
  
  P  = ((int64_t)D1 * SENS / 2097152 - OFF) / 32768;

  Pressure = (float)P / 100;
  
  Serial.print("     Actual TEMP= ");
  Serial.print(Temperature);
  Serial.print("      Actual PRESSURE= ");
  Serial.print(Pressure);

  Serial.println();  
  Serial.print(" RAW Temp D2=  ");
  Serial.print(D2);
  Serial.print(" RAW Pressure D1=  ");
  Serial.println(D1);
  Serial.println();

//  Serial.print(" dT=  ");
//  Serial.println(dT); can't print int64_t size values
  Serial.println();
  Serial.print(" C1 = ");
  Serial.println(C[1]);
  Serial.print(" C2 = ");
  Serial.println(C[2]); 
  Serial.print(" C3 = ");
  Serial.println(C[3]); 
  Serial.print(" C4 = ");
  Serial.println(C[4]); 
  Serial.print(" C5 = ");
  Serial.println(C[5]); 
  Serial.print(" C6 = ");
  Serial.println(C[6]); 
//  Serial.print(" C7 = ");
//  Serial.println(C[7]);
  Serial.println();

  delay(1000);
}

long getVal(int address, byte code)
{
  unsigned long ret = 0;
  Wire.beginTransmission(address);
  Wire.write(code);
  Wire.endTransmission();
  delay(10);
  // start read sequence
  Wire.beginTransmission(address);
  Wire.write((byte) 0x00);
  Wire.endTransmission();
  Wire.beginTransmission(address);
  Wire.requestFrom(address, (int)3);
  if (Wire.available() >= 3)
  {
    ret = Wire.read() * (unsigned long)65536 + Wire.read() * (unsigned long)256 + Wire.read();
  }
  else {
    ret = -1;
  }
  Wire.endTransmission();
  return ret;
}

void initial(uint8_t address)
{

  Serial.println();
  Serial.println("PROM COEFFICIENTS ivan");

  Wire.beginTransmission(address);
  Wire.write(0x1E); // reset
  Wire.endTransmission();
  delay(10);


  for (int i=0; i<6  ; i++) {

    Wire.beginTransmission(address);
    Wire.write(0xA2 + (i * 2));
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.requestFrom(address, (uint8_t) 6);
    delay(1);
    if(Wire.available())
    {
       C[i+1] = Wire.read() << 8 | Wire.read();
    }
    else {
      Serial.println("Error reading PROM 1"); // error reading the PROM or communicating with the device
    }
    Serial.println(C[i+1]);
  }
  Serial.println();
}

Very many thanks for looking at this.

I changed from address 0x77 to 0x76 and I get the following

Actual TEMP= 24.30 Actual PRESSURE= 1003.81
RAW Temp D2= 8505592 RAW Pressure D1= 8251668

C1 = 54277
C2 = 57096
C3 = 33888
C4 = 33309
C5 = 32729
C6 = 28420

The temperature here in my room is 13.6C and pressure about 1030mB.

I have just run it a second time and the temperature is now
Actual TEMP= 21.06 Actual PRESSURE= 1003.53
with
RAW Temp D2= 8409976 RAW Pressure D1= 8279884

and I get a 31386 value for dT (pen and paper) instead of about 2500, D2 decreasing from above.
(why do I get errors when I try to Serial.print dT? Is there something wrong with wire.h for ver 1?)

The sensor now responds to the heat from my finger after you changed some code. It cannot be the 'temperature' you introduced, any idea?
If it is working with you Leo what can I possibly be doing wrong here?

Again thank you.

vanja:
...
RAW Temp D2= 8505592 RAW Pressure D1= 8251668

C1 = 54277
C2 = 57096
C3 = 33888
C4 = 33309
C5 = 32729
C6 = 28420

Actual TEMP= 24.30 Actual PRESSURE= 1003.81

I just ran the above values and get the same result: T = 24.30 °C, Pressure = 1003.81 mbar

This means your setup is working correctly.

vanja:
The temperature here in my room is 13.6C and pressure about 1030mB.

Are you sure it's 13.6 °C in your room!?

vanja:
(why do I get errors when I try to Serial.print dT? Is there something wrong with wire.h for ver 1?)

See my comment in the code.

As for the pressure, I went to the local weather station and recorded the pressure, then added the difference to the line:

  Pressure = (float)P / 100 + Pressure_Correction;

I'm sure there is a better way but it works for me.

Just did a short test with 3 sensors on my table

QNH = 1003 mbar, 19.3°C (actual values)

Embedded Adventure MS56111 DROTEK MS5611 DROTEK BMP085

Sketch „A“ 19.33°C, 978.14 mbar 21.62°C, 999.33 mbar

Sketch „B“ 18.06°C, 977.85 mbar 17.88°C, 1002.20 mbar

Sketch „C“ 21.20°C, 997.28 mbar

I am puzzled a little with those barometric sensors.

@vanja: The Problem is probably an overflow, dT is int64 in Leos code, but int32 in yours.

Hi,
Yes you are correct to question the temperature in my room Leo. I was using a new temperature measurement unit and it is not working properly (it uses the SCL1000 in a TI watch! What they used to sell at Sparkfun). I have checked the BBC and other sites and the temperature outside in my part of the UK is 7 to 8C, pressure 1005mb.
It reports in my car 8C and I have 2 identical Chinese, I assume, units and they are giving me a temp of 17 and 18C respectively in my room.
Thank you Leo for checking my results, I should have done that but I have become fixed with the temperature values. So my setup is working as you write, many thanks again.
As with Kalle123 it seems that my Drotek sensor does not give accurate temperature readings compared with the BMP and the German import MS5611.
The MS5803 gives a 25C reading which I do not understand as the calculation are the same for that and the MS5611. The temperature corrections on p8 of the datasheets cannot make much difference.

A quote from the company http://www.sensor-test.de/press/search/fairnews/67/en
The miniature precision pressure sensor module MS5611 consists of a high linear measurement element (pressure die) and a ??- A/D-Interface-IC. The module converts the measured pressure and temperature-dependant voltage into two 24bit data words, which are available as output signal. Additionally six individual coefficients are placed in the internal PROM, which enable extremely precise software correction for pressure and temperature measurement using an external microprocessor.
The resolution for pressure measurement is specified with 0.012mbar dependent from the Oversampling Ratio (OSR). The resolution of the temperature signal is typ < 0.01°C.

Two obvious things strike me from the manufacturer claim: The resolution of the temp signal is <0.01C which I assume tells us about the signal and not the final reading. But (how) can so much noise (standard signal to noise ratio s/n, I assume) be introduced into the system to give such different readings? My nearest two temp readings below are 21.5 and 21.99, a difference of nearly 0.5C or some 2.5% at best and 1.5C at worst. The calibration coefficients I assume give the lower and the maximum values for the temperature and pressure, 2 ranges with 20C as a reference. Given the range gap (like 0 to 100) and a reading it is simple to derive the final value. I can see that pressure is measured by an adaptation of a Wheatstone bridge where a change in pressure is converted into a change in resistance which is then digitized to a 0.012mbar resolution – with OSR it must be admitted. BUT even without OSR we should get consistently the same inaccurate values or does the lack of OSR more random error / results? But having said that from my results the most accurate readings are for the pressure. 992.67 (Germany) 992.04 (France) 990.91 (BMP) 999.7 (MS5803). So the 2 nearest pressure readings are Germany and France which have the greatest temperature difference.
How can you get accurate pressure readings when the temperature is inaccurate???!!!
Especially as pressure is compensated for by temperature in the equations for SENS a function of dT and in OFF also a function of dT.

Oh I just saw that you changed my dT to int64_t from int32_t. For what reason Leo? int64_t is good for a value up to 18x10^18?, do we need that long long? I also managed to print out dT before, now not.

Thanks guys as always
Best

Results
MS1 Germany

Actual TEMP= 21.99 Actual PRESSURE= 992.67
RAW Temp D2= 8036006 RAW Pressure D1= 8046020

C1 = 53520
C2 = 53270
C3 = 34137
C4 = 31191
C5 = 31166
C6 = 29055

MS2 Drotek France

Actual TEMP= 20.46 Actual PRESSURE= 992.04
RAW Temp D2= 8392488 RAW Pressure D1= 8240970

C1 = 54277
C2 = 57096
C3 = 33888
C4 = 33309
C5 = 32729
C6 = 28420

BMP085 Bosch
Temperature = 21.50 *C
Pressure = 99091 Pa
Altitude = 188.53 meters
Real altitude = 101.10 meters

MS5803 Another sensor type
Actual TEMP= 25.26 Actual PRESSURE= 99.97
RAW Temp D2= 8583292 RAW Pressure D1= 3934668

C1 = 45851
C2 = 38039
C3 = 28971
C4 = 25814
C5 = 32925
C6 = 28593

This began by trying to get the MS5611 working using the code from Fabio at varesano.net -
I was unable to get it working so used simple code we have been looking at.
I have just run 2 of Fabio’s programmes again just after obtaining the results above and this is what I get:

Fabio's Altitude programme using the Drotek sensor

temp: 20.74 degC pres: 324.67 mbar altitude: 10928.87 m

Fabio's Simple programme using the Drotek sensor

temp: 20.51 degC pres: 324.73 mbar
temp: 0.00 degC pres: 0.00 mbar
temp: 0.00 degC pres: 0.00 mbar
temp: 0.00 degC pres: 0.00 mbar
temp: 0.00 degC pres: 0.00 mbar
temp: -261.63 degC pres: 0.00 mbar
temp: 0.00 degC pres: 0.00 mbar
temp: 0.00 degC pres: 0.00 mbar

Absolutely senseless. He uses and calls cpp and h files using OSR 3 or 4096 precision although a see a -261.63C temp and wonder if absolute -273C Kelvin is being used and needs to be used. I will check.

An overflow problem!! I certainly hope it is.
In the data sheet p7 dT is declared as a signed int 32
Am I missing something?
Best

An afterthought to this:

I have just run my original code before you changed it Leo and I get

Actual TEMP= 1812 Actual PRESSURE= 4
RAW Temp D2= 8462844 RAW Pressure D1= 8219614

dT= 8407292

C0/1= 54277
C1/2= 57096
C2/3= 33888
C3/4= 33309
C4/5= 32729
C5/6= 28420
C6/7= 4195
C7/8= 8577

Am I getting these results from using int32_t dT instead of int64_t dT for dT as has just been suggested, an overflow problem.
It may be bad style to write as I did
dT = D2 - (C[4]*256)
Instead of dT = D2 - ((uint32_t)C[5] << 8) etc
I assume you can use decimals and bitshift notation interchangeably. (No thinking out loud, it is not notation it is operation, two different things.) It is certainly not elegant what I did but does it make a difference? Does it make a difference to the compiler? I suspect it does apart from being a time problem as in shifting a bit is quicker than multiplication.

I cannot quite see what you have done Leo to give good results unless it is the overflow? Puzzled.
Best

I've added to Leo's code pieces from Fabio's code:

const float sea_press = 1013.25;

....

Serial.print(getAltitude(Pressure, Temperature));
  Serial.println(" m");

...

float getAltitude(float Pressure, float Temperature) {
  return ((pow((sea_press / Pressure), 1/5.257) - 1.0) * (Temperature + 273.15)) / 0.0065;
}
...

And now I have the altitude displayed too in the Serial monitor (although I'm not sure how precise it is ...)

I think you will need to check and monitor the sea pressure value for accurate results. Why is absolute temperature being introduced here?

Because Fabio is using this hypsometric formula:

Just seen Leo's code over at http://arduino.cc/forum/index.php/topic,104247.0.html. Added in Flx lines for the altitude and we have -

#include <Wire.h>
#define ADDRESS 0x76 //0x77

uint32_t D1 = 0;
uint32_t D2 = 0;
int64_t dT = 0;
int32_t TEMP = 0;
int64_t OFF = 0; 
int64_t SENS = 0; 
int32_t P = 0;
uint16_t C[7];

float Temperature;
float Pressure;
const float sea_press = 1013.25;

void setup() {
// Disable internal pullups, 10Kohms are on the breakout
 PORTC |= (1 << 4);
 PORTC |= (1 << 5);

  Wire.begin();
  Serial.begin(9600); //9600 changed 'cos of timing?
  delay(100);
  initial(ADDRESS);

}

void loop()
{
  D1 = getVal(ADDRESS, 0x48); // Pressure raw
  D2 = getVal(ADDRESS, 0x58);// Temperature raw

  dT   = D2 - ((uint32_t)C[5] << 8);
  OFF  = ((int64_t)C[2] << 16) + ((dT * C[4]) >> 7);
  SENS = ((int32_t)C[1] << 15) + ((dT * C[3]) >> 8);

  TEMP = (int64_t)dT * (int64_t)C[6] / 8388608 + 2000;

  if(TEMP < 2000) // if temperature lower than 20 Celsius 
  {
    int32_t T1    = 0;
    int64_t OFF1  = 0;
    int64_t SENS1 = 0;

    T1    = pow(dT, 2) / 2147483648;
    OFF1  = 5 * pow((TEMP - 2000), 2) / 2;
    SENS1 = 5 * pow((TEMP - 2000), 2) / 4;
    
    if(TEMP < -1500) // if temperature lower than -15 Celsius 
    {
      OFF1  = OFF1 + 7 * pow((TEMP + 1500), 2); 
      SENS1 = SENS1 + 11 * pow((TEMP + 1500), 2) / 2;
    }
    
    TEMP -= T1;
    OFF -= OFF1; 
    SENS -= SENS1;
  }


  Temperature = (float)TEMP / 100; 
  
  P  = ((int64_t)D1 * SENS / 2097152 - OFF) / 32768;

  Pressure = (float)P / 100;
  
  Serial.print("     Actual TEMP= ");
  Serial.print(Temperature);
  Serial.print("      Actual PRESSURE= ");
  Serial.print(Pressure);
  Serial.println();
  Serial.println();
  
  Serial.print("     Actual ALTITUDE= ");
  Serial.print(getAltitude(Pressure, Temperature));
  Serial.println("m");
  Serial.println();  
  Serial.print(" RAW Temp D2=  ");
  Serial.print(D2);
  Serial.print(" RAW Pressure D1=  ");
  Serial.println(D1);
  Serial.println();

//  Serial.print(" dT=  ");
//  Serial.println(dT); can't print int64_t size values
  Serial.println();
  Serial.print(" C1 = ");
  Serial.println(C[1]);
  Serial.print(" C2 = ");
  Serial.println(C[2]); 
  Serial.print(" C3 = ");
  Serial.println(C[3]); 
  Serial.print(" C4 = ");
  Serial.println(C[4]); 
  Serial.print(" C5 = ");
  Serial.println(C[5]); 
  Serial.print(" C6 = ");
  Serial.println(C[6]); 
//  Serial.print(" C7 = ");
//  Serial.println(C[7]);
  Serial.println();

  delay(1000);
}
float getAltitude(float Pressure, float Temperature) {
  return ((pow((sea_press / Pressure), 1/5.257) - 1.0) * (Temperature + 273.15)) / 0.0065;
}
long getVal(int address, byte code)
{
  unsigned long ret = 0;
  Wire.beginTransmission(address);
  Wire.write(code);
  Wire.endTransmission();
  delay(10);
  // start read sequence
  Wire.beginTransmission(address);
  Wire.write((byte) 0x00);
  Wire.endTransmission();
  Wire.beginTransmission(address);
  Wire.requestFrom(address, (int)3);
  if (Wire.available() >= 3)
  {
    ret = Wire.read() * (unsigned long)65536 + Wire.read() * (unsigned long)256 + Wire.read();
  }
  else {
    ret = -1;
  }
  Wire.endTransmission();
  return ret;
}

void initial(uint8_t address)
{

  Serial.println();
  Serial.println("PROM COEFFICIENTS ivan");

  Wire.beginTransmission(address);
  Wire.write(0x1E); // reset
  Wire.endTransmission();
  delay(10);


  for (int i=0; i<6  ; i++) {

    Wire.beginTransmission(address);
    Wire.write(0xA2 + (i * 2));
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.requestFrom(address, (uint8_t) 6);
    delay(1);
    if(Wire.available())
    {
       C[i+1] = Wire.read() << 8 | Wire.read();
    }
    else {
      Serial.println("Error reading PROM 1"); // error reading the PROM or communicating with the device
    }
    Serial.println(C[i+1]);
  }
  Serial.println();
}

I hastily ran the code and the results seem to be all correct now. Excellent.
Best

Rather foolishly I did not check the results for below 20C. I obtain the following above 20C

Actual TEMP= 20.07 Actual PRESSURE= 1003.17
Actual ALTITUDE= 85.88m

RAW Temp D2= 8380806 RAW Pressure D1= 8287532

C1 = 54277
C2 = 57096
C3 = 33888
C4 = 33309
C5 = 32729
C6 = 28420

And below 20C
Actual TEMP= 145530.26 Actual PRESSURE= 345737.84
Actual ALTITUDE= -15034990.00m

RAW Temp D2= 8374970 RAW Pressure D1= 8289406

I have been checking the figures and obtain, calculating by hand, the following values for these two instances.
Above 20 Below 20

dT 2182 -3654
D2 8380806 8374970
c5*2^8 8378624 8378624
c6/8388608 = 0.003387928
TEMP 20.07 19.87

In order to obtain a temperature reading below 20C a negative value must be subtracted from the value 2000 (or 20C) in the line
TEMP = (int64_t)dT * (int64_t)C[6] / 8388608 + 2000;
That is dT must be negative which it indeed is from the readings with a value given by the hand calculated value of -3654, resulting in an acceptable temperature of 19.87C.

I read P7 of the 5611 datasheet as saying that the calculations are valid for ALL temperatures but they become less accurate below 20C. I was content using this and the sums on P7 as a first approximation. I ran the sketch and put the sensor outside and immediately received a temperature reading 145530.26 shown above. I thought it may have been something to do with the <20C corrections that Leo kindly introduced but obviously that was not the case.
The error seems to lie in TEMP = (int64_t)dT * (int64_t)C[6] / 8388608 + 2000; not accepting the negative value for dT, in this case the -3654. The error must lie, I think, in the interpretation of the value of dT or (int64_t)dT as all the rest of the values on this line are constants.
Any ideas thoughts?
Best

I 've added this lines from Fabio's Code to make the Pressure-readings smoother.

#define MOVAVG_SIZE 32

float movavg_buff[MOVAVG_SIZE];
int movavg_i=0;

uint32_t D1 = 0;
uint32_t D2 = 0;
....

Wire.begin();
Serial.begin(9600); //9600 changed 'cos of timing?
delay(100);
initial(ADDRESS);
//populate movavg_buff before starting loop
for(int i=0; i<MOVAVG_SIZE; i++) {
movavg_buff = Pressure;

  • }[/color]*
    Serial.print(" Actual TEMP= ");
  • Serial.print(Temperature);*
  • Serial.print(" Actual PRESSURE= ");*
  • pushAvg(Pressure);*
  • Serial.print(getAvg(movavg_buff, MOVAVG_SIZE));*
    void pushAvg (float val) {
  • movavg_buff[movavg_i] = val;*
  • movavg_i = (movavg_i + 1) % MOVAVG_SIZE;*
    }
    float getAvg(float * buff,int size) {
  • float sum = 0.0;*
  • for(int i=0; i<size; i++) {*
    _ sum += buff*;_
    _
    }_
    _
    return sum /size;_
    _
    }_
    _
    [/color]_
    long getVal(int address, byte code)
    _
    ....*_

Juergen, check your code because it's not going to work correctly.

]@_Leo

i use my code at a few days, the calculations of temperature and pressure are correct! The only thing i' ve recognize, is the pressure value grows up after reset to a stable result. This happens through the average code.

Here my complete Code with my LCD EA-DIP204-4, if someone use this code with these Display, he must change these line in the LiquidCrystal cpp.file: int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
to int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };

here a link to this display: http://www.lcd-module.de/pdf/doma/dip204-4.pdf

It's a EA-DIP204J-4NLW. The only problem are the pins, whose are in a distance of 2 mm !

#include <Wire.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

#define ADDRESS 0x77 //0x76
#define MOVAVG_SIZE 32

float movavg_buff[MOVAVG_SIZE];
int movavg_i=0; 

uint32_t D1 = 0;
uint32_t D2 = 0;
int64_t dT = 0;
int32_t TEMP = 0;
int64_t OFF = 0; 
int64_t SENS = 0; 
int32_t P = 0;
uint16_t C[7];

float Temperature;
float Pressure;


void setup() {
  // Disable internal pullups, 10Kohms are on the breakout
  PORTC |= (1 << 4);
  PORTC |= (1 << 5);

  Wire.begin();
  Serial.begin(9600); //9600 changed 'cos of timing?
  delay(100);
  initial(ADDRESS);
  //populate movavg_buff before starting loop
  for(int i=0; i<MOVAVG_SIZE; i++) {
   //movavg_buff[i] = Pressure;
  }
  // set up the LCD's number of columns and rows: 
  lcd.begin(20, 4);
  {
    lcd.command(0x01);//clear display lcd.command (0x01) / / clear display
    delay(02); 
    lcd.command(0x24);//function set RE=1 lcd.command (0x24) / / function set RE = 1
    delay(50); 
    lcd.command(0x09);//extendet function set, 4 lines, 5-dot fontwith
    delay(50); 
    lcd.command(0x20);//function set RE=0 lcd.command (0x20) / / function set RE = 0
    delay(50); 
    lcd.command(0x0C);//control, display on, cursor off, blinken off
    delay(50); 
    lcd.command(0x01);//clear display lcd.command (0x01) / / clear display
    delay(20); 
    lcd.command(0x06);//entry mode segment bidirectional

  }
}

void loop()
{
  D1 = getVal(ADDRESS, 0x48); // Pressure raw
  D2 = getVal(ADDRESS, 0x58);// Temperature raw

  dT   = D2 - ((uint64_t)C[5] << 8);
  OFF  = ((int64_t)C[2] << 16) + ((dT * C[4]) >> 7);
  SENS = ((int32_t)C[1] << 15) + ((dT * C[3]) >> 8);

  TEMP = (int64_t)dT * (int64_t)C[6] / 8388608 + 2000;

  Temperature = (float)TEMP / 100; 

  P  = ((int64_t)D1 * SENS / 2097152 - OFF) / 32768;

  Pressure = (float)P / 100;

  Serial.print("     Actual TEMP= ");
  Serial.print(Temperature);
  Serial.print("      Actual PRESSURE= ");
  pushAvg(Pressure);
  Serial.print(getAvg(movavg_buff, MOVAVG_SIZE));

  Serial.println();  
  Serial.print(" RAW Temp D2=  ");
  Serial.print(D2);
  Serial.print(" RAW Pressure D1=  ");
  Serial.println(D1);
  Serial.println();
  lcd.setCursor(0, 0);
  lcd.print("J");
  lcd.setCursor(1, 0);
  lcd.write(0x7E);
  lcd.setCursor(2, 0);
  lcd.print("rgen Schmidt");
  lcd.setCursor(0, 1);
  lcd.print("Temperatur:");
  lcd.setCursor(12, 1);
  lcd.print(Temperature);
  lcd.setCursor(18, 1);
  lcd.write(0xDC);
  lcd.print("C");
  lcd.setCursor(0, 2);
  lcd.print("Druck hPa:");
  lcd.setCursor(10, 2);
  if ((Pressure)<1000)
  {
    lcd.print(" ");
  }
  lcd.print(getAvg(movavg_buff, MOVAVG_SIZE));

  //  Serial.print(" dT=  ");
  //  Serial.println(dT); can't print int64_t size values
  //Serial.println();
  //Serial.print(" C1 = ");
  //Serial.println(C[1]);
  //Serial.print(" C2 = ");
  //Serial.println(C[2]); 
  //Serial.print(" C3 = ");
  //Serial.println(C[3]); 
  //Serial.print(" C4 = ");
  //Serial.print(" C5 = ");
  //Serial.println(C[5]); 
  //Serial.print(" C6 = ");
  //Serial.println(C[6]); 
  //  Serial.print(" C7 = ");
  //  Serial.println(C[7]);
  //Serial.println();

}

void pushAvg (float val) {
  movavg_buff[movavg_i] = val;
  movavg_i = (movavg_i + 1) % MOVAVG_SIZE;
}  

float getAvg(float * buff,int size) {
  float sum = 0.0;
  for(int i=0; i<size; i++) {
    sum += buff[i];
  }
  return sum /size;
}

long getVal(int address, byte code)
{
  unsigned long ret = 0;
  Wire.beginTransmission(address);
  Wire.write(code);
  Wire.endTransmission();
  delay(10);
  // start read sequence
  Wire.beginTransmission(address);
  Wire.write((byte) 0x00);
  Wire.endTransmission();
  Wire.beginTransmission(address);
  Wire.requestFrom(address, (int)3);
  if (Wire.available() >= 3)
  {
    ret = Wire.read() * (unsigned long)65536 + Wire.read() * (unsigned long)256 + Wire.read();
  }
  else {
    ret = -1;
  }
  Wire.endTransmission();
  return ret;
}

void initial(uint8_t address)
{

  Serial.println();
  Serial.println("PROM COEFFICIENTS ivan");

  Wire.beginTransmission(address);
  Wire.write(0x1E); // reset
  Wire.endTransmission();
  delay(10);


  for (int i=0; i<6  ; i++) {

    Wire.beginTransmission(address);
    Wire.write(0xA2 + (i * 2));
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.requestFrom(address, (uint8_t) 6);
    delay(1);
    if(Wire.available())
    {
      C[i+1] = Wire.read() << 8 | Wire.read();
    }
    else {
      Serial.println("Error reading PROM 1"); // error reading the PROM or communicating with the device
    }
    Serial.println(C[i+1]);
  }
  Serial.println();
}

Juergen_S:
//populate movavg_buff before starting loop
for(int i=0; i<MOVAVG_SIZE; i++) {
movavg_buff = Pressure;
}

It should be:

//populate movavg_buff before starting loop
  for(int i=0; i<MOVAVG_SIZE; i++) {
   movavg_buff[i] = Pressure; // Pressure is read from the sensor in every loop!!
  }

:slight_smile: