Pages: [1]   Go Down
Author Topic: Help with a barometric sensor: MS5535C  (Read 1526 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everyone. I'm working on a project that incorporates a Measurement Specialties Barometric Sensor, MS5535C (http://www.meas-spec.com/product/t_product.aspx?id=5029).

There is a similar sensor, the MS5534C, that has some Arduino code which I've based my own sketch off of (http://blog.ulrichard.ch/?p=23). Unfortunately, I'm getting garbage from the outputs of sensor, leading me to believe that I'm putting garbage in. I'm not exactly sure if I'm addressing the MS5535C correctly, and as it's my first time with a sensor of this sort, I'm turning to the forums for help.

The sensor data sheet (http://www.meas-spec.com/downloads/MS5535C.pdf) says:
Quote
The MS5535C communicates with microprocessors and other digital systems via a 3-wire synchronous serial interface as shown in Fig. 1.

My sketch looks like this, and it complies, loads and runs without trouble:

Code:
/*
  /*
  Reading the pressure from an intersema barometric pressure sensor
 
 
 By Richard Ulrich
 */

#include <Arduino.h>


// The circuit:
// * Intersema MS5534C connected to the following pins:.
static const uint8_t pinBaroSCLK  =   8;
static const uint8_t pinBaroDOUT  =   1; // in  on the arduino
static const uint8_t pinBaroDIN   =   0; // out on the arduino
static const uint8_t pinBaroMCLK  =   9; // the tone function used to generate the 34kHz signal interferes with pin 3 and 11, so it's best to use it directly

unsigned int coefficients[6];
uint32_t temperature;
uint32_t pressure;


void setup()   
{   

  // set the pin directions
  pinMode(pinBaroMCLK, OUTPUT);
  pinMode(pinBaroSCLK, OUTPUT);
  pinMode(pinBaroDIN,  OUTPUT);
  pinMode(pinBaroDOUT, INPUT);

  Serial.begin(9600);

  // generate approx 34kHz square for pinBaroMCLK
  tone(pinBaroMCLK, 31250); 

}

void loop()                     

  ReadCoefficients();
  for(size_t i=0; i<6; ++i)
  {
    Serial.print("Coefficient ");
    Serial.print(i + 1, DEC);
    Serial.print(" : ");
    Serial.println(coefficients[i], DEC);
  }

  temperature = ReadTemperature();

  pressure = ReadPressure();

  ConvertPressureTemperature(pressure, temperature);

  Serial.print("Pressure: ");
  Serial.println(pressure, DEC);

  Serial.print("Temperature: ");
  Serial.println(temperature, DEC);


  Serial.println(" ");
  delay(2000);
}

/*
 * Interface to Intersema Barometric pressure sensor.
 * For the moment, only the following sensors are supported:
 * MS5534C though manual protocol
 * MS5607B through I2C
 * Others might be added in the future.
 *
 * Created 14 Jan 2010
 * By Richard Ulrich
 * Inspired by the work of Hari Nair
 *
 * Added support for the MS5607B I2C : 7 Jan 2011
 */

void ResetSensor()
{
  SendCommand(0x155540, 21); // 1010101010101010 + 00000


void ReadCoefficients(void)
{   
  ResetSensor();
  unsigned int wa = ReadCoefficient(0x15);
  unsigned int wb = ReadCoefficient(0x16);
  coefficients[0] = (unsigned int)((wa >> 1) & (unsigned int)0x7FFF);
  coefficients[4] = (unsigned int)(((wa & 0x1) << 10) | ((wb >> 6) & (unsigned int)0x3FF));
  coefficients[5] = (unsigned int)(wb & 0x3F);

  wa = ReadCoefficient(0x19);
  wb = ReadCoefficient(0x1A);
  coefficients[3] = (unsigned int)((wa >> 6) & 0x3FF);
  coefficients[1] = (unsigned int)(((wa & 0x3F) << 6) | (wb & 0x3F));
  coefficients[2] = (unsigned int)((wb >> 6) & 0x3FF);
}

size_t ReadCoefficient(unsigned char addr)
{
  // 111 + 6bit coeff addr + 000 + 1clk(send0) 
  unsigned long cmd = (unsigned long)0x1C00 | (((unsigned long)addr) << 4);
  SendCommand(cmd,13);
  return ReadWord();
}

void SendCommand(unsigned long cmd, size_t nbits)
{
  while(nbits--) 
  {
    if(cmd & (unsigned long)(1 << nbits))
      digitalWrite(pinBaroDIN, HIGH);
    else
      digitalWrite(pinBaroDIN, LOW);

    digitalWrite(pinBaroSCLK, HIGH);
    digitalWrite(pinBaroSCLK, LOW);
  }
}

unsigned int ReadWord(void)
{
  unsigned int w;
  unsigned int clk = 16;
  w = 0;
  while(clk--) 
  {
    digitalWrite(pinBaroSCLK, HIGH);
    digitalWrite(pinBaroSCLK, LOW);             
    w |=  (digitalRead(pinBaroDOUT) << clk);
  }
  digitalWrite(pinBaroSCLK, HIGH);
  digitalWrite(pinBaroSCLK, LOW); 

  return w;
}

uint32_t ReadTemperature(void)
{
  // 111 + 1001 + 000 + 2clks(send 0)
  ResetSensor();
  SendCommand(0xF20, 12);
  while(digitalRead(pinBaroDOUT));
  const unsigned int temperature = ReadWord();
  return temperature;
}

uint32_t ReadPressure(void)
{
  // 111 + 1010 + 000 + 2clks(send 0)
  ResetSensor();
  SendCommand(0xF40, 12);
  while(digitalRead(pinBaroDOUT));
  const unsigned int pressure = ReadWord(); // read pressure
  return pressure;
}

void ConvertPressureTemperature(uint32_t pressure, uint32_t temperature)
{
  const long UT1  = (coefficients[4] << 3) + 20224;
  const long dT   = temperature  - UT1;
  const long TEMP = 200 + ((dT * (coefficients[5] + 50)) >> 10);
  const long OFF  = (coefficients[1] <<2) + (((coefficients[3] -512) * dT) >> 12);
  const long SENS = coefficients[0]  + ((coefficients[2] * dT) >> 10)  + 24576;
  const long X    = ((SENS* ((long)pressure  - 7168)) >> 14) - OFF;
  pressure    = ((X * 10) >> 5) + 2500;
  temperature = TEMP;

  long T2 = 0, P2 = 0;
  if(TEMP < 200)
  {
    T2 = (11 * (coefficients[5] + 24) * (200 - TEMP) * (200 - TEMP)) >> 20;
    P2 = (3 * T2 * (pressure - 3500)) >> 14;
    pressure    = pressure - P2;
    temperature = temperature - T2;
  }
}
       
The output that I'm getting from the serial monitor looks like this:

Code:
Coefficient 1 : 32767
Coefficient 2 : 4095
Coefficient 3 : 1023
Coefficient 4 : 1023
Coefficient 5 : 2047
Coefficient 6 : 63
Pressure: 8161
Temperature: 16256
 
Coefficient 1 : 32767
Coefficient 2 : 4095
Coefficient 3 : 1023
Coefficient 4 : 1023
Coefficient 5 : 2047
Coefficient 6 : 63
Pressure: 8161
Temperature: 16320
 
Coefficient 1 : 32767
Coefficient 2 : 4095
Coefficient 3 : 1023
Coefficient 4 : 1023
Coefficient 5 : 2047
Coefficient 6 : 63
Pressure: 8161
Temperature: 16256

My suspicion is that I've done something wrong with the baud rate, and I'm getting garbage from the sensor, but I have no way of knowing for sure. Perhaps someone with expertise could weigh in. Thanks in advance! smiley





« Last Edit: February 02, 2012, 01:35:12 pm by spincrisis » Logged

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


Quote
// generate approx 34kHz square for pinBaroMCLK
  tone(pinBaroMCLK, 31250); 

- that is 10%  off !!  that means after 10 bits the device got an errorreading smiley-sad

I recognize the code, think it is resolved earlier .. doing some googling ...
Logged

Rob Tillaart

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

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

Thanks,

According to the data sheet, the sensor will accept clock values between 30 kHz and 35 kHz, and 40/60 and 60/40 duty cycling. This is a tricky topic for goggling. I'm regretting not getting the I2C version of this sensor...
Logged

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


Found the code I was looking for, It is a sensor with similar code - same manufacturer - same hardware ?

- http://arduino.cc/forum/index.php/topic,67188.0.html -
Please check if the comments are helpfull.

You might need to make some vars  unsigned long iso long  to prevent overflow.

Logged

Rob Tillaart

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

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

Looks like a great source to help solve my problem. I'll have a go at implementing this tonight and report back with the code that works for me.

Thank you for digging this up!
Logged

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


you are welcome, next time you might help me out smiley-wink
Logged

Rob Tillaart

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

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

SHAZAM! The code for the MS5541C works with the MS5535C! I'm just going to tidy up the code a little bit and work on understanding it and I'll post my MS5535C code here:

Code:
/*
 MS5535C Pressure Sensor calwords readout
 This program will read your MS5535C or compatible pressure sensor every 5 seconds and show you the calibration words, the calibration factors,
 the raw values and the compensated values of temperature and pressure.
 Once you read out the calibration factors you can define them in the header of any sketch you write for the sensor.
 
Pins:
 MS5535C sensor attached to pins 10 - 13:
 DIN (MOSI): pin 11
 DOUT (MISO): pin 12
 SCLK: pin 13
 MCLK: pin 9
 
 Created August 2011 by SMStrauch based on application note AN510 from www.intersema.ch (http://www.meas-spec.com/downloads/Using_SPI_Protocol_with_Pressure_Sensor_Modules.pdf),
 and with help of robtillaart and ulrichard.
 
 Modified February 2012 by spincrisis for the MS5535C.
 */

// include library:
#include <SPI.h>

// generate a MCKL signal pin
const int clock = 9;

void resetsensor() //this function keeps the sketch a little shorter
{
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
}

void setup() {
  Serial.begin(9600);
  SPI.begin(); //see SPI library details on arduino.cc for details
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV32); //divide 16 MHz to communicate on 500 kHz
  pinMode(clock, OUTPUT);
  delay(100);
}

void loop()
{
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (clock, 128) ;

  resetsensor();//resets the sensor - caution: afterwards mode = SPI_MODE0!

  //Calibration word 1
  unsigned int result1 = 0;
  unsigned int inbyte1 = 0;
  SPI.transfer(0x1D); //send first byte of command to get calibration word 1
  SPI.transfer(0x50); //send second byte of command to get calibration word 1
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  result1 = SPI.transfer(0x00); //send dummy byte to read first byte of word
  result1 = result1 << 8; //shift returned byte
  inbyte1 = SPI.transfer(0x00); //send dummy byte to read second byte of word
  result1 = result1 | inbyte1; //combine first and second byte of word
  Serial.print("Calibration word 1 =");
  Serial.println(result1);

  resetsensor();//resets the sensor

  //Calibration word 2; see comments on calibration word 1
  unsigned int result2 = 0;
  byte inbyte2 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x60);
  SPI.setDataMode(SPI_MODE1);
  result2 = SPI.transfer(0x00);
  result2 = result2 <<8;
  inbyte2 = SPI.transfer(0x00);
  result2 = result2 | inbyte2;
  Serial.print("Calibration word 2 =");
  Serial.println(result2); 

  resetsensor();//resets the sensor

  //Calibration word 3; see comments on calibration word 1
  unsigned int result3 = 0;
  byte inbyte3 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x90);
  SPI.setDataMode(SPI_MODE1);
  result3 = SPI.transfer(0x00);
  result3 = result3 <<8;
  inbyte3 = SPI.transfer(0x00);
  result3 = result3 | inbyte3;
  Serial.print("Calibration word 3 =");
  Serial.println(result3); 

  resetsensor();//resets the sensor

  //Calibration word 4; see comments on calibration word 1
  unsigned int result4 = 0;
  byte inbyte4 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0xA0);
  SPI.setDataMode(SPI_MODE1);
  result4 = SPI.transfer(0x00);
  result4 = result4 <<8;
  inbyte4 = SPI.transfer(0x00);
  result4 = result4 | inbyte4;
  Serial.print("Calibration word 4 =");
  Serial.println(result4);

  //now we do some bitshifting to extract the calibration factors
  //out of the calibration words; read datasheet AN510 for better understanding
  long c1 = result1 >> 3 & 0x1FFF;
  long c2 = ((result1 & 0x07) << 10) | ((result2 >> 6) & 0x03FF);
  long c3 = (result3 >> 6) & 0x03FF;
  long c4 = (result4 >> 7) & 0x07FF;
  long c5 = ((result2 & 0x003F) << 6) | (result3 & 0x003F);
  long c6 = result4 & 0x007F;

  Serial.println(c1);
  Serial.println(c2);
  Serial.println(c3);
  Serial.println(c4);
  Serial.println(c5);
  Serial.println(c6);

  resetsensor();//resets the sensor

  //Temperature:
  unsigned int tempMSB = 0; //first byte of value
  unsigned int tempLSB = 0; //last byte of value
  unsigned int D2 = 0;
  SPI.transfer(0x0F); //send first byte of command to get temperature value
  SPI.transfer(0x20); //send second byte of command to get temperature value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  tempMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  tempMSB = tempMSB << 8; //shift first byte
  tempLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D2 = tempMSB | tempLSB; //combine first and second byte of value
  Serial.print("Temperature raw =");
  Serial.println(D2); //voilá!

  resetsensor();//resets the sensor

  //Pressure:
  unsigned int presMSB = 0; //first byte of value
  unsigned int presLSB =0; //last byte of value
  unsigned int D1 = 0;
  SPI.transfer(0x0F); //send first byte of command to get pressure value
  SPI.transfer(0x40); //send second byte of command to get pressure value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  presMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  presMSB = presMSB << 8; //shift first byte
  presLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D1 = presMSB | presLSB; //combine first and second byte of value
  Serial.print("Pressure raw =");
  Serial.println(D1);

  //calculation of the real values by means of the calibration factors and the maths
  //in the datasheet. const MUST be long
  const long UT1 = (c5 << 3) + 10000;
  const long dT = D2 - UT1;
  const long TEMP = 200 + ((dT * (c6 + 100)) >> 11);
  const long OFF  = c2 + (((c4 - 250) * dT) >> 12) + 10000;
  const long SENS = (c1/2) + (((c3 + 200) * dT) >> 13) + 3000;
  long PCOMP = (SENS * (D1 - OFF) >> 12) + 1000;
  float TEMPREAL = TEMP/10;
 

  Serial.print("Real Temperature in °C=");
  Serial.println(TEMPREAL);

  Serial.print("Compensated pressure in mbar =");
  Serial.println(PCOMP);

  //2nd order compensation only for T > 0°C
  const long dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
  const float TEMPCOMP = (200 + (dT2*(c6+100) >>11))/10;
  Serial.print("2nd order compensated temperature in °C =");
  Serial.println(TEMPCOMP); 

  delay(5000);
}

Thank you for pointing me in the right direction.
« Last Edit: February 02, 2012, 11:43:02 pm by spincrisis » Logged

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

Welcome,
Logged

Rob Tillaart

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

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

Hi All!
I am very new and very inexperienced with programming and could really use some help. I can do a little in PIC Basic and have no idea how to read the "C" language. It would be nice not to have to learn another programming language right now. I am trying to get an MS5541 to work in PIC Basic. Does anyone have the program or know where to find the program in PIC Basic? I would really appreciate any and all help I can get. Thank you in advance. Best, Ed
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 287
Posts: 25682
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you tried a PIC BASIC forum?
Here, we try to help wean people off BASIC.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

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

Thank you and you are right. I was actually pointed here by a PIC forum. It just makes it a little easier if you can understand everything in the language you already know before trying to write in a language you do not know.  smiley-wink
Logged

Pages: [1]   Go Up
Jump to: