Arduino Forum

Using Arduino => Sensors => Topic started by: godo on Jul 21, 2011, 04:17 pm

Title: MS5541 depth sensor communication
Post by: godo on Jul 21, 2011, 04:17 pm
Hi there,
our current project is a k-meter, a device to measure the attenuation of light in the water column (which is a core question in fotobiology, biological ozeanography, ecology, etc.). The final version is supposed to have a visible light sensor and separate UV-A and UV-B channels as well as temperature, salinity and depth measurement, a hardware clock and a µSD-Card for data storage. And it is all based on Arduino of course, right now we plan with a MiniArduino but plan to have a small sized Arduino clone with USB on a circlular 60 mm diameter PCB (so you might use it for a cansat ;-))
So far I managed to implement data storage on µSD, hardware clock (DS1307), visible light sensor and temperature (DS18S20). Right now I am about to include the MS5541 depth sensor, which will be hooked onto the SPI-Bus (where already sits the µSD; I ordered the 74HTC1G125 as indicated in the datasheet of the sensor in order to connect it to a shared SPI-Bus).
I searched deeply but did not find anything I could use right away (and I am not so much of a programer, if I musn't). Of course I already have all the datasheets and the information to start putting a code together (if I'd knew how to do it quick'n'easy), but does anybody by chance have a working code to read the sensor data? Unfortunately most topics I found in the internet seize without a final documentation and I did not recieve answers on my eMails.
I already wondered if it would be a good idea to adapt a code for one of the other SPI-using MS**** sensors, any comments about that?

We deeply appreciate the Arduino community which already helped us a lot in building (and dreaming about) other small equipment for our scientific work. If anybody is interested in joining that project of ours, you are welcome!
Thank you all very much for sharing great and inspiring ideas and helping most selflessly people who otherwise would propably not dare to start building cool stuff!
Greetings from Patagonia
Sebastian
http://www.efpu.org.ar
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Jul 21, 2011, 07:26 pm

Hi Sebastian,

Welcome to Arduino forum, sounds like a very interesting abnd valuable project. Have you seen this project @ lady ada: - http://www.ladyada.net/make/logshield/lighttemp.html - I recalled it when I read your story.

Quote
I already wondered if it would be a good idea to adapt a code for one of the other SPI-using MS**** sensors, any comments about that?

You must compare the datasheets, if they look alike, it gives you a good starting point, if they don't you better start from scratch.

I don't have a library for the sensor you named, but if you build it and want a code review, you can post it here.

Be aware that every SPI device has its own select line and you can have only one SPI device active at the same time. Give this enough attention as you would not be the first with SPI interference caused by this.

If you like a review of your code you build so far feel free to post it.


Regards from the Netherlands..
Rob
How is the weather in Patagonia?
Title: Re: MS5541 depth sensor communication
Post by: godo on Jul 22, 2011, 03:21 pm
Hi Rob,
thanks for your quick answer! Bedankt!
Yes, in deed I know that project and I think I even used the code for learning the logging procedure. The setup is a little to rough for our kind of radiation measurement, but it is a great project to learn from it.
Thanks for the advice with the SPI-Bus; I am thinking in making a string of all the data first and then writing it to the card so every slave would be adressed exclusively.
As soon as I have something post-worthy I'll do, and I also hope to provide a good documentation one day if it works neatly.
Regards and saludos
Seb
PS: Weather is fine, a little cold at night, but not so much ashes any more from Puyehue volcano. You can check our weather station on the webpage below (and fotos of the beautiful place).
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 02, 2011, 08:59 pm
Uuh, swell! With all the software challenges I did not care for hardware restrictions. Now I got about 21kB to squeeze into the Mini's memory... even without the sensor comunication.
Did anybody ever change the 168 for a 328 on an Arduino Mini board and it worked? I do have a USBtinyISP and spare chips, so the bootloader might not be the problem. I only find that it is "irreplaceable", well, how irreplaceable exactly?
Thanks
Sebastian


_ _ _ UPDATE _ _ _
Irreplaceable my ...! HA! It IS possible to change the chip! OK, it is not a walk in the park, but it is definitely possible:
I cut of the chip, because I didn't want to temper with the other components by heating the entire circuit board up. I used my swiss army knife after rejecting the idea do dremel it of - there are lots of vias under the chip, so I think it is safer to cut the pins. Then I cleaned the pads from the pin rests and checked for connections between the pads and also if the pads still were connected to the outbreak pins. Soldering the new chip onto it was quite challenging. Started with a corner pin, then adjusted neatly and attached the opposite corner. Then one pin by one, using a desktop lamp and a magnifying lens to see when the tin got liquid and sucked under the pins. Next time I use one of our stereo microscopes for that. Anyway, afterwards I checked again for shortcuts and corrected. Then I burned the bootloader with my USBtinyISP. And then I used my Duemilanove to upload sketches; this worked with "Duemila or Nano w/ ATmega 328" selected as board, not with the "Mini with ATmega 328". Happy happy, joy joy!
Some additional remarks:
- I didn't use extra tin but only the rest on the pads. I do not have SMD soldering paste yet.
- I know there is a Mini with a 328 available, but I have no possibility to get one here (within a week or two. Besides: everybody could buy one :-) ).
OK; the basic problem remains, though, but we will try something about it next week.
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 06, 2011, 01:32 am
Hi,
today I tried some code I put together:
Code: [Select]
/*
 MS5541 Pressure Sensor Display

Circuit:
MS5541 sensor attached to pins 10 - 13:
MOSI: pin 11
MISO: pin 12
SCK: pin 13

*/

// library:
#include <SPI.h>

//Sensor memory register addresses:
const int PRESSURE = 0x0F;      //MSB pressure
const int PRESSURE_LSB = 0x40;  //LSB of pressure
const int TEMPERATURE = 0x0F;   //MSB temperature
const int TEMPERATURE_LSB = 0x20;  //LSB temperature
const int W1M = 0x1D; // MSB Calibration word 1
const int W1L = 0x50; // LSB Calibration word 1
const int W2M = 0x1D; // MSB Calibration word 2
const int W2L = 0x60; // LSB Calibration word 2
const int W3M = 0x1D; // MSB Calibration word 3
const int W3L = 0x90; // LSB Calibration word 3
const int W4M = 0x1D; // MSB Calibration word 4
const int W4L = 0xA0; // LSB Calibration word 4
const byte RST1 = 0x15; //Reset sequence word 1
const byte RST2 = 0x55; //Reset sequence word 2
const byte RST3 = 0x40; //Reset sequence word 3


// CS just in case
const int chipSelectPin = 10;

void setup() {
 Serial.begin(9600);
 SPI.begin();
 pinMode(chipSelectPin, OUTPUT);
 delay(100);
}

void loop() {
 //RESET
 SPI.setDataMode(1);
 SPI.transfer(0x15);
 SPI.transfer(0x55);
 SPI.transfer(0x40);
 delay(100);
 
 //Calibration word 1
 unsigned int result1 = 0;
 unsigned int inbyte1 = 0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.transfer(0x1D);
 SPI.transfer(0x50);
 SPI.setDataMode(0);
 result1 = SPI.transfer(0x00);
 result1 = result1 <<8;
 inbyte1 = SPI.transfer(0x00);
 result1 = result1 | inbyte1;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Calibration word 1 =");
 Serial.println(result1);
 
 //Calibration word 2
 unsigned int result2 = 0;
 byte inbyte2 = 0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.setDataMode(1);
 SPI.transfer(0x1D);
 SPI.transfer(0x60);
 SPI.setDataMode(0);
 result2 = SPI.transfer(0x00);
 result2 = result2 <<8;
 inbyte2 = SPI.transfer(0x00);
 result2 = result2 | inbyte2;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Calibration word 2 =");
 Serial.println(result2);  
 
 //Calibration word 3
 unsigned int result3 = 0;
 byte inbyte3 = 0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.setDataMode(1);
 SPI.transfer(0x1D);
 SPI.transfer(0x90);
 SPI.setDataMode(0);
 result3 = SPI.transfer(0x00);
 result3 = result3 <<8;
 inbyte3 = SPI.transfer(0x00);
 result3 = result3 | inbyte3;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Calibration word 3 =");
 Serial.println(result3);  
 
 //Calibration word 4
 unsigned int result4 = 0;
 byte inbyte4 = 0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.setDataMode(1);
 SPI.transfer(0x1D);
 SPI.transfer(0xA0);
 SPI.setDataMode(0);
 result4 = SPI.transfer(0x00);
 result4 = result4 <<8;
 inbyte4 = SPI.transfer(0x00);
 result4 = result4 | inbyte4;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Calibration word 4 =");
 Serial.println(result4);
 
 //Temperature:
 unsigned int tempMSB = 0;
 byte tempLSB =0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.setDataMode(1);
 SPI.transfer(0x0F);
 SPI.transfer(0x20);
 delay(30);
 SPI.setDataMode(0);
 tempMSB = SPI.transfer(0x00);
 tempMSB = tempMSB <<8;
 tempLSB = SPI.transfer(0x00);
 tempMSB = tempMSB | tempLSB;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Temperature raw =");
 Serial.println(tempMSB);
 
 
 //Pressure:
 unsigned int presMSB = 0;
 byte presLSB =0;
 digitalWrite (chipSelectPin, LOW);  
 SPI.setDataMode(1);
 SPI.transfer(0x0F);
 SPI.transfer(0x40);
 delay(30);
 SPI.setDataMode(0);
 presMSB = SPI.transfer(0x00);
 presMSB = presMSB <<8;
 presLSB = SPI.transfer(0x00);
 presMSB = presMSB | presLSB;
 digitalWrite(chipSelectPin, HIGH);
 Serial.print("Pressure raw =");
 Serial.println(presMSB);
 
 
 delay(10000);
}

First it looked quite good, then I extracted the calibration factors (5422, 2908, 702, 366, 1202, and 27) from the calibration words (43378, 55058, 44978, and 46875) and I am pretty far away from the usual values in the datasheet. But who cares taking in account that the pressure and temperature reading is overflowing (both 65535)?
I am pretty sure my wiring is ok; the OSC signal is quite low (~0,2V), is that ok? I get it from pin 2 of a DS1307. Shall I better generate a signal with an I/O-pin? The 47µF Tn cap is not very close to the pins (~5 cm).
Thanks in advance, nice weekend to all!

PS: SPI.setDataMode is not really doing anything. Doesn't matter if it is there or not or the other way 'round.
PPS: Tried another sensor. Different values, but in the same range. Obviously my code does not work.
The workflow for the temp and pressure values is wrong, but I don't know how to do this:
Quote
Two additional clocks at SCLK are required after the acknowledge signal. Then SCLK is to be held low by the microcontroller until a high to low transition on DOUT indicates the end of the conversion.
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 06, 2011, 09:08 pm
Hi all, as you see, it is really somehow work in progress...
I implemented a clock generated as described here:  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1271194241 (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1271194241). Basically I inserted
Code: [Select]

const int clock = 9;
...
pinMode(clock, OUTPUT);

and
Code: [Select]

TCCR1B = (TCCR1B & 0xF8) | 1 ;
analogWrite (clock, 128) ;

Now I have a beautiful clock signal and if I am asking for the values I get everything as befor except the temperature reading, which now changes between 65535 and 32767.
OK then, what now? 8)
Nice weekend to all of you!
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 12, 2011, 08:37 pm
Hi, here is a new version of the code.
Code: [Select]
/*
  MS5541 Pressure Sensor Display

Circuit:
MS5541 sensor attached to pins 10 - 13:
MOSI: pin 11
MISO: pin 12
SCK: pin 13
MCLK: pin 9

Voltage divider converts 5V to 3.3V on all lines except MISO

created 4 August 2011
by SMStrauch
*/

// library:
#include <SPI.h>

// MCKL signal pin
const int clock = 9;

void setup() {
  Serial.begin(9600);
  SPI.begin();
  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) ;
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
  delay(100);

  //Calibration word 1
  unsigned int result1 = 0;
  unsigned int inbyte1 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x50);
  SPI.setDataMode(SPI_MODE1);
  result1 = SPI.transfer(0x00);
  result1 = result1 << 8;
  inbyte1 = SPI.transfer(0x00);
  result1 = result1 | inbyte1;
  Serial.print("Calibration word 1 =");
  Serial.println(result1);
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Calibration word 2
  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); 
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Calibration word 3
  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); 

  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
   
  //Calibration word 4
  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);
 
  unsigned int c1 = 0;
  unsigned int c2 = 0;
  unsigned int c3 = 0;
  unsigned int c4 = 0;
  unsigned int c5 = 0;
  unsigned int c6 = 0;

  c1 = result1 >> 3 & 0x1FFF;
  c2 = ((result1 & 0x7) << 10) | ((result2 >> 6) & 0x3FF);
  c3 = (result3 >> 6) & 0x3FF;
  c5 = ((result2 & 0x3F) << 6) | (result3 & 0x3F);
  c4 = (result4 >> 7) & 0x7FF;
  c6 = result4 & 0x7F;

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

  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Temperature:
  unsigned int tempMSB = 0;
  unsigned int tempLSB = 0;
  SPI.transfer(0x0F);
  SPI.transfer(0x20);
  /*int ready = digitalRead (12);
  while (ready = 0)
  {
  delay (10);
  }*/
  delay(50);
  SPI.setDataMode(SPI_MODE1);
  tempMSB = SPI.transfer(0x00);
  tempMSB = tempMSB << 8;
  tempLSB = SPI.transfer(0x00);
  tempMSB = tempMSB | tempLSB;
  Serial.print("Temperature raw =");
  Serial.println(tempMSB);
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Pressure:
  unsigned int presMSB = 0;
  unsigned int presLSB =0;
  SPI.transfer(0x0F);
  SPI.transfer(0x40);
  delay(50);
  SPI.setDataMode(SPI_MODE1);
  presMSB = SPI.transfer(0x00);
  presMSB = presMSB << 8;
  presLSB = SPI.transfer(0x00);
  presMSB = presMSB | presLSB;
  Serial.print("Pressure raw =");
  Serial.println(presMSB);
 
 
  delay(10000);
}


I threw out all the ballast like chip select and Set.Data.Set since it did not make a real difference. Of course, with a couple of loops it will be leaner in the last version.
In the //temperature  paragraph I tried a while-loop to wait until the sensor indicates end of data conversion by pulling the Dout line down, but I still get all 1s. In the meantime I can not completely rule out any more that the sensor is working properly, although I connected a spare one and the values differ in strangeness a little, but are neither really better nor worse.
As a programing noob I really would appreciate every advice I can get. One doubt I have about the reset command is if it is really send as a 24bit block or if there are gaps between each byte. I suppose it is put together during compilation so three seperate command lines in the sketch are as good as on sequence of hex numbers in brackets? Thanks very much in advance
Have a nice weekend
Sebastian
PS I measured with my DSO Nano from Seeedstudio but I did not see movement on sckl nor dout, but I am sure I've choosen the wrong settings. What is the speed of the spi communication? In what resolution can I expect to see something?

PPS I replaced the code on Monday, 8/15,  with a new version since I found myself a couple of errors during the weekend. Calibration values are now well in the expected range. Speed is adapted. Still, the temp and pressure values are 11111111 11111111, so still no satisfaction. Come on, people! A tiny pressure sensor for about 30€ is a fantastic peripheral we really should make accessible for Arduino!  ;)
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 16, 2011, 04:15 pm
Hi there,
it works - somehow. Here the current version of the code:
Code: [Select]

/*
  MS5541 Pressure Sensor Display

Circuit:
MS5541 sensor attached to pins 10 - 13:
MOSI: pin 11
MISO: pin 12
SCK: pin 13
MCLK: pin 9

Voltage divider converts 5V to 3.3V on all lines except MISO

created 4 August 2011
by SMStrauch based on application note AN510 from www.intersema.ch
*/

// library:
#include <SPI.h>

// MCKL signal pin
const int clock = 9;

void setup() {
  Serial.begin(9600);
  SPI.begin();
  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) ;
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
  delay(100);

  //Calibration word 1
  unsigned int result1 = 0;
  unsigned int inbyte1 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x50);
  SPI.setDataMode(SPI_MODE1);
  result1 = SPI.transfer(0x00);
  result1 = result1 << 8;
  inbyte1 = SPI.transfer(0x00);
  result1 = result1 | inbyte1;
  Serial.print("Calibration word 1 =");
  Serial.println(result1);
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Calibration word 2
  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); 
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Calibration word 3
  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); 

  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
   
  //Calibration word 4
  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);

  unsigned int c1 = result1 >> 3 & 0x1FFF;
  unsigned int c2 = ((result1 & 0x7) << 10) | ((result2 >> 6) & 0x3FF);
  unsigned int c3 = (result3 >> 6) & 0x3FF;
  unsigned int c5 = ((result2 & 0x3F) << 6) | (result3 & 0x3F);
  unsigned int c4 = (result4 >> 7) & 0x7FF;
  unsigned int c6 = result4 & 0x7F;

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

  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Temperature:
  unsigned int tempMSB = 0;
  unsigned int tempLSB = 0;
  unsigned int D2 = 0;
  SPI.transfer(0x0F);
  SPI.transfer(0x20);
  delay(50);
  SPI.setDataMode(SPI_MODE1);
  tempMSB = SPI.transfer(0x00);
  tempMSB = tempMSB << 8;
  tempLSB = SPI.transfer(0x00);
  D2 = tempMSB | tempLSB;
  Serial.print("Temperature raw =");
  Serial.println(D2);
 
  //RESET
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
 
  //Pressure:
  unsigned int presMSB = 0;
  unsigned int presLSB =0;
  unsigned int D1 = 0;
  SPI.transfer(0x0F);
  SPI.transfer(0x40);
  delay(50);
  SPI.setDataMode(SPI_MODE1);
  presMSB = SPI.transfer(0x00);
  presMSB = presMSB << 8;
  presLSB = SPI.transfer(0x00);
  D1 = presMSB | presLSB;
  Serial.print("Pressure raw =");
  Serial.println(D1);
 
  //calculation of the real values
  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;
  const long PCOMP = (SENS * (D1 - OFF) >> 12) + 1000;
  const 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(10000);
}


I get this on the serial monitor:
Quote

Calibration word 1 =21788
Calibration word 2 =35364
Calibration word 3 =24837
Calibration word 4 =28726
2723
4648
388
224
2309
54
Temperature raw =28204
Pressure raw =14665
Real Temperature in °C=17.00
Compensated pressure in mbar =5561
2nd order compensated temperature in °C =17.00

Temperature is fine. Pressure is wrong and increases with every new measurement. Any thoughts?
Thank you.
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Aug 16, 2011, 06:21 pm
You really should consider creating functions to reduce memory  e.g. reset()

Quote
Pressure is wrong and increases with every new measurement. Any thoughts?

Can you post a sequence of values you got?
Is the difference between two consecutive readings (nearly) constant ?

Formulas in the code are "quite complex" but I see no reason in the code.
Can it be that the sensor does not reset properly?
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 16, 2011, 10:25 pm
Hi Rob,
once the code runs well I will make it slim.
In the annex is a graph of a 107 s measurement. I think my problem is in the wiring and not so much in the software, what o you think? I touched the sensor to generate some pressure at the point where the values drop. Even so they are quickly stable again, the compensated values climbs up to fall again...
I checked the formulas twice today, they are ok.
How could I check if the sensor resets?
Thanks
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Aug 17, 2011, 12:38 am
Found a datasheet at: - http://www.thaieasyelec.net/archives/Manual/MS5541-CM.pdf -
3,3Volt?

I checked your code with the datasheet especially the formulas for the 6 correction factors.

