I am a beginner at using I2C communication to read data from sensors. I highly appreciate it if you could help me with this question.
I have to get and display the Temperature and Pressure values from the following 4-Byte data package. Only the lower 14 bits of the Higher two bytes are used for the value of the pressure; whereas only the higher11 bits of the lower two bytes are for the temperature.
And this is my code (it is mostly a copy paste of several other posts, I did not create it myself)
// Wire Master Reader
// by Nicholas Zambetti <http://www.zambetti.com>
// Demonstrates use of the Wire library
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
#define SENSOR_ADDRESS 0x30
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop() {
Wire.requestFrom(SENSOR_ADDRESS, 4); // request x bytes from sensor
delay(5);
uint32_t buf;
while (Wire.available()) { // slave may send less than requested
size_t actually_read = Wire.readBytes((uint8_t*)&buf, 4);
Serial.println(buf, BIN); // print the character
}
delay(500);
}
The only thing is that for Pressure values, I am getting numbers very small, and the opposite for temperature. They should be numbers of 14 bits for the Pressure and 11 bits for the temperature.
Could it have something to do with the order of bits coming from the serial transmission (MSB or LSB)?
for the pressure: I was using a sensor with a nominal pressure of 7 Bar, which made any small difference in pressure that I could do almost negligent. I exchange the sensor for one of 100 mBar and now any small pressure change actually modifies the value up to 16,384 (max pressure).
for the temperature: I believe that the Bit shift operation needed a "<<3" instead of "<<8". Doing that gave me a smaller number after I perform the OR operation. The value at room temperature is more appropriate and closer to what I would expect.
If I understand correctly, by using an unsigned int I am only storing the bits in the order that is sent from the sensor.
What do I have to consider if I want to actually condition the value so I get the real mBars?
if I add the conversion equation considering my sensor´s parameters, and save the result to a new double variable, it always shows "0.00" when I print the result (it does not matter than the "raw" bits are actually changing.
I am guessing that the type of variable is not the correct one, or that I am skipping a step to convert the unsigned int to a type that I can actually work with.
wow, thank you! I am impressed on how quick the solution is to someone with experience.
Do you mind explaining what kind of logic is that? (why float type instead of double?; what does the "(float)" do?; and why the decimal point with the extra zero?)
1. For UNO, there is no difference between double and float data types -- they both refer to 32-bit bunray32 format (IEEE-754) standard for a floating point number (having integer part and fractional part).
(1) Using paper and pencil, the RHS of the above equation becomes:
==> (16383 - 1560)*0.007
==> 103.761
or
==> ((16383 - 1560)*100)/13107
==> 113.09
Which one is correct - (1) or (2)?
3. You have declared the destination data type as float (double) which means that you want both integer part and fractional part of the output. Therefore, the data types of the operand of RHS must also be of float type which has been done by adding 0.0 with the numerical operands (data) and doing (float) cast on the variable. As a result, the Compiler will do the float math instead of integer math which takes only the integer part (0) from 0.007 and makes the output 0. Serial.print() shows 0.00; because, the data type id double/float.