Shop OBEX P1 Docs P2 Docs Learn Events
Help using SPI in Altimeter MS5607 and Arduino — Parallax Forums

Help using SPI in Altimeter MS5607 and Arduino

danidubdanidub Posts: 13
edited 2012-08-24 14:56 in Accessories
Hello again!
I'm still trying to communicate the Altimeter and the Arduino with SPI, and I made this code, that when a "0" is recieved in the serial, the arduino sends the conversion and read command to the altimeter and stores the 24 bit data of the altitude. Till now, I get the data in three bytes, but for some reason I only get 3 bytes of 11111111, 11111111, 11111111.
I post the code:
[/COLOR][LEFT][COLOR=#333333][FONT=Parallax]/*[/FONT][/COLOR][/LEFT]

Circuit: SCK: pin 13 MISO: pin 12 MOSI: pin 11 SS: pin 9 */const int ss = 9;#include <SPI.h>//3 bytes to get the 24 bit adc readbyte byte1; byte byte2; byte byte3;void setup() {  Serial.begin(9600);  SPI.begin();  SPI.setBitOrder(MSBFIRST);  pinMode(ss, OUTPUT);}void loop() {  if (Serial.available() > 0) {    byte incomingByte = Serial.read();    switch (incomingByte){    case '0':      read_alt();      break;    } //endswitch  }//enif}//endloopvoid read_alt(){  //READ Altimeter  digitalWrite(ss, LOW);  SPI.transfer(0x50); //ADC conversion command  delay(1);  // and store read data into three bytes  byte1 = SPI.transfer(0x00);//ADC conversion read command, first 8 bits  byte2 = SPI.transfer(0x00);//ADC conversion read command, second 8 bits  byte3 = SPI.transfer(0x00);//ADC conversion read command, third 8 bits  //print the 3 bytes in serial  Serial.println(byte1, BIN);  Serial.println(byte2, BIN);  Serial.println(byte3, BIN);  Serial.println();  //release chip, signal end transfer  digitalWrite(ss, HIGH);  [LEFT][COLOR=#333333][FONT=Parallax]}[/FONT][/COLOR][/LEFT][COLOR=#333333]

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-15 12:46
    There are examples for the Arduino on the <learn.parallax.com> website using the MS5607 altimeter in I2C mode. There are no ready-to-go examples using SPI mode. I suggest you start with the available examples. Once you've got the altimeter working with your Arduino, you can ask on the Arduino support forums about using the altimeter in SPI mode. If you post code in the future, make sure the end of line character for your code is a carriage return and line feed. The code you posted is all run together and impossible to read easily.
  • danidubdanidub Posts: 13
    edited 2012-06-17 17:16
    Thanks Mike!
    Here is the code again:
    /*
    Circuit:
     
     SCK: pin 13
     MISO: pin 12
     MOSI: pin 11
     SS: pin 9
     */
    
    
    const int ss = 9;
    #include <SPI.h>
    
    
    //3 bytes to get the 24 bit adc read
    byte byte1; 
    byte byte2; 
    byte byte3;
    
    
    void setup() {
      Serial.begin(9600);
    
    
      SPI.begin();
      SPI.setBitOrder(MSBFIRST);
    
    
      pinMode(ss, OUTPUT);
    }
    
    
    void loop() {
    
    
      if (Serial.available() > 0) {
    
    
        byte incomingByte = Serial.read();
    
    
        switch (incomingByte){
        case '0':
          read_alt();
          break;
        } //endswitch
    
    
      }//enif
    
    
    }//endloop
    
    
    void read_alt()
    {
      //READ Altimeter
      digitalWrite(ss, LOW);
      SPI.transfer(0x50); //ADC conversion command
      delay(1);
    
    
      // and store read data into three bytes
      byte1 = SPI.transfer(0x00);//ADC conversion read command, first 8 bits
      byte2 = SPI.transfer(0x00);//ADC conversion read command, second 8 bits
      byte3 = SPI.transfer(0x00);//ADC conversion read command, third 8 bits
    
    
      //print the 3 bytes in serial
      Serial.println(byte1, BIN);
      Serial.println(byte2, BIN);
      Serial.println(byte3, BIN);
      Serial.println();
    
    
      //release chip, signal end transfer
      digitalWrite(ss, HIGH); 
    }
    
    
    

    I will try the altimeter with the I2C mode to check it's working, then I'll post in the Arduino forums regarding communication between the two devices in SPI mode.
    Thank you,
    Daniel P.
  • danidubdanidub Posts: 13
    edited 2012-06-20 08:04
    Hello Mike, I have tryed with I2C mode and it works "fine" ( I get the altitude of 150 meters when I'm on 40 meters above sea level ) but the important thing is that he's sending data to the Arduino. But I still need it in the SPI mode to work. I have posted in the Arduino forums (here is the post) but still getting the 11111111, 11111111,11111111.

    I have made some little fixes in the code:
    [COLOR=#000000][FONT=courier new]/*[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]Circuit:[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new] SCK: pin 13[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new] MISO: pin 12[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new] MOSI: pin 11[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new] SS: pin 10[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new] */[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]const int ss = 10;[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]#include <SPI.h>[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]//3 bytes to get the 24 bit adc read[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]byte byte1; [/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]byte byte2; [/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]byte byte3;[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]void setup() {[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  Serial.begin(9600);[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  pinMode(ss, OUTPUT);[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  SPI.begin();[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  SPI.setBitOrder(MSBFIRST);[/FONT][/COLOR]
    
    
    [COLOR=#000000][FONT=courier new]}[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]void loop() {[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  if (Serial.available() > 0) {[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]    byte incomingByte = Serial.read();[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]    switch (incomingByte){[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]    case '0':[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]      read_alt();[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]      break;[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]    } //endswitch[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  }//enif[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]}//endloop[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]void read_alt()[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]{[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  //READ Altimeter[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  digitalWrite(ss, LOW);[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  SPI.transfer(0x50); //ADC conversion command[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  delay(1);[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  // and store read data into three bytes[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  byte1 = SPI.transfer(0x00);//ADC conversion read command, first 8 bits[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  byte2 = SPI.transfer(0x00);//ADC conversion read command, second 8 bits[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  byte3 = SPI.transfer(0x00);//ADC conversion read command, third 8 bits[/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  //release chip, signal end transfer[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  digitalWrite(ss, HIGH); [/FONT][/COLOR]
    
    [COLOR=#000000][FONT=courier new]  //print the 3 bytes in serial[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  Serial.println(byte1, BIN);[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  Serial.println(byte2, BIN);[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  Serial.println(byte3, BIN);[/FONT][/COLOR]
    [COLOR=#000000][FONT=courier new]  Serial.println();[/FONT][/COLOR]
    
    
    [COLOR=#000000][FONT=courier new]}[/FONT][/COLOR]
    
  • FranklinFranklin Posts: 4,747
    edited 2012-08-23 13:28
    Show us how you have it connected to the arduino.
  • danidubdanidub Posts: 13
    edited 2012-08-24 14:56
    Franklin wrote: »
    Show us how you have it connected to the arduino.

    Hello Franklin I have it connected like this:



    Altimeter
    Arduino pin


    CS
    10


    SDO
    12


    SDA
    11


    SCL
    13


    PS
    GND


    VIN
    +5


    GND
    GND




    Reading the datasheet I think I have to set or send some parameters but dont know how.

    In the other hand, I have an I2C code that works, but I need to connect it using SPI for my project, perhaps from the I2C code we can get the logic to make the communication for SPI.

    Here are the two files with I2C code:

    Altimeter_Arduino_10.ino
    #include <Wire.h>#include "IntersemaBaro.h"
    
    
    
    Intersema::BaroPressure_MS5607B baro(true);
    
    
    
    
    void setup() { 
        Serial.begin(9600);
        baro.init();
    }
    
    
    
    
    void loop() {
      int alt = baro.getHeightCentiMeters();
      Serial.print("Centimeters: ");
      Serial.print((float)(alt));
      Serial.print(", Feet: ");
      Serial.println((float)(alt) / 30.48);
      delay(400);
    }
    

    IntersemaBaro.h
    // http://code.google.com/p/ardroneme/// From the file NavData2.zip 
    
    
    
    /* Updated by MAPGPS based on Richi's code:
     * http://ulrichard.is-a-geek.net/?p=23
     */
    
    
    
    
    //Update by boulderjoe 12/30/11 to work with arduino 1.0 
    
    
    
    
    #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
    
Sign In or Register to comment.