your code:
Code: [Select]

  unsigned int c1 = result1 >> 3 & 0x1FFF;
  unsigned int c2 = ((result1 & 0x7) << 10) | ((result2 >> 6) & 0x3FF);
  unsigned int c3 = (result3 >> 6) & 0x3FF;
  unsigned int c5 = ((result2 & 0x3F) << 6) | (result3 & 0x3F);
  unsigned int c4 = (result4 >> 7) & 0x7FF;
  unsigned int c6 = result4 & 0x7F;


If I read the datasheet correctly ( figure Page 12)
There is a small diff in c4  (TCO), it need another mask than in your code, but that cannot cause such a problem.
c4 is used to calculate the compensated pressure.

Code: [Select]

  long c1 = (result1 >> 3) & 0x1FFF;    //SENST1
  long c2 = ((result1 & 0x0007) << 10) | ((result2 >> 6) & 0x03FF);  // OFFT1
  long c3 = (result3 >> 6) & 0x03FF;  // TCS
  long c4 = (result4 >> 7) & 0x01FF;  // TCO  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  long c5 = (result2 & 0x003F) << 6  | (result 3 & 0x003F); // Tref
  long c6 = result4 & 0x007F;  // TEMPSENS


If I read the formulas correctly the math needs long (32 bits) for intermediate results, so I made the correction factors long so the CPU does the math with enough bits.
(Too few bits could cause overflow => strange results)

Please give it a try..


Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 17, 2011, 01:41 am
OMG, it works! Thanks man, thanks a lot!
It seems to have been the "long"-thing, because first I changed the "0x7FF" to "0x1FF" with no effect.
But now: joya! Pressing the sensor increased the value nicely, releasing it made it go back to 1007 mbar immediately.
OK; now I will try to create a library and some loops to make it a little more neat.
Again, thanks a lot!
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Aug 17, 2011, 01:49 am
And show us a new graph !!

If you want feedback on the library don't hesitate to ask (don't have such sensor but written/optimized a few small libs)
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 17, 2011, 06:11 pm
Hi,
here is the new graph. You see nicely when I touched and squeezed it and how the temperature rises and slowly falls again.
Title: MS5541 depth sensor communication via ISP - working
Post by: godo on Aug 25, 2011, 07:35 pm
Hi all,
I wrapped up the code and commented it out. To close the case I will post a sketch to read out all calibration words and one which shows how to include the extracted calibration factors into a sketch to avoid reading these constants all the time while using the sensor in whatever application.
MS5541_read_all.pde
Code: [Select]

/*
MS5541 Pressure Sensor calwords readout
This program will read your MS5441 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:
MS5541 sensor attached to pins 10 - 13:
MOSI: pin 11
MISO: pin 12
SCK: pin 13
MCLK: pin 9
CS is not in use, but might be pin 10

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. Thanks!
*/

// 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);
}



PS: Un-voided the resetsensor call as of today, Nov 25 2011.
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 25, 2011, 07:37 pm
.... and just because it was to much to put it in one post:


MS5541_demo.pde
Code: [Select]

/*
MS5541 Pressure Sensor demonstration sketch
To obtain the calibration factors run the read-calwords-sketch before.

Circuit:
MS5541 sensor attached to pins 10 - 13:
MOSI: pin 11
MISO: pin 12
SCK: pin 13
MCLK: pin 9
CS is not in use, but might be pin 10
 
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. Thanks!
*/

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

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

//include the calibration factors according to your individual sensor; they MUST be long for internal calculation of the compensated values
//intersema.ch provides a file with expected values
const long c1 = 2723;
const long c2 = 4648;
const long c3 = 388;
const long c4 = 224;
const long c5 = 2309;
const long c6 = 54;

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();
 SPI.setBitOrder(MSBFIRST);
 SPI.setClockDivider(SPI_CLOCK_DIV32); //divide 16 MHz to communicate on 500 kHz
 pinMode(clock, OUTPUT); //sets clockpin on output
}

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

 void resetsensor(); //resets the sensor, be aware SPI remains in Mode 0 afterwards!

 //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á!

 void 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 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;
 //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("Real Temperature [°C]=");
 Serial.println(TEMPREAL);

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

 Serial.print("2nd order compensated temperature [°C] =");
 Serial.println(TEMPCOMP);  

 delay(5000);
}



Any comments are welcome, and please tell me about your applications with the sensor.
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Aug 25, 2011, 08:30 pm
¡Bien hecho ;)

Might include the link to the datasheet in the code
Title: Re: MS5541 depth sensor communication
Post by: godo on Aug 25, 2011, 08:47 pm
¡Muchas gracias!
Links are in.
Title: Re: MS5541 depth sensor communication II
Post by: godo on Oct 12, 2011, 03:37 pm
Hi folks,
and on it goes: I have a new riddle to solve!
Since my project requires quite some memory I decided to upgrade and made myself a neat little Sanguino clone board. It works nicely, I downloaded and installed awesome stuff from here http://avr-developers.com/corefiles/index.html (http://avr-developers.com/corefiles/index.html) and some Sanguino board data I do not remember from where. It runs both with the Ardu-Duino 644P and Sanguino board settings (but that's probably obvious).
Then I tested sketches I already used on my 2009 as this one... no wait, it is far to long. It is the AnalogLogger example from the SdFat-library which I adapted and added a DS18B20. Unfortunately I only figured out the code formally and adapted it without deep understanding. But it runs like a charm logging 4 analog inputs and digital temperature via SPI onto a µSD-Card. So far so good.
Now comes the riddle: I also adapted the code I displayed in this post but it won't work. There aren't even osci-spikes on the SCK line which I clearly saw running the SdFat-based code. So to me it looks like the sketch doesn't access the SPI-Bus at all, even though I adjusted the PINs to the right ones on the 644 (SS 4, MOSI 5, MISO 6, SCK 7). So - more of a general understanding question - where exactly does the SdFat library access the information about the PIN configuration? And where do I have to give the SPI library that information (I copied and included ArduinoPins.h from the SdFat diractory, but it didn't help)?
Can anybody tell me more about the compiling process, I mean, by selecting a specific board, do I already direct the compiler to a specific file in which the PIN configuration is given or do the respective libraries do that independently of the board I chose; it seems to me a valuable general info and a good point to look for the problem.
Thanks in advance, any comment is apreciated, greetings from Patagonia
Seb

PS: Problem solved with help from Nick. If you modify a .h-file NEVER copy-paste the code but type it. If copy-pasted the changes are visible, appear totally normal but the compiler does not read it properly.
Title: Re: MS5541 depth sensor communication
Post by: buton on May 07, 2012, 04:18 pm
Hey this is great I just bought the sensor and it is pretty small, how did you manage to solder it, any recommendations?

