Selecting the 4th and 5th bit of an i2c data

Hello, I have a SDP810 differential pressure sensor that works with i2c. It’s pressure data is stored in the first two bits of SDA, where the temperature data is stored in the 4th and the 5th. I can obtain the first two bits simply by the following code snippet

//Read pressure from SDP810
int16_t Pres_Raw; //16 bit intiger to store the msb and lsb
double Pres; //Double precision float to store actual pressure reading
byte msb; 
byte lsb;
Wire.requestFrom(0x25, 2); //Contents of first two bytes
msb = Wire.read(); //Byte1 is msb
lsb = Wire.read(); //Byte2 is lsb
Pres_Raw = msb<<8; //Assign msb to combined variable
Pres_Raw |= lsb; //Add the lsb to the combined variable
Pres = Pres_Raw/float(240); //Divide the raw reading by the scaling factor (page 10 in cut sheet)

However, I am really struggling to read the temperature data. I am trying to obtain it by first getting the first getting the first 5 bits, discarding the first 3 and using the remaining ones with this code.

//byte gen = Wire.requestFrom(0x25,5);
//byte a = Wire.read();
//byte b = Wire.read();
//byte c = Wire.read();
//byte d = Wire.read();
//byte e = Wire.read();

//int16_t temp_raw = d << 8 | e;
//temp = temp_raw/float(60);

In conclusion, I want to obtain both of these datas simultaneously and print them. Any help would be much appreciated.

It’s pressure data is stored in the first two bits of SDA

The first thing to clarify is whether you mean bits or bytes

Bytes, my bad.

the example in this library seems to do what you're looking for...

https://github.com/rac2030/Arduino-Sensirion-SDP3x-driver

Yes it does. But I only want to use the Wire.h library. Other premade libraries can do just fine. But they do not allow the user to change the operating modes of the sensor. This is why I specifically want to learn how can I obtain the temperature value solely by shifting the bytes left or right without messing up the pressure readings. And of course, to learn more about how all this stuff works.

ege621: Yes it does. But I only want to use the Wire.h library. Other premade libraries can do just fine. But they do not allow the user to change the operating modes of the sensor. This is why I specifically want to learn how can I obtain the temperature value solely by shifting the bytes left or right without messing up the pressure readings. And of course, to learn more about how all this stuff works.

well then, all you need to do is to look into the libs to see how they do it and implement/mod the codes in there into your main code thereby eliminating the libs! :)

In the libraries, they are using a lot of other notepad files within those library files. They are storing the bytes in an array and just calling them as they like. But as I said, they are just not doing it by equating the bytes to an array. There should be another simpler way.

Read and store each bytes in an array then read from the array using the index of the byte you want.

@OP

Try to complete the following sketch and upload it. Extract pressure and temperature from the raw data using the formulate of data sheets. If possible, try to utilize the received CRC to check the validity of the received data. (I have no sensor to test the sketch.)

#include<Wire.h> 
byte myData[15];  //array to hold data coming from sensor

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  //----continuous measurement command----------
  Wire.beginTransmission(0x25);
  Wire.write(0x36);
  Wire.write(0x15);   //see data sheets
  Wire.endTransmission();
  //-------------------------------
  delay(10);
  //-------------------------------
  Wire.requestFrom(0x25, 9);
  for(int i=0; i<9; i++)
  {
    myData[i] = Wire.read();
  }
  //----process data by taking them from Array and display on Serial Monitor----
  //myData[0]-myData[1] = Raw Pressure Data as signed integer
  //myData[2] = CRC of Pressure data
  
  //myData[3]-myData[4] = Raw Temperature data as signed integer
  //myData[5]= CRC of Temperature data
  
  //myData[6]-myData[7] = Scale factor for differential pressure
  //myData[8] = CRC of scale factor data
   
  //----measurement stop command--
  Wire.beginTransmission(0x25);
  Wire.write(0x3F);
  Wire.write(0xF9);   //see data sheets
  Wire.endTransmission();
  //----------------------
  delay(1000);   //test interval
}

GolamMostafa:
@OP

Try to complete the following sketch and upload it. Extract pressure and temperature from the raw data using the formulate of data sheets. If possible, try to utilize the received CRC to check the validity of the received data. (I have no sensor to test the sketch.)

#include<Wire.h> 

byte myData[15];  //array to hold data coming from sensor

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  //----continuous measurement command----------
  Wire.beginTransmission(0x25);
  Wire.write(0x36);
  Wire.write(0x15);  //see data sheets
  Wire.endTransmission();
  //-------------------------------
  delay(10);
  //-------------------------------
  Wire.requestFrom(0x25, 9);
  for(int i=0; i<9; i++)
  {
    myData[i] = Wire.read();
  }
  //----process data by taking them from Array and display on Serial Monitor----
  //myData[0]-myData[1] = Raw Pressure Data as signed integer
  //myData[2] = CRC of Pressure data
 
  //myData[3]-myData[4] = Raw Temperature data as signed integer
  //myData[5]= CRC of Temperature data
 
  //myData[6]-myData[7] = Scale factor for differential pressure
  //myData[8] = CRC of scale factor data
 
  //----measurement stop command–
  Wire.beginTransmission(0x25);
  Wire.write(0x3F);
  Wire.write(0xF9);  //see data sheets
  Wire.endTransmission();
  //----------------------
  delay(1000);  //test interval
}

wow thank you very much. Will definetely try it right now. I have also realized that I was trashing the CRC bytes. oh god.

Apart from the missing Wire.begin() function and the sensor configuration lines being in the void loop, this worked fine for me. Great effort. Thanks! Still trying to figure out how can I use the CRC bytes because in the datasheet it is stated that they are not needed to be read continuously.

To utilize CRC information, you need to compute CRC from the received data (for example: pressure data) and then compare it with the received CRC byte (myData[2]). If they appear to be equal, the received pressure signal is (very much) good for use. This CRC check is usually implemented in the 'critically important' works.

Can you post the screenshot showing the readings of your sensor to see how good it is working?

Here you go; The data seems pretty stable. When you blow on the sensor it changes accordingly.

Would be glad to see your full codes posted.

GolamMostafa:
Would be glad to see your full codes posted.

#include <Wire.h> 
byte myData[15];  //array to hold data coming from sensor

void setup() 
{
  Wire.begin();
  Serial.begin(9600);

// ---------CONTINOUS READING COMMANDS----------//

//Mass Flow, Average till read
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x03);   
//  Wire.endTransmission();

   //Mass Flow, None, update rate 0.5ms
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x08);   
//  Wire.endTransmission();
//
// //Differential Pressure, Average till read
  Wire.beginTransmission(0x25);
  Wire.write(0x36);
  Wire.write(0x15);   
  Wire.endTransmission();

// //Differential Pressure, None, Update rate 0.5ms
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x1E);   
//  Wire.endTransmission();

//-----------------------------------------------//

//------TRIGGERED READING COMMANDS---------//

 //Mass Flow, w/o clock stretching
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x24);   
//  Wire.endTransmission();

 //Mass flow, w/ clock stretching
//  Wire.beginTransmission(0x25);
//  Wire.write(0x37);
//  Wire.write(0x26);   
//  Wire.endTransmission();

//Differential pressure w/o clock stretching
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x2F);   
//  Wire.endTransmission();

 //Differential pressure w/ clock stretching
//  Wire.beginTransmission(0x25);
//  Wire.write(0x37);
//  Wire.write(0x2D);   
//  Wire.endTransmission();


  //------RESET COMMAND----//
//  Wire.beginTransmission(0x25);
//  Wire.write(0x00);
//  Wire.write(0x06);  
//  Wire.endTransmission();

   //Enter sleep mode
//  Wire.beginTransmission(0x25);
//  Wire.write(0x36);
//  Wire.write(0x77);   //see data sheets
//  Wire.endTransmission();
  //Any command other than go to sleep will wake the sensor up. 

delay(8);
}

void loop() 
{
  
  Wire.requestFrom(0x25, 9);
  for(int i=0; i<9; i++)
  {
    myData[i] = Wire.read();
  }
  delay(1);
  
  int16_t Pressure_raw = myData[0]<<8|myData[1]; // Raw Pressure Data 
  //myData[2] = CRC of Pressure data
 
  int16_t Temperature_raw = myData[3]<<8|myData[4];// Raw Temperature data 
  //myData[5]= CRC of Temperature data
  double Temperature = Temperature_raw/float(200);
  
  float SF_pressure = myData[6]<<8|myData[7];  //Scale factor for differential pressure
  //myData[8] = CRC of scale factor data
  double Pressure = Pressure_raw/SF_pressure; 
   
  //----measurement stop command--
//  Wire.beginTransmission(0x25);
//  Wire.write(0x3F);
//  Wire.write(0xF9);   //see data sheets
//  Wire.endTransmission();

Serial.print("Differential Pressure= ");
Serial.print(Pressure,5); //Print pressure reading in terminal (Pa)
Serial.print(" Pa\n");

Serial.print("Temperature= ");
Serial.print(Temperature);
Serial.print("C\n");
Serial.print("\n");
  
  //----------------------
  delay(500);   //test interval
}

here you go.