Pages: 1 [2] 3 4 5   Go Down
Author Topic: Pressure Sensors MS5611 MS5803  (Read 23557 times)
0 Members and 2 Guests are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: May 06, 2012, 11:38:08 am by vanja » Logged

Germany
Offline Offline
Newbie
*
Karma: 1
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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;
  }


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;
}


long getVal(int address, byte code)
....
Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Germany
Offline Offline
Newbie
*
Karma: 1
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

]@_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 !

Code:
#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();
}
« Last Edit: May 21, 2012, 03:51:36 pm by Juergen_S » Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

It should be:
Code:
//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!!
  }



 smiley
« Last Edit: May 12, 2012, 08:27:30 am by _Leo_ » Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Germany
Offline Offline
Newbie
*
Karma: 1
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello _Leo

here is my code, i make a mistake to do not use the #-button to insert my code here.

Jürgen

* MS5611_LCD_Moverage.ino (4.5 KB - downloaded 29 times.)
Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Jürgen,

you misunderstood.

Code:
"movavg_buff[i] = Pressure;"

Pressure has no value in your code.

You need to write a subroutine that reads the pressure from the sensor. Then call the routine in the loop to populate the buffer.

Example:
Code:
"movavg_buff[i] = Get_Pressure();"

Leo
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo can you caste your eye over these results and those in my last post?
Dead on the reference temperature of 20C the temperature changes to a large negative number which seems to be a constant-21329306.00 with the sensor put into the Kuhlschrank.
The code I use is as already posted which I assume you use and Juergen usw.

RAW Temp D2=  8379134 RAW Pressure D1=  8352890
     Actual TEMP= 20.01      Actual PRESSURE= 1019.96

 RAW Temp D2=  8379080 RAW Pressure D1=  8352918
     Actual TEMP= 20.00      Actual PRESSURE= 1019.96

 RAW Temp D2=  8378778 RAW Pressure D1=  8352956
     Actual TEMP= -21329306.00      Actual PRESSURE= -9499139.00

 RAW Temp D2=  8378598 RAW Pressure D1=  8353160
     Actual TEMP= -21329306.00      Actual PRESSURE= -9495526.00

 RAW Temp D2=  8378420 RAW Pressure D1=  8353066
     Actual TEMP= -21329306.00      Actual PRESSURE= -9504028.00

 RAW Temp D2=  8378290 RAW Pressure D1=  8353288
     Actual TEMP= -21329306.00      Actual PRESSURE= -9503490.00

If I use another 5611 then I get the same thing

 RAW Temp D2=  7972696 RAW Pressure D1=  8170442
     Actual TEMP= -21326056.00      Actual PRESSURE= -4003808.25

With this one the Actual TEMP is a constant at-21326056.00 and the raw pressure is half.

(Has it anything to do with the use of int64_t).

Best
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I found the same problemm for temperatures below 20°C. dt then gets negative. The uint_32 then roll to big numbers
I changed dt to int32_t and the line for calculation of dt as follows:
dT   = D2 - ((int32_t)C[5] << smiley-cool;
Now it seems to work. smiley-wink
BR
c00laris

You see only a small "jump" due to the change in the compensation at 20.00°C:

Actual TEMP= 19.99      Actual PRESSURE= 975.79
 Actual ALTITUDE= 324.33m
 RAW Temp D2=  8787722 RAW Pressure D1=  8083108
 dT=  -246
 TEMP=  1999
 T1=  0
 OFF=  -1100205905
 OFF1=  2
 SENS=  1658456444
 SENS1=  1



Actual TEMP= 20.00      Actual PRESSURE= 975.73
 Actual ALTITUDE= 324.88m
 RAW Temp D2=  8788094 RAW Pressure D1=  8082768
 dT=  126
 TEMP=  2000
 T1=  0
 OFF=  -1100125650
 OFF1=  2
 SENS=  1658502323
 SENS1=  1



Actual TEMP= 20.00      Actual PRESSURE= 975.73
 Actual ALTITUDE= 324.88m
 RAW Temp D2=  8788254 RAW Pressure D1=  8082694
 dT=  286
 TEMP=  2000
 T1=  0
 OFF=  -1100091132
 OFF1=  2
 SENS=  1658522055
 SENS1=  1



Actual TEMP= 20.01      Actual PRESSURE= 975.75
 Actual ALTITUDE= 324.71m
 RAW Temp D2=  8788534 RAW Pressure D1=  8082688
 dT=  566
 TEMP=  2001
 T1=  0
 OFF=  -1100030727
 OFF1=  2
 SENS=  1658556587
 SENS1=  1


Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@c00laris
Can you post your final code for future reference?
Thanks,
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I found the same problemm for temperatures below 20°C. dt then gets negative. The uint_32 then roll to big numbers
I changed dt to int32_t and the line for calculation of dt as follows:
dT   = D2 - ((int32_t)C[5] << smiley-cool;
Now it seems to work. smiley-wink
BR
c00laris
...

That's a bad idea because C[] can be between 0 - 65535!

To solve the problem in the code you are using use:
Code:
dT = D2 - ((uint64_t)C[5] << 8);
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I just tested my MS5611 using the following code (Arduino-1.0.1) letting the sensor rest quietly on my desk (weather is fine,..):

Code:
#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;


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

  Wire.begin();
  Serial.begin(115200); //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 - ((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;
  
//  Serial.print("     Actual TEMP= ");
//  Serial.print(Temperature);
//  Serial.print("      Actual PRESSURE= ");
  Serial.println(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();
}

I just sampled the pressure value for 60 seconds, attached you can find an image of the pressure/time dependency. I think the pressure (97436 Pa) is OK for my height, but the pressure noise seems too much for me! The range is 100 Pa, which would correspond to a height variation of more than 12 meters I think.
What characteristic pressure noise do you have? Is there a possibility to get less noise (oversampling,...?) without averaging too much? I would need about 5 reliable values per second...

Best regards,
Mike


* MS5611-60sec-sample.JPG (384.74 KB, 1658x1203 - viewed 98 times.)
« Last Edit: July 07, 2012, 01:47:27 pm by TheMike » Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The pressure always has to be corrected in relation to the location of measurement.

The "Noise" you are witnessing can be different depending which hardware you are using.
The sensor has fluctuations, which is normal. However if e.g. the I2C bus layout on the PCB board is poorly designed then you will get additional interference noise.
I'm running 3 different manufactured Arduino platforms, all showing different noise levels. Interestingly my Arduino R3 with protoshield has the least interference noise.

Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The noise can be due to many different reasons, that´s clear....but the magnitude makes me a little bit irritated. I have mounted the MS5611 directly besides a BMP085 on my breadboard, both sharing the same I2C bus just with different addresses.
The MS5611 shows a range of +/-50 Pa, while the BMP085 only shows about +/-15 Pa.
I thought the MS5611 should be much better than the BMP085 exhibiting a max. resolution of around 10 to 15 cm, which would be a factor 100 away from my measurements... :-(


Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 82
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The noise can be due to many different reasons, that´s clear....but the magnitude makes me a little bit irritated. I have mounted the MS5611 directly besides a BMP085 on my breadboard, both sharing the same I2C bus just with different addresses.
The MS5611 shows a range of +/-50 Pa, while the BMP085 only shows about +/-15 Pa.
I thought the MS5611 should be much better than the BMP085 exhibiting a max. resolution of around 10 to 15 cm, which would be a factor 100 away from my measurements... :-(

In your post from the 7th July you didn't state that you were comparing it to the BMP085!
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Pages: 1 [2] 3 4 5   Go Up
Jump to: