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
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.
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.
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:
friend so you know the scale of the sensor is 0-10 bar
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
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
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)
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
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.
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)