ESP8266 & Pressure sensor MC5540 over SPI

Hello,

I'm trying to adapt the following code to my WeMos D1 R1 board, based on esp8266, to get a proper temperature & pressure from a MS5540 sensor : water-depth-using-ms5540c.

As of now, code seems to work, but it's probably only luck ... !

  • i'm geeting values for word1 to word4
word1 : 47942 - 1011101101000110
word2 : 63066 - 1111011001011010
word3 : 41184 - 1010000011100000
word4 : 48901 - 1011111100000101
  • the calibration coefficients are properly calculated, I checked versus the MS5540 datasheet.
c1 : 23971 - 101110110100011
c2 : 2053 - 100000000101
c3 : 764 - 1011111100
c4 : 643 - 1010000011
c5 : 985 - 1111011001
c6 : 26 - 11010
  • but the values D1 & D2 are wrong, always same value 65535, thus at the end the pressure and temperature displayed are incorrect.
D1 : 65535 - 1111111111111111
D2 : 65535 - 1111111111111111
Temp °C : 297 - 100101001
Pressure mBar : 2775 - 101011010111

My questions are the following:

  • ESP8266 is running at 80Mhz versus 16Mhz for the Arduino. In the original code there is a
    SPI.setClockDivider(SPI_CLOCK_DIV32) that I tryed to adapt with /128 to be as close as possible to the 500Khz from the MS5540. Does it mean the controller and the sensor are not compatible on this point?

  • Orignal code have the instruction at the beginning of the loop TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal. Or course it doesn't work on esp8266 as registry TCCR1B doesn't exist for my µC, but as I don't really understand the purpose of it I'm in trouble to find a workaround for esp8266... But i assume this is driving the timing of the reading of the SPI? Thus probably the root cause of my issue.

  • finally, in the Reset Sequence figure (bottom, page 13) in the datasheet I understand the reset should be done with 3 bytes like this 10101010 1010101000 00000000 and not with 0x15 0x55 0x40 (00010101 01010101 01000000) as it's done in the code. What do I miss?

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

My current code is below:

#include <SPI.h>

int pin_clock = 3;

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

void setup(void) {
  Serial.begin(9600);
  
  SPI.begin(); //see SPI library details on arduino.cc for details
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV128); 
  
  pinMode(pin_clock, OUTPUT);
  delay(100);
}

void printValue(unsigned int wordX, const char* wordName){
  Serial.print(wordName);
  Serial.print(" : ");
  Serial.print(wordX);
  Serial.print(" - ");
  Serial.println(wordX,BIN);  
}

void loop(void) {
  
  //TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (pin_clock, 128) ;
  resetsensor();//resets the sensor - caution: afterwards mode = SPI_MODE0!

  
  //Calibration word 1
  unsigned int word1 = 0;
  unsigned int word11 = 0;
  SPI.transfer(0x1D); //29 send first byte of command to get calibration word 1
  SPI.transfer(0x50); //80 send second byte of command to get calibration word 1
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  word1 = SPI.transfer(0x00); //send dummy byte to read first byte of word
  word1 = word1 << 8; //shift returned byte
  word11 = SPI.transfer(0x00); //send dummy byte to read second byte of word
  word1 = word1 | word11; //combine first and second byte of word
  printValue(word1, "word1");
  resetsensor();//resets the sensor

  //Calibration word 2; see comments on calibration word 1
  unsigned int word2 = 0;
  byte word22 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x60); //96
  SPI.setDataMode(SPI_MODE1);
  word2 = SPI.transfer(0x00);
  word2 = word2 << 8;
  word22 = SPI.transfer(0x00);
  word2 = word2 | word22;
  printValue(word2, "word2");
  resetsensor();//resets the sensor

  //Calibration word 3; see comments on calibration word 1
  unsigned int word3 = 0;
  byte word33 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x90); //144
  SPI.setDataMode(SPI_MODE1);
  word3 = SPI.transfer(0x00);
  word3 = word3 << 8;
  word33 = SPI.transfer(0x00);
  word3 = word3 | word33;
  printValue(word3, "word3");
  resetsensor();//resets the sensor

  //Calibration word 4; see comments on calibration word 1
  unsigned int word4 = 0;
  byte word44 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0xA0); //160
  SPI.setDataMode(SPI_MODE1);
  word4 = SPI.transfer(0x00);
  word4 = word4 << 8;
  word44 = SPI.transfer(0x00);
  word4 = word4 | word44;
  printValue(word4, "word4");

  long c1 = (word1 >> 1) & 0x7FFF;
  long c2 = ((word3 & 0x003F) << 6) | (word4 & 0x003F);
  long c3 = (word4 >> 6) & 0x03FF;
  long c4 = (word3 >> 6) & 0x03FF;
  long c5 = ((word1 & 0x0001) << 10) | ((word2 >> 6) & 0x03FF);
  long c6 = word2 & 0x003F;

  printValue(c1, "c1");
  printValue(c2, "c2");
  printValue(c3, "c3");
  printValue(c4, "c4");
  printValue(c5, "c5");
  printValue(c6, "c6");    
  
  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;
  printValue(D1,"D1");
  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
  printValue(D2,"D2");
  resetsensor();//resets the sensor




  //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 * 8) + 20224;
  const long dT = D2 - UT1;
  const long TEMP = 200 + ((dT * (c6 + 50)) >> 10);
  const long OFF  = (c2 * 4) + (((c4 - 512) * dT) >> 12);
  const long SENS = c1 + ((c3 * dT) >> 10) + 24576;
  const long X = (SENS * (D1 - 7168) >> 14) - OFF;
  long PCOMP = ((X * 10) >> 5) + 2500;
  float TEMPREAL = TEMP/10;
  float PCOMPHG = PCOMP * 750.06 / 10000; // mbar*10 -> mmHg === ((mbar/10)/1000)*750/06
  
  printValue(UT1,"UT1");
  printValue(dT,"dT");
  printValue(TEMP,"TEMP");
  printValue(OFF,"OFF");
  printValue(SENS,"SENS");
  printValue(X,"X");

  printValue(TEMPREAL,"Temp °C");
  printValue(PCOMP,"Pressure mBar");
  printValue(PCOMPHG,"Pressure mmHg");
  
  Serial.println("************************************");

  delay(1000);
}

Any hint are welcome, many thanks for the time you took for reading this post already.

Thanks,
V

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.