MS5541 depth sensor communication

this is a pool test with Diveduino i did last weekend... it worked really good

Dear buton or godo,

huberrob i suggest you take a look at OpenLog SparkFun OpenLog - DEV-13712 - SparkFun Electronics 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

if someone is looking into this sensor i made this breakout board

you can now solder it...

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

No one?

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..

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

buton:
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

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

#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;
}

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.

#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

SPI.setDataMode(SPI_MODE0);

to alow AdafruitST7735 to work correctely.

Problem that remain is no correct data from pressure sensor.

Can anyone help?

@IgorP
Can it be that you have not enough power?
Can you measure the voltage?

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

IgorP:
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??

Supply voltage to sensor is 3.2 V

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

MS55xx_underwater_test.zip (6.19 KB)

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

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 -

godo:
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

/*

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

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