What did you use for the 32.768. khz clock? I bought t a DS32khz/ 14-dip .. http://www.maxim-ic.com/datasheet/index.mvp/id/2940
I will be using an arduino pro mini for the 3.3 volts that the sensor requires.

I will be use this a diving depth logger..

So I will keep you inform.

Thanks for the code I will try it, any more tips?
Title: Re: MS5541 depth sensor communication
Post by: godo on May 07, 2012, 04:46 pm
Hi there,
soldering that little one is a royal pain in the ... soldering hand, I can tell you. End of this week I will try it with a reflow oven, but up to now I managed with no clean flux and a lot of patience. Good luck anyway; if you use SPI for datalogging you will have to put a 74HC125 or so into the DOUT line to avoid interfering of the sensor with the sd-card. And THAT one is a demanding little bugger to solder!
This codeline
Code: [Select]
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (clock, 128) ;
takes care of the signal on pin 9. It is not possible to use any pin but the timer pin, so do not simply switch it. It will allow you to skip the extra chip, so it might be an elegant possibility to keep it all small.
Good luck and share your progress and chalenges, by all means!
Title: Re: MS5541 depth sensor communication
Post by: buton on May 07, 2012, 07:16 pm
Thanks for the info..

did you ever tried to do it without using the SPI? i don really want to add the 74HC125...but i will have to try it.. or maybe storing values in an external memory and then export it through serial port will be another idea..

i will keep you posted..
Title: Re: MS5541 depth sensor communication
Post by: buton on May 10, 2012, 05:18 am
it was quite a challenge to solder this but and i do not if i broke the sensor for over-heating XD

this is what i go on the serial port when reading the calibration words...


Calibration word 1 =18820
Calibration word 2 =35237
Calibration word 3 =22501
Calibration word 4 =27826
2352
4646
351
217
2405
50
Temperature raw =65535
Pressure raw =65535
Real Temperature in °C=285.00
Compensated pressure in mbar =-209082
2nd order compensated temperature in °C =285.00


some of the values are pretty similar to yours...

but the temperature somehow is not working.. another interesting think is that i am using a 8 MHZ  arduino not the 16....

so i wonder if the divider is set correctly for the frequency...

thanks
Title: Re: MS5541 depth sensor communication
Post by: buton on May 10, 2012, 06:21 am
second try i hooked the 32.768 khz clock i bought directly to the sensor and things got better

first reading is good, second reading is bad...


Temperature raw =30027
Pressure raw =2047
Real Temperature [°C]=31.00
Compensated pressure [mbar] =-12747
2nd order compensated temperature [°C] =31.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.00
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00

i reset and put my finger and temperature increases
Title: Re: MS5541 depth sensor communication
Post by: buton on May 10, 2012, 04:50 pm

second try i hooked the 32.768 khz clock i bought directly to the sensor and things got better

first reading is good, second reading is bad...


Temperature raw =30027
Pressure raw =2047
Real Temperature [°C]=31.00
Compensated pressure [mbar] =-12747
2nd order compensated temperature [°C] =31.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.00
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00

i reset and put my finger and temperature increases



I solder it again and it is working perfect

thank you man..

the diving community really appreciate your effort

Temperature raw =29659
Pressure raw =14623
Real Temperature [°C]=28.00
Compensated pressure [mbar] =981
2nd order compensated temperature [°C] =28.00
Title: Re: MS5541 depth sensor communication
Post by: godo on May 10, 2012, 09:56 pm
Great, congratulations!
Let me know if you by chance modify the code, because for some reason it only gives X.00 (point zero) temperature values and I would like to have a better resolution.
It is great to contribute to the community after I received so much help and advice, I am very happy to share!
Title: Re: MS5541 depth sensor communication
Post by: buton on May 12, 2012, 08:41 pm

Great, congratulations!
Let me know if you by chance modify the code, because for some reason it only gives X.00 (point zero) temperature values and I would like to have a better resolution.
It is great to contribute to the community after I received so much help and advice, I am very happy to share!


i think that i got it

change the calculation of the temeperature to double

Code: [Select]
const double TEMP = 200 + ((dT * (c6 + 100)) >> 11);

double TEMPREAL = TEMP/10;


:)

Title: Re: MS5541 depth sensor communication
Post by: godo on May 14, 2012, 09:49 am
Wow, great, that is a bit of a surprise though, because:
Quote
The double implementation on the Arduino is currently exactly the same as the float, with no gain in precision.

But, on the other hand:
Quote
Users who borrow code from other sources that includes double variables may wish to examine the code to see if the implied precision is different from that actually achieved on the Arduino.

I will try that asap, thanks!
Title: Re: MS5541 depth sensor communication
Post by: buton on May 26, 2012, 04:08 am
I realized that having the microsd card and the sensor on the same buss will be too complicated due to the libray SDFAT.. and i dont want to add another IC

so i was thingking about doing some bit banging to get the data...

somehow i got it to work(i think)  the reset and pressure conversion sequence works because i am getting data

where i am having problems is on the reading, no reading the correct raw value...how ever if i manually press the sensor with my finger... i start getting numbers...also if i modify the delay on the clk while reading it also changes... :)

godo please helpme out if you see something weird.. i almost follow the datasheet and some insights of you spi code..

Code: [Select]



word start=0b1111010000000000;//start sequence
unsigned int p1,p2;
long reset=0b10101010101010100000000000000000;//reset sequence
byte counts;//for debug
int dout= 2;//pin for data out MOSI
int din=3;//pin for data in MISO
int clk=4;//data clock
boolean data=0;


void setup() {               
  // initialize the digital pin as an outputand input
 
  Serial.begin(9600);
  pinMode(dout, OUTPUT);     
    pinMode(din, INPUT); 
   pinMode(clk,OUTPUT);
 
}

void loop() {
  pressure();   //main function
  delay(3000);              // wait for a second
}

void pressure()
{
  Serial.println("start Reset");
  //---start REset sequence...
        for(int i=31;i>10;i--)
        {
         
          boolean x;
         
          x=bitRead(reset,i);
       
         
          digitalWrite(dout,x);
           digitalWrite(clk,HIGH);
            digitalWrite(clk,LOW);
        }
   
  //--------Start Conversion sequence
    for(int i=15; i>5;i--)   
    {
               
                       boolean x;
                       x=bitRead(start,i);
                       digitalWrite(dout,x);               
                       //--DRIVE CLOCK
                       digitalWrite(clk,HIGH);
                       digitalWrite(clk,LOW);   
                               
                                       
                               
                               
   }
               
         
         
   //wait unti conversion
    // i keep runing the clock and wait until the Din(miso) detects that it went to 0 and the data is ready
   
     data=  digitalRead(din);
    while(data==1)
   
    {
     
      digitalWrite(clk,HIGH);   
      digitalWrite(clk,LOW);
      data=digitalRead(din);
     
     
    }
   //------------


//---start reading
    //Serial.println("Read raw pressure");
     
        for(int i=16; i>=0;i--)
            {
                 digitalWrite(clk,HIGH);    // drive the clock down     
                 delay(10);       
                 digitalWrite(clk,LOW);
                 delay(10);
                 data= digitalRead(din);// i read on low cycle de input(output of the sensor)
                  if(data==1)
                  {
                   
                    bitWrite(p1,i,1);// write the value and i index the int to the right..
             
                    }
                 else
                 {
                bitWrite(p1,i,0);
             
                   
                 }
                 
              counts++;
            }
     
     
     
     
   
   
    //testing to see if shifting will help also
  Serial.println(p1);
  p2=p1>>1;
 
  Serial.println(p2);
  Serial.println(counts);//test to se how many times went into for cycle
  counts=0;
 
}

Title: Re: MS5541 depth sensor communication
Post by: buton on Jun 05, 2012, 04:23 am
well i added the 74hc125 and it is workign

take a look

http://www.youtube.com/watch?v=xZsiV52b0B0&feature=youtu.be (http://www.youtube.com/watch?v=xZsiV52b0B0&feature=youtu.be)
Title: Re: MS5541 depth sensor communication
Post by: godo on Jun 06, 2012, 09:30 am
Hey buton,
sorry, I did not see your previous post. I am impressed of your code, I myself have no idea about bit banging. Way to go, I saw your video, very nice.
At work I use the MS5803 sensor which is also very interesting, same size, but with both an I2C and SPI interface. And you could actually use the logging device for climbing as well ;-)
So keep us updated about the mechanical work which is coming up, especially how to get the sensor sealed and water tight.
Greetings
Title: Re: MS5541 depth sensor communication
Post by: buton on Jul 06, 2012, 08:14 pm
i tried to put today the sensor in a hole and then put some sillicon but i broke it  :smiley-fat:

i order two more just in case, i will try them out next week in a 9 feet pool, and take some video... i just want to finish the ugly prototype get the software running and then i will focus in getting a quote for and actual board//shield  for the "DIVE-DUINO"... still a lot of work to do.
Title: Re: MS5541 depth sensor communication
Post by: godo on Jul 06, 2012, 09:54 pm
Oh no, that's bad, we did something similar two days ago, a catastrophic leakage in the sensor housing... man, I thought the programing was the toughest part, but no!
So good luck and don't give up!
Cheers
Seb
Title: Re: MS5541 depth sensor communication
Post by: buton on Jul 11, 2012, 03:33 pm
i got the new sensor i ordered, i soldered it it did not work with the software already compiled.. it was weird.. so then i tried you example about the calibration factors and it work, then i compile the second version without the calibration factors and it did not work...

i dont know is weird...

so  i finally made it to work but i am unsure what was the issue becuase is the SAME CODE...
Title: Re: MS5541 depth sensor communication
Post by: huberrob on Aug 22, 2012, 01:57 pm
Dear godo, dear buton,

I also play with a similar sensor, the MS5535 which I intend to use for a basic underwater mini observatory and your work was of great help for me! I am using a arduino adk board and my plan was to use a Andrid phone to store and transfer the data. However, it seems as if the USB host of this board conflicts with SPI ... I assume this is a similar case like the SD card pin conflict. In an earlier post godo proposed to
Quote
put a 74HC125 or so into the DOUT
. This might also be the solution for my problem however I have no idea how to assemble that, it would be very nice if you could post an image or similar of the circuit?
Godo also mentioned he was playing with another sensor, the MS5803, do you know a reseller of that product?

best regards,
Robert
Title: Re: MS5541 depth sensor communication
Post by: buton on Sep 01, 2012, 04:04 am
so i made this my little after hour hobbie...

look at

www.diveduino.com

i have some videos and pictures in there about how it is going



huberrob i suggest you take a look at OpenLog https://www.sparkfun.com/products/9530 (https://www.sparkfun.com/products/9530) this will make your life easier at some cost lol
Title: Re: MS5541 depth sensor communication
Post by: buton on Sep 01, 2012, 05:31 am
http://youtu.be/YKzSPx77WTg
Title: Re: MS5541 depth sensor communication
Post by: buton on Sep 11, 2012, 06:14 pm
this is a pool test with Diveduino i did last weekend... it worked really good

https://www.youtube.com/watch?v=iIIexUNN6bE&feature=youtube_gdata_player

https://www.youtube.com/watch?v=iIIexUNN6bE&feature=youtube_gdata_player
Title: Re: MS5541 depth sensor communication
Post by: huberrob on Sep 13, 2012, 09:48 am
Dear buton or godo,

Quote
huberrob i suggest you take a look at OpenLog https://www.sparkfun.com/products/9530 this will make your life easier at some cost lol

thank you very much for this hint and I will consider to use this as a data backup.
However, as I mentioned before I intend to use a Android phone for data transmission and the SPI sensor communication seems to conflict with the USB of the Mega ADK board this was the reason why I was asking for assitance in using the 74HC125.. any advice on that would be very welcome..

best regards,
Robert
Title: Re: MS5541 depth sensor communication
Post by: buton on Nov 06, 2012, 03:45 pm
if someone is looking into this sensor i made this breakout board

http://youtu.be/TRuqvO_s07A


you can now solder it...
Title: Re: MS5541 depth sensor communication
Post by: bilaouras on Mar 17, 2013, 12:18 am
Hello everyone.
I am new to this forum and arduino programmer too.
Iam bought a mini board arduino http://www.digikey.gr/search/en/A000005/1050-1001-ND?recordId=2638989&keywords=arduino
and the sensor http://www.digikey.gr/search/en?refPId=1&homePageRef=homePage&lang=en&site=gr&keywords=MSP3101P3-ND&x=9&y=19

I found this post about depth sensor so i post my question.
I have a project who it is necessary to take the information from the sensor (in meters) and sent a command to one of outputs e.g to move one servo when to depth measures for example 2 meters etc.
Where can i found a code similar to that?
Thanks and sorry if i hijack this thread,
bilaouras


Title: Re: MS5541 depth sensor communication
Post by: bilaouras on Mar 17, 2013, 08:07 pm
No one?
Title: Re: MS5541 depth sensor communication
Post by: buton on Mar 23, 2013, 01:20 am
your sensor is completely different, according to the data sheet this has an analog output which you will have to read with the arduino ADC..
Title: Re: MS5541 depth sensor communication
Post by: sin91 on Apr 18, 2013, 11:06 pm
Hi,

