Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Depth Sensor Code - modified j.brian
/*
created August 2011
by SMStrauch and with help of robtillaart and ulrichard. Thanks!
Manufacturer: www.intersema.ch
Source: http://www.meas-spec.com/downloads/Using_SPI_Protocol_with_Pressure_Sensor_Modules.pdf
Source: http://forum.arduino.cc/index.php?topic=67188.0
Datasheet: http://media.digikey.com/pdf/Data%20Sheets/Measurement%20Specialties%20PDFs/MS5541-CM.pdf
Modified 2-10-2015 J.Brian
MS5541 Pressure Sensor calwords readout
This program will read your MS5441 or compatible pressure sensor every 5 seconds and show you:
calibration words
calibration factors
raw values
and compensated values of temperature and pressure
Assumed pressure and temp. range: 0...14 bar, -40...85°C
Pins:
MS5541 sensor attached to pins 9, 11 - 13:
SPI : Arduino Pin : MS5541
--------------------------
MOSI: 11 : DIN
MISO: 12 : DOUT
SCK : 13 : SCKL
MCLK: 9 : MCLK
CS : N/C(10) : N/A
Calibration Words 1-4 16-bit
Source: http://www.amsys.info/sheets/amsys.en.an518_e.pdf
Coefficients:
Name : Value : Bits : MIN : TYP : MAX : Variable Name :
C1 : Pressure Sensitivity : 13 : 0 : 2391 : 8191 : SENST1 :
C2 : Pressure Offset : 13 : 0 : 4888 : 8191 : OFFT1 :
C3 : Temp. Coef. of Press. Sensitivity : 10 : 0 : 385 : 1023 : TCS :
C4 : Temp. Coef. of Press. Offset : 9 : 0 : 221 : 511 : TCO :
C5 : Ref. Temp. : 12 : 0 : 1689 : 4095 : Tref :
C6 : Temp Coef. of Temp. : 7 : 0 : 58 : 127 : TEMPSENS :
Digital Pressure & Temp.:
Variable Name: Value : Bits : MIN : TYP : MAX :
D1 : Digital Pressure : 16 : 0 : 17000 : 40000 :
D2 : Digital Temperature : 16 : 0 : 27000 : 45000 :
Maximum Values for Calculation Results
Pmin = 0mbar
Pmax = 14bar
Tmin = -40°C
Tmax = +85°C
Tref = +20°C
: MIN : TYP : MAX :
UT1 = 8 * C5 + 10000 : 10000 : 28016 : 42760 :
dUT = D2 - UT1 : -11400 : 0 : 12350 :
** dTmin = (Tmin - Tref) * 190TLSB / °C
** dTmax = (Tmax - Tref) * 190TLSB / °C
OFF = C2 + 10000 + (C4-250) * dUT / 2^12 : 9246 : 14888 : 18887 :
** OFFmin = C2min + 10000 + (C4min - 250) * dTmax / 2^12
** OFFmax = C2max + 10000 + (C4max - 250) * dTmin / 2^12
SENS = C1 / 2 + (C3 + 200) * dUT / 2^13 + 3000 : 1298 : 4196 : 8939 :
**SENSmin = C1min / 2 + (C3max + 200) * dTmin / 2^13 + 3000
**SENSmax = C1max / 2 + (C3max + 200) * dTmax / 2^13 + 3000
P(0...14bar, with 1mbar resolution) : 0 : : 14000 :
TEMP = 200 + dT * (C6 + 100) / 2 ^ 11 : -400 : : 850 :
**(-40...85°C, with 0.1 °C resolution, in 0.1 °C units)
*/
// include library:
#include <SPI.h>
//*******************************************************************
//One of the following defines have to be uncommented but never both
//If Coeffecients have ben set:
#define CONSTANTS_SET true
//otherwise
//#define CALIBRATION true;
//********************************************************************
#ifdef CONSTANTS_SET
const long SENST1 = 63;
const long OFFT = 8077;
const long TCS = 386;
const long TCO = 234;
const long Tref = 2097;
const long TEMPSENS = 55;
#endif
#ifdef CALIBRATION
long SENST1 = 2723;
long OFFT = 4648;
long TCS = 388;
long TCO = 224;
long Tref = 2309;
long TEMPSENS = 54;
#endif
// generate a MCKL signal pin
const int clock = 9;
//Hex Values for writing to MS5541
byte D1_HIGH = 0x0F;
byte D1_LOW = 0x40;
byte D2_HIGH = 0x0F;
byte D2_LOW = 0x20;
byte W1_HIGH = 0x1D;
byte W1_LOW = 0x50;
byte W2_HIGH = 0x1D;
byte W2_LOW = 0x60;
byte W3_HIGH = 0x1D;
byte W3_LOW = 0x90;
byte W4_HIGH = 0x1D;
byte W4_LOW = 0xA0;
byte DUMMY = 0x00;
unsigned int word_1 = 0;
unsigned int word_2 = 0;
unsigned int word_3 = 0;
unsigned int word_4 = 0;
byte inByte_low = 0x00;
unsigned int D1 = 0;
unsigned int D2 = 0;
long UT1 = 0;
long dT = 0;
long TEMP = 0;
long OFF = 0;
long SENS = 0;
long PCOMP = 0;
float TEMPREAL = 0;
long dT2 = 0;
float TEMPCOMP = 0;
void Reset_Sequence_Command();
#ifdef CALIBRATION
void getCValues();
void getCalibrationWords();
#endif
void getDigitalValues();
void getRealValues();
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 & B11111000 | B00000001; //generates the MCKL signal
analogWrite(clock, 128) ;
#ifdef CALIBRATION
getCalibrationWords();
getCValues();
#endif
getDigitalValues();
getRealValues();
delay(500);
}
void Reset_Sequence_Command() {
SPI.setDataMode(SPI_MODE0);
SPI.transfer(0x15);
SPI.transfer(0x55);
SPI.transfer(0x40);
}
#ifdef CALIBRATION
void getCalibrationWords() {
//Calibration word 1
SPI.transfer(W1_HIGH);
SPI.transfer(W1_LOW);
SPI.setDataMode(SPI_MODE1);
word_1 = SPI.transfer(DUMMY);
word_1 = word_1 << 8;
inByte_low = SPI.transfer(DUMMY);
word_1 = word_1 | inByte_low;
Reset_Sequence_Command();//resets the sensor
//Calibration word 2;
SPI.transfer(W2_HIGH);
SPI.transfer(W2_LOW);
SPI.setDataMode(SPI_MODE1);
word_2 = SPI.transfer(DUMMY);
word_2 = word_2 << 8;
inByte_low = SPI.transfer(DUMMY);
word_2 = word_2 | inByte_low;
Reset_Sequence_Command();//resets the sensor
//Calibration word 3;
SPI.transfer(W3_HIGH);
SPI.transfer(W3_LOW);
SPI.setDataMode(SPI_MODE1);
word_3 = SPI.transfer(DUMMY);
word_3 = word_3 << 8;
inByte_low = SPI.transfer(DUMMY);
word_3 = word_3 | inByte_low;
Reset_Sequence_Command();//resets the sensor
//Calibration word 4;
SPI.transfer(W4_HIGH);
SPI.transfer(W4_LOW);
SPI.setDataMode(SPI_MODE1);
word_4 = SPI.transfer(DUMMY);
word_4 = word_4 << 8;
inByte_low = SPI.transfer(DUMMY);
word_4 = word_4 | inByte_low;
Serial.print("Calibration word 1 =");
Serial.println(word_1);
Serial.print("Calibration word 2 =");
Serial.println(word_2);
Serial.print("Calibration word 3 =");
Serial.println(word_3);
Serial.print("Calibration word 4 =");
Serial.println(word_4);
}
#endif
#ifdef CALIBRATION
void getCValues() {
//now we do some bitshifting to extract the calibration factors
//out of the calibration words; read datasheet AN510 for better understanding
SENST1 = word_1 >> 3 & 0x1FFF;
OFFT = ((word_1 & 0x07) << 10) | ((word_2 >> 6) & 0x03FF);
TCS = (word_3 >> 6) & 0x03FF;
TCO = (word_4 >> 7) & 0x07FF;
Tref = ((word_2 & 0x003F) << 6) | (word_3 & 0x003F);
TEMPSENS = word_4 & 0x007F;
Reset_Sequence_Command();
Serial.print("SENST1 (C1): ");
Serial.println(SENST1);
Serial.print("OFFT (C2): ");
Serial.println(OFFT);
Serial.print("TCS (C3): ");
Serial.println(TCS);
Serial.print("TCO (C4): ");
Serial.println(TCO);
Serial.print("Tref (C5): ");
Serial.println(Tref);
Serial.print("TEMPSENS (C6): ");
Serial.println(TEMPSENS);
}
#endif
void getDigitalValues() {
Reset_Sequence_Command();
//Pressure (D1):
SPI.transfer(D1_HIGH);
SPI.transfer(D1_LOW);
//delay(35);
SPI.setDataMode(SPI_MODE1);
D1 = SPI.transfer(DUMMY);
D1 = D1 << 8;
inByte_low = SPI.transfer(DUMMY);
D1 = D1 | inByte_low;
Serial.print("Pressure raw =");
Serial.println(D1);
Reset_Sequence_Command();
//Temperature (D2):
SPI.transfer(D2_HIGH);
SPI.transfer(D2_LOW);
//delay(35);
SPI.setDataMode(SPI_MODE1);
D2 = SPI.transfer(DUMMY);
D2 = D2 << 8;
inByte_low = SPI.transfer(DUMMY);
D2 = D2 | inByte_low;
Serial.print("Temperature raw =");
Serial.println(D2);
}
void getRealValues() {
//calculation of the real values by means of the calibration factors
UT1 = (Tref << 3) + 10000;
dT = D2 - UT1;
TEMP = 200 + ((dT * (TEMPSENS + 100)) >> 11);
OFF = OFFT + (((TCO - 250) * dT) >> 12) + 10000;
SENS = (SENST1/2) + (((TCS + 200) * dT) >> 13) + 3000;
PCOMP = (SENS * (D1 - OFF) >> 12) + 1000;
TEMPREAL = TEMP/10;
//2nd order compensation only for T > 0°C
dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
TEMPCOMP = (200 + (dT2*(TEMPSENS+100) >>11))/10;
Serial.print("Real Temperature in °C=");
Serial.println(TEMPREAL);
Serial.print("Compensated pressure in mbar =");
Serial.println(PCOMP);
Serial.print("2nd order compensated temperature in °C =");
Serial.println(TEMPCOMP);
Serial.println();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment