Arduino software not working with Parallax MS5607 Altimeter Module

I'm working on a Hack-a-Day project, and have hooked a Parallax MS5607 Altimeter Module with LCD readout to my Arduino Duemilanove experimenter's board. It's almost working :slight_smile:

The LCD board displays information wrapped in a crazy way, but that is not a concern right now. It displays (Centimeters: -29408.00, Feet: -964.83). Not sure why the minus sign is in there, but at first I thought it might be correct. I live just off the top of a 1100 foot hill, but the elevation won't change when I move the unit up and down. Then, I noticed that the first number in the 'lookup table' is (-29408.00), so I think the program might just be going their by default.

I thought maybe the Altimeter Module might not be working, but when is remove its 5v, the LCD changes to (Centimeters: 1166.00, Feet 38.25), 1166 is not in the lookup table. When I reconnect the 5v the display goes back to (Centimeters: -29408.00, Feet: -964.83), so I think all hardware is working.

It's as if something is missing in the program (Arduino 1.0.3). I know I'm way over my head in this project when it comes to software, but I think I'm close to getting things working. It as if something is missing in the program. I know with the Parallax Spin program, they want you to enter your elevation as a starting point, but the I don't see anywhere in the Arduino software to do that, or even if it needs that info. Maybe I should say, almost everything works, and almost nothing works. Any ideas would be appreciated.

Dave

Altimeter_Arduino_10.ino (371 Bytes)

I'm working on a Hack-a-Day project

A link would be good.

and have hooked a Parallax MS5607 Altimeter Module with LCD readout

Ditto.

to my Arduino Duemilanove experimenter's board.

Ditto.

A link to the library you are using would be good, too.

If the device reports elevation to the nearest centimeter, pretend that it is more accurate by casting to a float and printing two decimal places will fool no one.

http://hackaweek.com/hacks/?p=1021

#ifndef INTERSEMA_BARO_H
#define INTERSEMA_BARO_H

#include <Wire.h>
#include <util/delay.h>
#include "Arduino.h"

