How to read i2c pressure sensor with arduino (ZSC31014)

Hello friends, greetings.

greetings to all . Friends I am trying to get data from the WNK81MA sensor that uses an i2c communication protocol, I have the built-in assumption that it is the ZSC31014 but when asking for the bytes with a code to read i2c slaves, the information it gives me is a bit strange. It should be noted that it is the first time that I try to use this protocol with this sensor since I have little ability to create code from scratch for this type of implementations. Please if anyone knows how to get information from this sensor or has any code
to read data via i2c to this slave I would greatly appreciate

this is the datasheet if someone can help me interpret it it would be excellent

ZSC31014 (3) (1).pdf (890.1 KB)

this is the code

 #include<Wire.h>
    const int MPU_addr = 0x17;  // I2C address 
    int16_t GCVal;
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU_addr);
      Serial.begin(115200);
    }
    void loop(){
      Wire.beginTransmission(MPU_addr);
      Wire.endTransmission();
      
      Wire.requestFrom(MPU_addr,4);
        while (Wire.available()) { // slave may send less than requested
    char GCVal = Wire.read(); // receive a byte as character
    Serial.println(GCVal, DEC);         // print the character
  }
Serial.println("===========FIN===========");
  delay(500);
}

this is serial port

file:///C:/Users/Eder%20Rojas/Desktop/7373baf9-e3cf-4013-8763-52360740bc1e.jfif

31 / 5000

Resultados de traducción

I am using a NODEMCU ESP8266

This sensor needs additional code to properly read the data. A quick look at the datasheet shows there are many operational modes and there are calibration coefficients for the digital. You will need to wait for someone with more coding capability than you or I to write a driver.

Hi John, how can I generate that code? I read the datasheet but I don't know how to do the code correctly, I'm beginner at this

what is the final purpose of this project?
what is the pressure- range that you want to measure?

if you are a real newcomer about programming it wil take you weeks until you have programmed the driver

It will be much easier to use a sensor with analog output and then use the adc input of the nodemcu

That's the problem no one can "tell" you how to write a driver. I can tell you the first step is to read and understand the datasheet and all the registers etc.

OR you can purchase a HX711 on ebay that performs the same function and there are drivers for it available. I can't say if one will outperform the other.

This datasheet for the chip is confusing. The chip seems to be used in other devices as well. However, I can not find a library (or "driver") for it.

I agree with @JohnRob, if you can use a HX711, then you better try that.

The writing without data bytes is possible.
That is the "Write_MR" of page 41

Wire.beginTransmission( i2c_address);
Wire.endTransmission();

I don't know if a read without data is possible. Do you have a logic analyzer ?
It is the "Read_MR" of page 38.

Wire.requestFrom( i2c_address, 0);     // request no data, will this work ?

Did you run a I2C Scanner sketch to confirm that 0x17 is the i2c address ?

Perhaps you should add a delay between starting a measurement and requesting the data.

I suggest to focus on the two last bytes for the temperature.

void loop()
{
  // Write_MR
  Wire.beginTransmission( MPU_addr);
  Wire.endTransmission();
  
  delay( 500);

  int n = Wire.requestFrom( MPU_addr, 4);
  if( n == 4)
  {
    byte data[4];
    Wire.readBytes( data, 4);

    uint16_t high = data[2];
    uint16_t low  = data[3];
    uint16_t t = (high << 3) | (low >> 5);
    Serial.println( t);
  }
  else
  {
    Serial.println( "Error while trying to communicate with the chip");
  }

  delay( 2000);
}

If the temperature changes when you warm up the sensor, then you still have a long way to go. The parameters for the calculation are stored in the chip.

That's not all, there is also a calibration procedure.

Hi Koepel, if I confirm the sensor direction with this sketch:

#include <Wire.h>              
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

the reason why I can't use an HX711 analog sensor is that it has already been implemented and we need to use this one which is cheaper hence the need to use the i2c sensor.

your sketch gave me this result:

image

friend so you know the scale of the sensor is 0-10 bar

The manufacturer.website says
image

So I would ask the manufacturer if he has a Arduino-C++driver for his sensors.
At least a C-library-driver for I2C.
lilyh@wnksensor.com

Even if the manufacturer has a C-driver you still will have a hard time to learn enough C-programming to get it adapted to work with arduino C++.

So $12 for a sensor like this is too much?

or something like that?

You asked "How can I "generate" the code?
Well "generating" the code in this case means

"generate" expertise-knowledge about I2C-Bus on the level of Clock and Data-signals
this will take 4 to 8 weeks as a fulltime job

"generate" expertise-knowledge about programming in general
this will take 4 to 8 weeks as a fulltime job

and then the program gets "generated" by typing 100 to 300 lines of code into an texteditor.
with a lot of testing if you send the right data to make the chip answer in the right way
this will take 4 to 8 weeks as a fulltime job

That is the reason why I say you will be way better if you go working for 4 weeks in any kind of job to earn the money to buy another much easier to use pressure-sensor.

You haven't told what the final purpose of the pressure-sensor is.
There might be completely different solutions für what you want to do

in the end

best regards Stefan

@StefanL38 Tip: You can delete everything behind the first ? and I think that the .,- in the URL is a site design mistake.
So this is the URL to the same page: https://www.digikey.de/product-detail/de/seeed-technology-co-ltd/114991178/1597-1515-ND/7387419

the purpose of the sensor to measure pressure in refrigeration equipment. They asked me to get the data from this sensor. apparently it is customer's request

Given those two statements, I'm not optimistic about your chance of success. Perhaps it's time to consider paying someone to do it for you.

This (the ZSC31014) is the same core used in TE Connectivity FX290 I2C load cells, which I'm using in a project.

