Shop OBEX P1 Docs P2 Docs Learn Events
Problem with the Altimeter Module MS5607 — Parallax Forums

Problem with the Altimeter Module MS5607

SkywolfSkywolf Posts: 3
edited 2013-03-01 19:59 in Accessories
Hello!

I recently bought my altimeter module. But I'm new to working with these and Arduino, and I'm having some trouble getting proper results. So here's My setup...

photo 3.jpg
photo 1.jpg
photo 2.jpg



My code...
#include <Wire.h> #include "IntersemaBaro.h"


Intersema::BaroPressure_MS5607B baro(true);


void setup() { 
    Serial.begin(9600);
    baro.init();
}


void loop() {
  long alt = baro.getHeightCentiMeters();
  Serial.print("Centimeters: ");
  Serial.print((float)(alt), 2);
  Serial.print(", Feet: ");
  Serial.println((float)(alt) / 30.48, 2);
  delay(400);
}
// http://code.google.com/p/ardroneme/// From the file NavData2.zip 


/* 
 * http://ulrichard.is-a-geek.net/?p=23
 */
 


#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_[i] = 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_[i], 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






And my results--

[HTML]http://gyazo.com/c2ca47d96fe1d6894ae6d02529ce80e6[/HTML]

The data never changes. Am I doing anything wrong?


Thanks!
1024 x 768 - 114K
1024 x 768 - 144K
1024 x 768 - 122K

Comments

  • SkywolfSkywolf Posts: 3
    edited 2013-02-24 13:02
    I really need help! Am I doing anything wrong?
  • SRLMSRLM Posts: 5,045
    edited 2013-02-24 17:20
    The first problem that I see is that in your first code post you have two #includes on the same line. You should separate it into two lines.

    After that, it looks like you are using the Parallax KickStart code, so I assume it works. You probably have a hardware problem. Can you provide a schematic for your circuit, and maybe a picture?

    If the code is working correctly, you should be able to see a change in the numbers if you gently blow into the module. Do you see any change?
  • SkywolfSkywolf Posts: 3
    edited 2013-02-28 19:21
    photo 2.jpg
    photo 1.jpg
    photo 3.jpg


    Thanks for replying! I posted these pictures earlier, but here they are again in case you didn't see them.

    The numbers don't change when I blow into the module, but I noticed that if I remove the power while the script is running, the numbers change to a different set of digits. Does this mean that the chip is being "registered", but not working?

    Thanks!
    1024 x 768 - 122K
    1024 x 768 - 144K
    1024 x 768 - 114K
  • SRLMSRLM Posts: 5,045
    edited 2013-03-01 19:59
    I somehow missed them the first time.

    The change in readings is likely due to the pullup resistors being removed.

    Well, it looks like you have everything wired up correctly, and the sample code is presumed good. So, here are some things that I would try:
    1. Attach a logic analyzer or oscilloscope to the SCL and SDA lines, and see what data is sent.
    2. Try a new Arduino and/or a new altimeter module.

    After that, I don't have ideas.
Sign In or Register to comment.