namespace Intersema
{

class BaroPressure
{
public:
virtual void init() = 0;

int32_t getHeightCentiMeters(void)
{
return AcquireAveragedSampleCm(NUM_SAMP_FOR_AVG);
}

protected:
virtual int32_t AcquireAveragedSampleCm(const uint8_t nSamples) = 0;
virtual uint32_t ConvertPressureTemperature(uint32_t pressure, uint32_t temperature) = 0;

int32_t PascalToCentimeter(const int32_t pressurePa)
{
// Lookup table converting pressure in Pa to altitude in cm.
// Each LUT entry is the altitude in cm corresponding to an implicit
// pressure value, calculated as [PA_INIT - 1024*index] in Pa.
// The table is calculated for a nominal sea-level pressure = 101325 Pa.
static const int32_t PZLUT_ENTRIES = 77;
static const int32_t PA_INIT = 104908;
static const int32_t PA_DELTA = 1024;

static const int32_t lookupTable[PZLUT_ENTRIES] = {
-29408, -21087, -12700, -4244, 4279,
12874, 21541, 30281, 39095, 47986,
56953, 66000, 75126, 84335, 93628,
103006, 112472, 122026, 131672, 141410,
151244, 161174, 171204, 181335, 191570,
201911, 212361, 222922, 233597, 244388,
255300, 266334, 277494, 288782, 300204,
311761, 323457, 335297, 347285, 359424,
371719, 384174, 396795, 409586, 422552,
435700, 449033, 462560, 476285, 490216,
504360, 518724, 533316, 548144, 563216,
578543, 594134, 609999, 626149, 642595,
659352, 676431, 693847, 711615, 729752,
748275, 767202, 786555, 806356, 826627,
847395, 868688, 890537, 912974, 936037,
959766, 984206};

if(pressurePa > PA_INIT)
return lookupTable[0];
else
{
const int32_t inx = (PA_INIT - pressurePa) >> 10;
if(inx >= PZLUT_ENTRIES - 1)
return lookupTable[PZLUT_ENTRIES - 1];
else
{
const int32_t pa1 = PA_INIT - (inx << 10);
const int32_t z1 = lookupTable[inx];
const int32_t z2 = lookupTable[inx+1];
return (z1 + (((pa1 - pressurePa) * (z2 - z1)) >> 10));
}
}
}

static const uint8_t NUM_SAMP_FOR_AVG = 4;

unsigned int coefficients_[6];
};

class BaroPressure_MS5607B : public BaroPressure
{
public:
/// @param CSB i2c address select
BaroPressure_MS5607B(bool CSB = false) : i2cAddr_((CSB ? 0xEC : 0xEE) >> 1) { }

void init()
{
ResetSensor();
ReadCoefficients();
}

private:

const uint8_t i2cAddr_;
static const uint8_t cmdReset_ = 0x1E;
static const uint8_t cmdAdcRead_ = 0x00;
static const uint8_t cmdAdcConv_ = 0x40;
static const uint8_t cmdAdcD1_ = 0x00;
static const uint8_t cmdAdcD2_ = 0x10;
static const uint8_t cmdAdc256_ = 0x00;
static const uint8_t cmdAdc512_ = 0x02;
static const uint8_t cmdAdc1024_ = 0x04;
static const uint8_t cmdAdc2048_ = 0x06;
static const uint8_t cmdAdc4096_ = 0x08;
static const uint8_t cmdPromRd_ = 0xA0;

void ResetSensor()
{
Wire.begin();
Wire.beginTransmission(i2cAddr_);
Wire.write(cmdReset_);
Wire.endTransmission();
delay(3);
}

void ReadCoefficients(void)
{
for(uint8_t i=0; i<6; ++i)
coefficients_ *= ReadCoefficient(i + 1); *

#ifdef DEBUG

  • for(uint8_t i=0; i<6; ++i)*
  • {*
  • Serial.print("Coefficient ");*
  • Serial.print(i + 1, DEC);*
  • Serial.print(" : ");*
    Serial.println(coefficients_, DEC);
    * }*
    * Serial.println(ConvertPressureTemperature(6074082, 8574974));*
    * Serial.println(ConvertPressureTemperature(6074082, 8574984));*
    #endif
    * }*
    * uint16_t ReadCoefficient(const uint8_t coefNum)
    _
    {_
    uint16_t rC=0;*

* Wire.beginTransmission(i2cAddr_);
Wire.write(cmdPromRd_ + coefNum * 2); // send PROM READ command
_
Wire.endTransmission();*_

* Wire.requestFrom(i2cAddr_, static_cast<uint8_t>(2));
_
if(Wire.available() >= 2)_
_
{_
uint16_t ret = Wire.read(); // read MSB and acknowledge*

uint16_t rC = 256 * ret;
* ret = Wire.read(); // read LSB and not acknowledge*
* rC = rC + ret;*
* return rC;*
* }*
#ifdef DEBUG
* else*
* {*
* Serial.println("No data available in ReadCoefficient()");*
* }*
#endif

* return 0;*
* }*
* virtual int32_t AcquireAveragedSampleCm(const uint8_t nSamples)
_
{_
int64_t pressAccum = 0;
for(size_t n = nSamples; n; n--)
_
{_
const uint32_t temperature = ReadAdc(cmdAdcD2_ | cmdAdc4096_); // digital temperature value : typical 8077636
const uint32_t pressure = ReadAdc(cmdAdcD1_ | cmdAdc4096_); // digital pressure value : typical 6465444
const uint32_t pressConv = ConvertPressureTemperature(pressure, temperature);
_
pressAccum += pressConv;_
_/
* //MAPGPS*
* Serial.print("pressure: ");*
* Serial.print(pressure, DEC);*
* Serial.print(", pressConv: ");*
* Serial.print(pressConv, DEC);*
* Serial.print(", temperature: ");*
* Serial.println(temperature, DEC);*
/_
_
}_
const int32_t pressAvg = pressAccum / nSamples;
const int32_t AltCm = PascalToCentimeter(pressAvg);*

* return AltCm; *
* }*

* int32_t ReadAdc(const uint8_t cmd)
_
{ _
Wire.beginTransmission(i2cAddr_);
Wire.write(cmdAdcConv_ | cmd); // send conversion command*

* Wire.endTransmission();*
* // wait necessary conversion time*
* switch(cmd & 0x0f)*
* {*
* case cmdAdc256_:
_
delay(1);_
_
break;_
case cmdAdc512_:
_
delay(3);_
_
break;_
case cmdAdc1024_:
_
delay(4);_
_
break;_
case cmdAdc2048_:
_
delay(6);_
_
break;_
case cmdAdc4096_:
_
delay(10);_
_
break;_
_
}_
Wire.beginTransmission(i2cAddr_);
Wire.write(cmdAdcRead_);
_
Wire.endTransmission();*_

* Wire.requestFrom(i2cAddr_, static_cast<uint8_t>(3));
_
if(Wire.available() >= 3)_
_
{_
uint16_t ret = Wire.read(); // read MSB and acknowledge*

uint32_t temp = 65536 * ret;
* ret = Wire.read(); // read byte and acknowledge*
_ temp = temp + 256 * ret;_
* ret = Wire.read(); // read LSB and not acknowledge*
* temp = temp + ret;*

* return temp;*
* }*
#ifdef DEBUG
* else*
* {*
* Serial.println("No data available in cmdAdc()");*
* }*
#endif

* return 0;*
* }*
* uint32_t ConvertPressureTemperature(uint32_t pressure, uint32_t temperature)
_
{_
_
// calcualte 1st order pressure and temperature (MS5607 1st order algorithm)*_
const int32_t dT = temperature - coefficients_[4] * 256; // difference between actual and reference temperature
//const int32_t temp = (2000 + (dT * coefficients_[5]) / pow(2, 23)) ; // / 100; // actual temperature
//const int64_t OFF = static_cast<int64_t>(coefficients_[1]) * pow(2, 17) + dT * coefficients_[3] / pow(2, 6); // offset at actual temperature
//const int64_t SENS = static_cast<int64_t>(coefficients_[0]) * pow(2, 16) + dT * coefficients_[2] / pow(2, 7); // sensitivity at actual temperature
//const int32_t press = ((pressure * SENS / pow(2, 21) - OFF) / pow(2, 15)); // / 100; // temperature compensated pressure

* //MAPGPS: adapt formulas to avoid overflow*
const int32_t OFF = coefficients_[1] * 4 + ((float)dT / 2048) * ((float)coefficients_[3] / 1024);
const int32_t SENS = coefficients_[0] * 2 + ((float)dT / 4096) * ((float)coefficients_[2] / 1024);
const int32_t press = ((float)pressure / 2048) * ((float)SENS / 1024) - OFF;
/*
* Serial.println();*
* Serial.println(dT, DEC);*
* Serial.println(OFF, DEC);*
* Serial.println(SENS, DEC);*
* Serial.println();*
*/
* return press;*
* }*
};
} // namespace Intersema
#endif