I have found this thread really useful and I am looking at using a MS5535C pressure sensor with and Arduino.

I am wanting to record the data from the sensor on to an SD card and have a Adafruit Assembled Data Logging shield for Arduino, this has a built in RTC which is used to time stamp the data on the SD card and I will also use it to drive the CLK on my sensor.

I read about the use of the SD library and the chip select pin being an issue with other data loggers, I am trying to figure out if this will be a problem with the data logging shield I have?

Thanks
Title: Re: MS5541 depth sensor communication
Post by: bigplik on Jan 01, 2015, 11:09 pm
second try i hooked the 32.768 khz clock i bought directly to the sensor and things got better

first reading is good, second reading is bad...


Temperature raw =30027
Pressure raw =2047
Real Temperature [°C]=31.00
Compensated pressure [mbar] =-12747
2nd order compensated temperature [°C] =31.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.00
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00

i reset and put my finger and temperature increases

hi, I am new on the forum, I play with arduino about few months,
now I want to make my MS5541 pressure sensor working,
I've used code from above of this page of this topic,
and made this conversion

"const double TEMP = 200 + ((dT * (c6 + 100)) >> 11);

double TEMPREAL = TEMP/10;"

but it isn't working well,
I have that readings:

"
Temperature raw =29549
Pressure raw =2047
Real Temperature [°C]=28.00
Compensated pressure [mbar] =-12646
2nd order compensated temperature [°C] =28.00
Temperature raw =49151
Pressure raw =2047
Real Temperature [°C]=175.40
Compensated pressure [mbar] =-16794
2nd order compensated temperature [°C] =175.00
"

could you help me how to set it
properly?
I made wires connection as it is in description
of the code
Title: Re: MS5541 depth sensor communication
Post by: nipzwick on Mar 23, 2015, 06:29 pm
Edited the library MS5541.cpp file for mega2560 and uno use.

#define mega2560 1 //if using mega2560 assign 1, UNO assign 0


if(mega2560 == 1){
      TCCR2B = (TCCR2B & 0xF8) | 1 ;
      analogWrite(9, 128);

}else{
      TCCR1B = (TCCR1B & 0xF8) | 1 ;
      analogWrite(9, 128);
}


Code: [Select]

#include <SPI.h>
#include "MS5541.h"
#define mega2560 1 //if using mega2560 assign 1, UNO assign 0

MS5541::MS5541() {
SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV32); //divide 16 MHz to communicate on 500 kHz
  pinMode(9, OUTPUT);
  getCalibrationWord();
}

void MS5541::resetSensor() {
SPI.setDataMode(SPI_MODE0);
SPI.transfer(0x15);
SPI.transfer(0x55);
SPI.transfer(0x40);
}

void MS5541::update() {


if(mega2560 == 1){
TCCR2B = (TCCR2B & 0xF8) | 1 ;
analogWrite(9, 128);

}else{
TCCR1B = (TCCR1B & 0xF8) | 1 ;
analogWrite(9, 128);
}

//Pressure:
resetSensor();
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
 
//Temperature
resetSensor();
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

//calculate temp according to datasheet
dT = D2 - UT1;
if (dT < 0) {
dT2 = dT - (dT/128*dT/128)/2;
}
else {
dT2 = dT - (dT/128*dT/128)/8;
}

TEMP = (200 + dT*(C6+100)/pow(2,11))/10;
TEMPC = (200 + dT2*(C6+100)/pow(2,11))/10;

//calculate pressure according to datasheet
OFF = C2 + ((C4-250)*dT)/pow(2,12) + 10000;
SENS = C1/2 + ((C3+200)*dT)/pow(2,13) + 3000;
P = (SENS * (D1-OFF))/pow(2,11) + 1000;
}

float MS5541::getPressureMBar() {
return P;
}

float MS5541::getPressureBar() {
return P/1000.0;
}


float MS5541::getTemperatureC() {
return TEMP;
}

float MS5541::get2ndTemperatureC() {
return TEMPC;
}

float MS5541::getTemperatureF() {
return (TEMP*1.8)+32.0;
}

float MS5541::get2ndTemperatureF() {
return (TEMPC*1.8)+32.0;
}

void MS5541::getCalibrationWord() {
if(mega2560 == 1){
TCCR2B = (TCCR2B & 0xF8) | 1 ;
analogWrite(9, 128);

}else{
TCCR1B = (TCCR1B & 0xF8) | 1 ;
analogWrite(9, 128);

}

resetSensor();
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

resetSensor();
SPI.transfer(0x1D);
SPI.transfer(0x60);
SPI.setDataMode(SPI_MODE1);
result2 = SPI.transfer(0x00);
result2 = result2 <<8;
inbyte2 = SPI.transfer(0x00);
result2 = result2 | inbyte2;

resetSensor();
SPI.transfer(0x1D);
SPI.transfer(0x90);
SPI.setDataMode(SPI_MODE1);
result3 = SPI.transfer(0x00);
result3 = result3 <<8;
inbyte3 = SPI.transfer(0x00);
result3 = result3 | inbyte3;

resetSensor();
SPI.transfer(0x1D);
SPI.transfer(0xA0);
SPI.setDataMode(SPI_MODE1);
result4 = SPI.transfer(0x00);
result4 = result4 <<8;
inbyte4 = SPI.transfer(0x00);
result4 = result4 | inbyte4;

C1 = result1 >> 3 & 0x1FFF;
C2 = ((result1 & 0x07) << 10) | ((result2 >> 6) & 0x03FF);
C3 = (result3 >> 6) & 0x03FF;
C4 = (result4 >> 7) & 0x07FF;
C5 = ((result2 & 0x003F) << 6) | (result3 & 0x003F);
C6 = result4 & 0x007F;
UT1 = 8*C5 + 10000;
}
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 21, 2015, 04:47 pm
Hi,

I am using a version of the library that I changed to work with MS5535 sensor.
I am using it with Teensy 3.1 and AdafruitST7735 TFT. The problems I have are not being able to read data from the pressure sensor as soon as I want to use the TFT.

Code: [Select]
#define sclk 13  // SCLK can also use pin 14
#define mosi 11  // MOSI can also use pin 7
#define cs   10  // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define dc   9   //  but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define rst  8   // RST can use any pin
#define sdcs 4   // CS for SD card, can use any pin
#define lite 5   // TFT backlite
#define presscs 6 // Pressures sensor cs
#define miso 12 //MISO

#include <MS55xx.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

#if defined(__SAM3X8E__)
   #undef __FlashStringHelper::F(string_literal)
   #define F(string_literal) string_literal
#endif

//Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);