I tried a couple of different libraries I found online, but settled on the old Wire.h library to communicate with it. I'm somewhat a newb, and found parts of this code elsewhere, but here's a copy of what I have to-date... and yes, feel free to (gently) let me know if I've coded poorly.

Some of the nonsense is trying to resolve the Sleep Mode... I hear the chip is still programmable (not Locked), and I am currently trying to piece together some code to disable Sleep Mode, as well as possibly change the default I2C address.

It should work with your sensor (OP) , but the scale and units will obviously need to change.... but it is working code.

#include <Wire.h>

#define UseDebug 1

#define clockFrequency 100000
#define zeroOffset 1234               // fine-tuned for a specific load cell, should stay at 1000 normally
const byte fx29Pwr = 3;               // using Digital IO pin 3 to power the load cell

float scaleFactor = 1400;             // maximum 14000 counts for 10 pounds
int curAddress = 0x28;                // I2C address for load cell

void setup() {
  pinMode(fx29Pwr, OUTPUT);
  
  Wire.begin();                       //Starts I2C, will need to change these two values (or delete them)
  Wire.setClock(clockFrequency);      //Sets I2C frequency to declared constant

  digitalWrite(fx29Pwr, LOW);         // make sure it's OFF for a while, before...
  delay(10);
  
  Serial.begin(9600);
  digitalWrite(fx29Pwr, HIGH);        // ... we turn it back ON
}

void loop() {
  Wire.beginTransmission(curAddress); //Request Measurement
  Wire.endTransmission();
  
  delay(100); //Delay for measurement to be taken (could be done in IRQ)
  
  Wire.requestFrom(curAddress, 2);  //Requests n bytes of data 
  byte msb = Wire.read();
  byte lsb = Wire.read();

  #if (UseDebug)
  byte statusVals = msb/64;     //Determines the status values from the measurement to ensure a new measurement was taken
  Serial.print("status:");
  Serial.print(statusVals, BIN);
  Serial.print("  //  ");
  Serial.print("msb:");
  Serial.print(msb, BIN);
  Serial.print("  //  ");
  Serial.print("lsb:");
  Serial.print(lsb, BIN);
  #endif
  
  int dataVal = (msb%64)*256 + lsb; //Throws out the status bits and converts the measurement data into a single int
                                    // "%" is division-Remainder", ex: Remainder from msb of 111011 (59d) / 64 = 0 with remainder 59 - 
                                    //  it throws away any significant bits above 63d xx11 1111
  Serial.println();                                  
  Serial.print("raw Wt DataValue: ");
  Serial.print(dataVal);  
  Serial.print("  //  ");
  
  float weightVal = ((dataVal - zeroOffset) / scaleFactor) * 100; // convert to Grams since rotary encoders are specified as such
  float rawVal =  (dataVal/scaleFactor) * 100;
  Serial.print("Gross weight: " + String(rawVal) + " grams");  
  Serial.print("  //  ");
  Serial.print("Net weight: " + String(weightVal) + " grams"); 
  
  Serial.println();
  Serial.println();
  delay(1000);
}

(edit - clarification for those that didn't understand the purpose of my first post)

I do not understand a single word what you want to try to say. AYJT?

If it is still actual. First two bytes is for the pressure, other two i s for the temperature. I've lost the formula, so I don't know how to calculate the temperature. For the pressure, first byte is the upper one in the 16 byte value. If the first bit of the first byte is 1, there is an error in readings. So every value bigger then 128 is an error. My formula is: (((100*($FB*256+$SB)-81915)*200)/16383)/9. $FB is First Byte, $SB is Second Byte. That gives me values scaled to 10 mBar. You should adopt it to your range, my is 0-20 Bar.

Hello dm999 I tried with this code but the values it gives me are wrong considering that I have a sensor of 0 - 10 bar, then I am attaching my code and the screenshot of the terminal with the result

#include<Wire.h>



 
    const int MPU_addr = 0x16;  // I2C address 
    int16_t GCVal;
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU_addr);
      Serial.begin(115200);
    }

void loop()
{
  // Write_MR
  Wire.beginTransmission( MPU_addr);
  Wire.endTransmission();
  
  delay( 500);

  int n = Wire.requestFrom(MPU_addr, 16);
  if( n == 16)
  {
    byte data[16];
    Wire.readBytes( data, 16);

    uint16_t high = data[1];
    uint16_t low  = data[2];
    uint16_t t = (high << 1) | (low >> 16);
 //   Serial.print( high);
   // Serial.print( ",");
    //Serial.println( low);
    float b1 = high;
    float b2 = low;
    delay(2000); 
    Serial.println("==========PRESION CALCULADA==========");
    
    float presionFinal = calPresion(b1,b2);
    Serial.println(presionFinal);
  }
  else
  {
    Serial.println( "Error while trying to communicate with the chip");
  }

  

  delay( 500);
}

float calPresion(float Fbyte, float Sbyte) {
    return (((100*(Fbyte*256*Sbyte)-81915)*200)/163838)/9;
}

image

This is not the output I have received from the I2C scanning program. You might want to reload and retest.

JHON already reloaded the code but AS I PRESS THE SENSOR THE PRESSURE TENDS TO INCREASE BUT AS THE PRESSURE INCREASES EVEN MORE THEN THE VALUE FALLS

I was referring to post #7. However if you are already reading data from your transducer I suggest you print out the raw data from the sensor before doing any calculations. This will allow you to see what is going on.

I am not using any formula I get this

So this still actual. In the mean time, I've managed to find the manual in some old mails. The formula for the sensor output is:
((90% * 16383)/(Pmax-Pmin))*(Pcurrent-Pmin)+(5% * 16383)