0

I am trying to get output from a sensor (micro-structure 5852D), but I only get two outputs: 11 and 255 for even applying pressure.

The following is my code, please show me how to over come this problem.

#include "Wire.h"
#define addrs 0x5F // I2C bus address


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

void loop()
{

   byte lobyte;
   byte hibyte;
   int Press;

   Wire.beginTransmission(addrs);
   Wire.write(1);        
   int x = Wire.endTransmission(); 

   Serial.print("endTransmission: ");
   Serial.println(x, DEC);

   Wire.requestFrom(addrs, 2); // contents of your first two registers
   while(Wire.available() < 2 );          // Check for data from slave
   {   
      delay(1000);
      lobyte = Wire.read();       // Read press high byte
      Serial.println(lobyte, DEC);
      hibyte = Wire.read();      // Read press low byte
      Serial.println(hibyte, DEC);

      Press = toPressure(hibyte, lobyte);
      Serial.print("Pressure: ");
      Serial.println(Press);

      delay(1000);
   } 

}


float toPressure(byte hi, byte lo)
{
  int a = (hi * 256 + lo) & 0x3FFF;  // see pdf, mask 14 bit

  float rv = (a - 116)* 0.8606; // faster //(t - 1638.0) / 30.84 + 600.0
  return rv;

} 

migrated from electronics.stackexchange.com Feb 19 '16 at 17:26

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

  • It's Silicon Microstructures SM5852, not "micro-structure 5852D". – jms Feb 19 '16 at 11:45
  • You need to tell us more about the specific sensor you are using. There are currently 7 SM5852 variants for different measurements and pressure ranges being sold. Where did you find the I2C specifications? I have looked at all the datasheets I could find and there is no mention of the I2C addressing or of the internal registers and commands. – jms Feb 19 '16 at 12:00
  • Thanks James For your kind replay, here we are sending your link for your reference – Shripad Puntambekar Feb 19 '16 at 12:54
  • datasheetlib.com/datasheet/1139457/… – Shripad Puntambekar Feb 19 '16 at 12:54
  • Sensor gives 2 out put 1 Analog ( 2.5 to 4v for 1.5psi) and digital. ( which include SCL and SDA pins ) we tried hard but we dosent get proper variable signals proportional to pressure. At same time Analog signal shows variation in V. so its sign that sensor is in working condition. As per digram we used all R and Capacitors in VDD and SCL,SDA took out sensor addres at I2C we got it 0x5F . but dosent indestad that what is went wrong in whole system, and its not working as per expectation. please give us your support to overcome problem. – Shripad Puntambekar Feb 19 '16 at 12:59
1

The issues in your code:

  • When communicating with the sensor, the sensor expects a register address after the device address. Instead of providing it the register address, you sent the number of bytes you would like to receive. Good guess, but unfortunately the device was not designed that way.

  • You did not combine the least significant bits and most significant bits of the sensor output correctly. The LSB contains the 6 (not 8) least significant bits, while the MSB contains the 6 most significant bits. You first combined them like 00MMMMMM00LLLLLL (where bits marked L come from the LSB and bits marked M come from the MSB), and then masked off the upper two bits as in MMMMMM00LLLLLL. The proper way would have been to only left shift the MSB 6 bits, producing 0000MMMMMMLLLLLL, and then masking away the upper 4 bits leaving MMMMMMLLLLLL.

  • You should avoid 32 bit floating point math on 8-bit microcontrollers at all costs unless you have a huge amount of processor cycles to spare.

In order to read data from the sensor you must first select the register you want to read. To select a register you must first send the device address (95 in decimal, 5F in hexadecimal) with the write request bit set, and then the register address of the byte you want to read.
You can then read the contents of the selected register by first sending the device address, this time with the write request bit clear, and then receiving one byte of data immediately followed by a not acknowledge (NACK) to end the transmission.

The internal registers are organized as in the following table:

register table

Here is my take on the code. It compiles fine, but obviously I cannot test if it actually works as I don't have the sensor. I removed the scaling routine, as it would be wise to first get it working to some level before implementing less essential features.

#include "Wire.h"
#include <stdint.h>

#define SENSOR_I2C_ADDR 95   
#define SENSOR_REG_PRESSURE_LSB 128  
#define SENSOR_REG_PRESSURE_MSB 129  

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

void loop()
{
    Wire.beginTransmission(SENSOR_I2C_ADDR);        //Send the address of the register where the least
    Wire.write(SENSOR_REG_PRESSURE_LSB);            //..significant bits of the pressure measurement are found
    Wire.endTransmission(false);                    //Send a repeated start
    Wire.requestFrom(SENSOR_I2C_ADDR, 1, false);    //Request 1 byte of data, followed by a repeated start

    Wire.beginTransmission(SENSOR_I2C_ADDR);        //Send the address of the register where the most
    Wire.write(SENSOR_REG_PRESSURE_MSB);            //..significant bits of the pressure measurement are found     
    Wire.endTransmission(false);                    //Send a repeated start
    Wire.requestFrom(SENSOR_I2C_ADDR, 1, true);     //Request 1 byte of data, followed by a stop, ending the transaction.

    uint16_t pressureRaw;

    //There should now be two bytes of data in the receive buffer.
    if(Wire.available() == 2)
    {
        uint8_t lsb = Wire.read();                  //The first byte contains the 6 least significant bits
        uint16_t msb = Wire.read();                 //The second byte contains the 6 most significant bits
        pressureRaw = (msb << 6 | lsb) & 0x0FFF;    //The most significant bits are aligned and combined with the  
                                                    //..least significant bits. As the resulting value only has   
                                                    //..12 bits of precision the upper 4 bits are masked to zero.

        Serial.print("Raw pressure value: ");
        Serial.println(pressureRaw);
    }  
    else                                            //If more or less than 2 bytes have been received something isn't right.
    {
        while(Wire.available())                     //Clear the buffer
            Wire.read();
        Serial.println("I2C transaction error");
    }
    delay(1000);
}

For some unfathomable reason Silicon Microstructures decided to not include the I2C interface specification in the datasheet itself. The information is instead found in a separate application note.

EDIT:
Apparently Wire.flush() does absolutely nothing. Implementation from Wire.cpp:

void TwoWire::flush(void)
{
    // XXX: to be implemented.
}

And no, the implementation isn't in the base class either: virtual void flush() = 0;. To work around this, I replaced the flush call with a read() loop.

  • Thanks I do try this , and replay you what dose come it out!!!!! – Shripad Puntambekar Feb 20 '16 at 4:40
  • Hi james we were working as per your solution but got result as lsb going increasingly form 3 to 61 at 0 mbar pressure and msb remains constant 65535 cont.so got confused how to get exact output.Please help in another way. Thanx in advance. – Shripad Puntambekar Feb 20 '16 at 15:51
  • @ShripadPuntambekar I cannot help in any other way, as I don't have the sensor. My code only outputs the combined value, so you must have modified the code to get a separate byte with the high bits and another with the low bits. Could you please test if my code works, without modifying it? I found a possible source for bugs in the arduino Wire library which I worked around in the update of the above code, so please copy the above code again. – jms Feb 20 '16 at 18:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.