Home > Back-end >  Converting sensor data (two's complement) to signed integer
Converting sensor data (two's complement) to signed integer

Time:05-15

I've seen a couple old posts that had a similar context but the answers were code snippets, not explanatory. And I can't even get the code offered in those answers to compile.

I apologize in advance if this is poorly formatted or explained, I am new to C and I avoid asking questions on forums at all costs but this has become a real thorn in my side.

I am using C to access the memory register of an accelerometer. This register contains 8 bits of data in the form of twos complement.

The accelerometer is set to have a range of /- 2 g's, meaning (see section 1.5 of reference manual on page 10)

My goal is to take this twos complement data and save it to a text file as signed base-10 data.

Relevant code below:

        while(1)
    {
            int d = 0;
            d= wiringPiI2CReadReg8(fd, DATA_X_H);
            d = (int8_t)d;
            d = d * EIGHTBITCONV;
            std::cout << d << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

I've tested the program by hard coding "d" as 01111111 (127) and the program returns "73". But hard coding "d" as 10000001 (-127) and the program returns the correct "-127".

So the program only functions properly when dealing with negative numbers.

Is this happening because when casting the float "d" to an 8bit integer it truncates the leading zero for positive numbers? How would I fix this?


Link to datasheet: https://www.mouser.com/datasheet/2/348/KX132-1211-Technical-Reference-Manual-Rev-1.0-1652679.pdf

CodePudding user response:

  1. You do not need to convert from 2's complement to "signed integer", because 2's complement is signed integer.

  2. You are only reading 8 bits, but int (the return type of wiringPiI2CReadReg8) has more. So you need a sign-extend conversion. Something like:

int result = (int)(signed char)wiringPiI2CReadReg8(fd, DATA_X_H);

The (int) conversion is implicit and can be omitted. And in your case you are converting to a float (The conversion is again implicit). So:

d = (signed char)wiringPiI2CReadReg8(fd, DATA_X_H);

Actually your solution (negating twice) would work as well. More explicitly it could be written like this (since 1 is int):

 d = -((int)(~(int8_t)d)   1);

But this is just unnecessary work. It could be simplified to be:

d = -(-(int8_t)d);

and now it is obviously simplifies into:

d = (int8_t)d;

same as what I wrote before.

CodePudding user response:

Ok so I think a lot of my confusion came from the fact that I was trying hard code values into my program without proper knowledge of how to do so.

If I were to do hard coding as a method to test the logic, I should have specified that the values of "d" were binary.

So it looks like my original code, while extremely sloppy, was functioning properly.

  • Related