Go Down

Topic: Pressure Sensors MS5611 MS5803 (Read 28 times) previous topic - next topic

vanja

#10
Apr 29, 2012, 04:13 pm Last Edit: Apr 29, 2012, 04:53 pm by vanja Reason: 1
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

H2SO4

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

Code: [Select]
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 ...)

vanja

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


vanja

#14
May 05, 2012, 06:39 pm Last Edit: May 05, 2012, 06:43 pm by vanja Reason: 1
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 -

Code: [Select]
#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

Go Up