Improper Pressure Number from MS5607 Device

Arduino Mega 2560 Board. MS5607 Altimeter.

Here is the data sheet for this device. Pages 8 and 9 are what I’m using. Very nicely laid out…

I am having immense problems with getting the correct pressure. Pressure is coming out as negative. Everything else in the program works correctly. Any thoughts as to what I can try to get this thing work? All help greatly appreciated. Thanks.

#include <Wire.h>
#define ADDRESS 0x76 //0x77
#include "IntersemaBaro.h"
Intersema::BaroPressure_MS5607B baro(true);
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;
int32_t I = 4430.76923;

int32_t Altitude;
int32_t P0;
uint16_t C[7];
int32_t ALTITUDE;

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


void setup() {
  
  baro.init();
// 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()
{

      int32_t T2;  //signed int 32 bit for T2 (used for Temperature compensation)
      int64_t OFF2; //signed int 64 bit for OFF2 (used for Temperature compesation [see flow chart])
      int64_t SENS2; //signed int 64 bit for SENS2 (used for Temperature compensation [see flow chart])

  D1 = getVal(ADDRESS, 0x48); // Pressure raw
  D2 = getVal(ADDRESS, 0x58);// raw temperature value

  //dT and Temp will calculate temperature
  dT   = D2 - ((uint64_t)C[5] *(2*2*2*2*2*2*2*2));
  
  //off and sens will calculate temperature compensated pressure  
  OFF  = ( (int64_t)C[2]*131072 ) + ( (dT * C[4]) / (64));  
  SENS = ( (int32_t)C[1]*65536  ) + ( (dT * C[3]) / (128)); 
  
  TEMP = 2000 + (dT * (int64_t)C[6] / (8388608) ); //base temperature formula
  
    Serial.print("      TEMP= ");
         Serial.print(TEMP);
  
  
  if(TEMP <2000) // FOR WHEN THE TEMPERATURE IS BELOW 20 CELSIUS
  {
       
    Serial.print("Made pass through low temp\n");   
       T2=-(dT*dT)/(pow(2,31));
       OFF2= (61*(TEMP-2000)*(TEMP-2000))/16;   
       SENS2 = 2*(TEMP-2000)*(TEMP-2000);
       
         
  }

if(TEMP>2000) //FOR WHEN THE TEMPERATURE IS ABOVE 20 CELSIUS
  {
         
         T2=0;
         OFF2=0;
         SENS2 =0; 
         
    }    

           TEMP -= T2;
           OFF -= OFF2;
           SENS -= SENS2;
         
         
         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);
         
         int alt = baro.getHeightCentiMeters();
         Serial.print(" CODE FROM PARALLAX FOR ALTITUDE \n");
         Serial.print(" Feet: ");
         Serial.println((float)(alt)/30.48);
         Serial.print(" \n");
         delay(1000);
                        
         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();
}

Eye-achingly bad formatting. What do the raw readings and intermediate results look like? Are your data types appropriate?

Very nicely laid out

Sorry, I can't agree

SENS appears to be the problem. It is submitting a negative number. Working on this right now and looking to get something going.. D1 and OFF both submitted positive numbers and looked correct. Any thoughts as to what to do with SENS?

EDIT: It's an overflow. What would be the best way to go about getting an overflow fixed?

Do 64 bit ints really work ?

michinyon:
Do 64 bit ints really work ?

yes,.
Why wouldn’t they?

Hi,

I’ve just got my FreeTronics Eleven to interface correctly with the MS5607 barometer. I ended up discarding the IntersemaBaro.h library and writing my own subroutines.

This solved 2 problems - the code size is much reduced and the 1st order pressure calibration now works.

I fixed the calibration errors by re-writting the pressure equation so that pressure is calculated from 4 terms, each of which can be generated using standard Long 32 bit variables.

The first attachment is a 4 page explanation of what I did. The second is a test program.

MS5607 First Order Calibration.pdf (357 KB)

Baro_Test_V04.ino (4.08 KB)

Oops - I am using a USBDroid not an Eleven.

AWOL:

michinyon: Do 64 bit ints really work ?

yes,. Why wouldn't they?

Probably quicker and more reasable to use floats, doing a 64x64 bit multiply or divide on an 8 bit processor is heavy lifting.