//creating the sensor

MS55xx PressSensor;
float airPressure;
float waterPressure=0;

void setup() {
   pinMode(sdcs, INPUT_PULLUP);  
   Serial.begin(9600);    
   pinMode(presscs, OUTPUT);
   digitalWrite(presscs, HIGH);      
   pinMode(5, OUTPUT);
   digitalWrite(5, HIGH);
   pinMode(23, OUTPUT);
   digitalWrite(23, HIGH);
   
   tft.initR(INITR_BLACKTAB);
   tft.setRotation(tft.getRotation()+1);
   tft.fillScreen(ST7735_BLACK);
   
   PressSensor.setPressureSensorType(5535);
   //start arduino before diving
   //otherwise a 1.0 bar is used as surface pressure
   digitalWrite(presscs, LOW);
   delay(10);
   PressSensor.update();
   digitalWrite(presscs, HIGH);
   airPressure = PressSensor.getPressureBar();
   if (airPressure > 1.2) {
     airPressure = 1.0;
   }
   tft.fillScreen(ST7735_BLACK);
}

void loop() {
 //Before getting the values you need to update the sensor
 digitalWrite(presscs, LOW);
 delay(10);
 PressSensor.update();
 digitalWrite(presscs, HIGH);
 //get pressure
 waterPressure = PressSensor.getPressureBar() - airPressure;
 Serial.print("Deep (meters): ");
 Serial.println(abs(waterPressure)*10.0,1);
 
 tft.setTextSize(2);
 tft.setCursor(0,0);
 tft.setTextColor(ST7735_GREEN);
 tft.println(abs(waterPressure)*10.0,1);
 
 //get 2nd temperature --> see datasheet for details
 Serial.print("Temperatre 2nd (celsius): ");
 //Serial.println(PressSensor.get2ndTemperatureC());
 
 Serial.println();
 
 delay(2000);
}


I added in library another line in both the Update() method and read Coeficients method the line
Code: [Select]

SPI.setDataMode(SPI_MODE0);
to alow AdafruitST7735 to work correctely.

Problem that remain is no correct data from pressure sensor.

Can anyone help?
Title: Re: MS5541 depth sensor communication
Post by: robtillaart on Aug 21, 2015, 07:37 pm
@IgorP
Can it be that you have not enough power?
Can you measure the voltage?
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 21, 2015, 08:14 pm
I think there should be more than enough power. TFT works fine, just data from pressure sensor not correct. I run Teensy from USB and sensor from Teensy 3.3 voltage output.

Was thinking about SCLK signal. SPI clock divider is set in TFT library to 21....don't kniw if that is not too high signal click for sensor..   skould be max 500kHz
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 21, 2015, 09:17 pm
I think there should be more than enough power. TFT works fine, just data from pressure sensor not correct. I run Teensy from USB and sensor from Teensy 3.3 voltage output.

Was thinking about SCLK signal. SPI clock divider is set in TFT library to 21....don't kniw if that is not too high signal click for sensor..   skould be max 500kHz
Anyway where should I measure power supply? At sensor or??
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 22, 2015, 03:39 am
Supply voltage to sensor is 3.2 V
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 22, 2015, 04:10 pm
I think it is CS problem, seem AdafruitST7735 is somehow preventing me from manualy manipulating CS for the sensor. As soon as I initialize the tft I lost sensor data. Does someone know how to solve this problem?

I attach the library and examples. The MS55xx eksample is MS5541 modified library to work with MS5535 too on Teensy 3.1 board. The example for mentioned problem is MA55xx_underwater_test
Title: Re: MS5541 depth sensor communication
Post by: IgorP on Aug 26, 2015, 06:42 pm
Adafruit updated thrir library per last standards in SPI communication and now I finaly have a solution iny hands. Will post links to the thread with updated ST7735 library and new version of MS55xx library updated to same standard.

Thanks to all that tried to behelpful!!

Title: Re: MS5541 depth sensor communication
Post by: abidhaque on Feb 04, 2016, 08:16 am
Hi,

I'm trying to use an ms5541-cm sensor with an arduino uno. I'm new to the forum, and would really appreciate some help.

I used the code from -

Hi all,
I wrapped up the code and commented it out. To close the case I will post a sketch to read out all calibration words and one which shows how to include the extracted calibration factors into a sketch to avoid reading these constants all the time while using the sensor in whatever application.
MS5541_read_all.pde
Code: [Select]

/*
 MS5541 Pressure Sensor calwords readout
 This program will read your MS5441 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:
 MS5541 sensor attached to pins 10 - 13:
 MOSI: pin 11
 MISO: pin 12
 SCK: pin 13
 MCLK: pin 9
 CS is not in use, but might be pin 10
 
 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. Thanks!
 */

// 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);
}



PS: Un-voided the resetsensor call as of today, Nov 25 2011.
But the calibration values keep fluctuating, and so do compensated temperature and pressure values.

Calibration word 1 =0
Calibration word 2 =0
Calibration word 3 =0
Calibration word 4 =65535
0
0
0
511
0
127
Temperature raw =0
Pressure raw =65535
Real Temperature in °C=-90.00
Compensated pressure in mbar =38782
2nd order compensated temperature in °C =-90.00
Calibration word 1 =65535
Calibration word 2 =65535
Calibration word 3 =65535
Calibration word 4 =65535
8191
8191
1023
511
4095
127
Temperature raw =0
Pressure raw =0
Real Temperature in °C=-454.00
Compensated pressure in mbar =-1685
2nd order compensated temperature in °C =-453.00
Title: Re: MS5541 depth sensor communication
Post by: hrishi104 on Apr 19, 2017, 03:05 pm
I know its silly question but i am not able to find register address for sensor can you please tell me from where you got this addressed in your code?

/Sensor memory register addresses:
const int PRESSURE = 0x0F;      //MSB pressure
const int PRESSURE_LSB = 0x40;  //LSB of pressure
const int TEMPERATURE = 0x0F;   //MSB temperature
const int TEMPERATURE_LSB = 0x20;  //LSB temperature
const int W1M = 0x1D; // MSB Calibration word 1
const int W1L = 0x50; // LSB Calibration word 1
const int W2M = 0x1D; // MSB Calibration word 2
const int W2L = 0x60; // LSB Calibration word 2
const int W3M = 0x1D; // MSB Calibration word 3
const int W3L = 0x90; // LSB Calibration word 3
const int W4M = 0x1D; // MSB Calibration word 4
const int W4L = 0xA0; // LSB Calibration word 4
const byte RST1 = 0x15; //Reset sequence word 1
const byte RST2 = 0x55; //Reset sequence word 2
const byte RST3 = 0x40; //Reset sequence word 3