Click here to Skip to main content
15,891,652 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I am trying to read data from a Sensor using I2C communication. The output data is four of one byte, which is 0x43, 0xDB, 0x8C, 0X2E respectively.
So i successfully read those value separately. When i try to combine and convert it to real number. The output value is not what i expected:

The value read from the sensor is: 0x43DB8C2E
According to the data sheet, it is Big Endian and corresponding to 439.09.
But what i got for output is 29650.

What I have tried:

I have tried the example code from the data sheet of how to read that value. But the output is still not what i want.

C++
// CO2 concentration
float co2Concentration;
unsigned int tempU32;
// read data is in a buffer. In case of I2C CRCs have been removed // beforehand. Content of the buffer is the following
unsigned char buffer[4];
buffer[0] = 0x43; //  MMSB CO2
buffer[1] = 0xDB; //  MLSB CO2
buffer[2] = 0x8C; //  LMSB CO2
buffer[3] = 0x2E; //  LLSB CO2

// cast 4 bytes to one unsigned 32 bit integer
tempU32 = (unsigned int)((((unsigned int)buffer[0]) << 24) | (((unsigned int)buffer[1]) << 16) | (((unsigned int)buffer[2]) << 8) |
                          ((unsigned int)buffer[3]));

// cast unsigned 32 bit integer to 32 bit float
co2Concentration = *(float*)&tempU32; // co2Concentration = 439.09f


i print the value of co2Concentration and it is 29650
Posted
Updated 1-Nov-18 11:26am
v4

The solution is much simpler:
C++
float co2Concentration = 0;
char *buffer = (char*) &co2Concentration;
buffer[0] = 0x43; //  MMSB CO2
buffer[1] = 0xDB; //  MLSB CO2
buffer[2] = 0x8C; //  LMSB CO2
buffer[3] = 0x2E; //  LLSB CO2
 
Share this answer
 
Try using a union. Here's something you can get started from:
C++
union U {
   int i;
   float f;
   };
U temp;
temp.f = 439.09;
int i = temp.i;

Step through that and see what i equals. Then play with your values and see if things come together for you. If the sensor is not supplying the float value per standards, you will have to come up with a custom method.

Hope this helps!
 
Share this answer
 
Why are you messing with pointers?
Just cast it:
double co2Concentration;
unsigned int tempU32;
// read data is in a buffer. In case of I2C CRCs have been removed // beforehand. Content of the buffer is the following
unsigned char buffer[4];
buffer[0] = 0x43; //  MMSB CO2
buffer[1] = 0xDB; //  MLSB CO2
buffer[2] = 0x8C; //  LMSB CO2
buffer[3] = 0x2E; //  LLSB CO2

// cast 4 bytes to one unsigned 32 bit integer
tempU32 = (unsigned int)((((unsigned int)buffer[0]) << 24) | (((unsigned int)buffer[1]) << 16) | (((unsigned int)buffer[2]) << 8) |
                          ((unsigned int)buffer[3]));

// cast unsigned 32 bit integer to 32 bit float
co2Concentration = (double)tempU32; // co2Concentration = 439.09f
	printf("%d\n", tempU32);	
	printf("%f\n", co2Concentration);	
And the output is:
1138461742
1138461742


(I switched to doubles because the value wasn't accurate in a float on my compiler for obvious reasons).
 
Share this answer
 
Comments
Member 14040031 1-Nov-18 9:04am    
Thank you for your solution. But the output that i need is 439.09 and i have no ideal how can i get that.
OriginalGriff 1-Nov-18 9:31am    
Do you mean 439.095154?
Because that's easy! - you have the byte order wrong, is all!
unsigned char buffer[4];
buffer[3] = 0x43; // MMSB CO2
buffer[2] = 0xDB; // MLSB CO2
buffer[1] = 0x8C; // LMSB CO2
buffer[0] = 0x2E; // LLSB CO2
float f = (float)(*buffer);
printf("%f\n", f);
PC numbers are little endian, not big endian!
On a little endian machine you have to first rearrange the byte order and the cast the pointer:
C
#include <stdio.h>

int main()
{
  unsigned char buffer[4];

  buffer[0] = 0x43; //  MMSB CO2
  buffer[1] = 0xDB; //  MLSB CO2
  buffer[2] = 0x8C; //  LMSB CO2
  buffer[3] = 0x2E; //  LLSB CO2

  unsigned char le [] = {buffer[3], buffer[2], buffer[1], buffer[0]};
  float f = *(float *)(le);
  printf("%f\n", f);
  return 0;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900