-->
Page 1 of 1

SPI reading data from sensor problem

PostPosted: Wed Jul 13, 2016 4:28 am
by MostafaKhattab
Basic Infos

Hardware:
Hardware: ESP-12E
Core Version: 2.1.0-rc2

Description

I am working with MS5540Chttp://www.fut-electronics.com/wp-content/uploads/2015/08/MS5540C_waterproof_pressure_sensor_datasheet.pdf sensor, trying to communicate with it using SPI, but getting wrong data and the same result regardless the environment changes.

I set the SPI Frequency to 500khz
Code: Select allSPI.setFrequency(500000);

I used to make this in arduino using this line of code
Code: Select allSPI.setClockDivider(SPI_CLOCK_DIV32);


I also uses a pwm frequency (mclk) using:
Code: Select allanalogWriteFreq(10);
analogWriteRange(256);
analogWrite(D8, 128);

I used to write that arduino uno using:
Code: Select allTCCR1B = (TCCR1B & 0xF8) | 1 ;
analogWrite(9, 128);

Why am I getting wrong reads ??
What Should I have to change to get write reads from the sensor.

Settings in IDE

Module: NodeMCU 1.0 (ESP-12E Module)
Flash Size: 4MB
CPU Frequency: 80Mhz
Upload Using: SERIAL

Sketch:

Code: Select all#include <SPI.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include "FS.h"

void setup() {
  Serial.begin(115200);
  Serial.println("");
  delay(2000);
  setupSensor();
  delay(500);

}

void loop() {
  readSensorData();
  delay(1000);
}

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

void setupSensor() {
  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 (16000000/32)
  // 80,000,000 /
  SPI.setFrequency(500000);
//  SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
//  SPI.setHwCs(false);
  pinMode(clock, OUTPUT);
  delay(100);
}

int readSensorData() {
  #ifdef __AVR__
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  Serial.println("HAHAHA d7kt 3leek");
  #else
  analogWriteFreq(10);
  analogWriteRange(256);
  #endif
  analogWrite(D8, 128);

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

  //Calibration word 1
  unsigned int word1 = 0;
  unsigned int word11 = 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
  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

  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);
  SPI.setDataMode(SPI_MODE1);
  word2 = SPI.transfer(0x00);
  word2 = word2 <<8;
  word22 = SPI.transfer(0x00);
  word2 = word2 | word22;

  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);
  SPI.setDataMode(SPI_MODE1);
  word3 = SPI.transfer(0x00);
  word3 = word3 <<8;
  word33 = SPI.transfer(0x00);
  word3 = word3 | word33;

  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);
  SPI.setDataMode(SPI_MODE1);
  word4 = SPI.transfer(0x00);
  word4 = word4 <<8;
  word44 = SPI.transfer(0x00);
  word4 = word4 | word44;

  long c1 = word1 >> 1;
  long c2 = ((word3 & 0x3F) << 6) | ((word4 & 0x3F));
  long c3 = (word4 >> 6) ;
  long c4 = (word3 >> 6);
  long c5 = (word2 >> 6) | ((word1 & 0x1) << 10);
  long c6 = word2 & 0x3F;

  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

  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;

  const long UT1 = (c5 * 8) + 20224;
  const long dT =(D2 - UT1);
  const long TEMP = 200 + ((dT * (c6 + 50))/1024);
  const long OFF  = (c2*4) + (((c4 - 512) * dT)/4096);
  const long SENS = c1 + ((c3 * dT)/1024) + 24576;

  long PCOMP = ((((SENS * (D1 - 7168))/16384)- OFF)/32)+250;
//  float TEMPREAL = TEMP/10;
  Serial.print("pressure =    ");
  Serial.print(PCOMP);
  Serial.println(" mbar");

  const long dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
  const float TEMPCOMP = (200 + (dT2*(c6+100) >>11))/10;
  Serial.print("temperature = ");
  Serial.print(TEMPCOMP); 
  Serial.println(" °C");
  Serial.println("************************************");
  analogWriteFreq(1000);
  analogWriteRange(PWMRANGE);
  return PCOMP; // in mbar
}

Re: SPI reading data from sensor problem

PostPosted: Wed Jul 13, 2016 3:34 pm
by MostafaKhattab
I think the problem is because the ESP8266 PWM MCLK pin frequency, which may not work with 32khz frequency.

Any solution / workaround to this problem ??

here's an updated code

Code: Select all#include <SPI.h>
#include <dummy.h>
#include <Esp.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include "FS.h"

void setupSensor();
int readSensorData();

void setup() {
  Serial.begin(9600);
  Serial.println("");
//  Serial.setDebugOutput(true);
  delay(2000);
  setupSensor();
//  Serial.print("Debug: ");
//  Serial.println(ESP8266_CLOCK/(2441 * 1));
  delay(500);
}

void loop() {
  readSensorData();
  delay(2000);
}

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

void setupSensor() {
  SPI.begin(); //see SPI library details on arduino.cc for details
//  analogWriteRange(2441);
//  analogWriteFreq(1000);
  SPI.setBitOrder(MSBFIRST);
//  SPI.setClockDivider(SPI_CLOCK_DIV64); //divide 16 MHz to communicate on 500 kHz (16000000/32)
  // 80,000,000 /
  SPI.setFrequency(500000);
//  SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
//  SPI.setHwCs(false);
  pinMode(clock, OUTPUT);
  delay(100);
}

int readSensorData() {
  #ifdef __AVR__
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  Serial.println("HAHAHA d7kt 3leek");
  #else
//  analogWriteRange(2441);
  analogWriteFreq(4000);
  delay(100);
  #endif
  analogWrite(D5, 128);

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

  //Calibration word 1
  unsigned int word1 = 0;
  unsigned int word11 = 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
  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

  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);
  SPI.setDataMode(SPI_MODE1);
  word2 = SPI.transfer(0x00);
  word2 = word2 <<8;
  word22 = SPI.transfer(0x00);
  word2 = word2 | word22;

  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);
  SPI.setDataMode(SPI_MODE1);
  word3 = SPI.transfer(0x00);
  word3 = word3 <<8;
  word33 = SPI.transfer(0x00);
  word3 = word3 | word33;

  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);
  SPI.setDataMode(SPI_MODE1);
  word4 = SPI.transfer(0x00);
  word4 = word4 <<8;
  word44 = SPI.transfer(0x00);
  word4 = word4 | word44;
 
  long c1 = word1 >> 1;
  long c2 = ((word3 & 0x3F) << 6) | ((word4 & 0x3F));
  long c3 = (word4 >> 6) ;
  long c4 = (word3 >> 6);
  long c5 = (word2 >> 6) | ((word1 & 0x1) << 10);
  long c6 = word2 & 0x3F;
//
//  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

  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;
 
  const long UT1 = (c5 * 8) + 20224;
  const long dT =(D2 - UT1);
  const long TEMP = 200 + ((dT * (c6 + 50))/1024);
  const long OFF  = (c2*4) + (((c4 - 512) * dT)/4096);
  const long SENS = c1 + ((c3 * dT)/1024) + 24576;
 
  long PCOMP = ((((SENS * (D1 - 7168))/16384)- OFF)/32)+250;
  float TEMPREAL = TEMP/10;
  Serial.print("pressure =    ");
  Serial.print(PCOMP);
  Serial.println(" mbar");

  const long dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
  const float TEMPCOMP = (200 + (dT2*(c6+100) >>11))/10;
  Serial.print("temperature = ");
  Serial.print(TEMPCOMP); 
  Serial.println(" °C");
  Serial.println("************************************");

  analogWriteFreq(1000);
  delay(300);
  return PCOMP; // in mbar
}