Help using SPI in Altimeter MS5607 and Arduino
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:
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
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.
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]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