Problems with Negative Floats *solved*

I have an ADXL345 I2C accelerometer where I read the X, Y, and Z values into float variables. On an arduino mega 1280, this works fine and will even show the negative numbers. On the Due, it works fine but only in the positive spectrum. If I tilt the accelerometer so the axes become negative, it starts counting down from 65537, or at least some number close to that.

The really strange thing is I can still use negative floating point numbers, so why is this so different? Here’s the part of the code where the variables are defined:

Wire.beginTransmission(acceldev); Wire.write(0x32); Wire.endTransmission();
Wire.requestFrom(acceldev,6);
byte acceldata[6];
for (int i=0;i<6 && Wire.available();i++) {acceldata[i]=Wire.read();}
Wire.endTransmission();
float ay1=acceldata[0] | (((int)acceldata[1])<<8);
float ax1=acceldata[2] | (((int)acceldata[3])<<8);
float az1=acceldata[4] | (((int)acceldata[5])<<8);

int is 32 bit on the Due, but 16 bit on the Mega - that's likely to be the problem (don't need to look at the code for that!)

[looked at code - oh yes, there you go shifting left and expecting the result to be signed 16 bit]

I'm aware the Due is 32 bit, but why exactly does that mean the number jumps to 65537 instead of -1? I want to get to the negatives, which it will do on the Mega.

EDIT: I found the solution - I used "short" instead of float and that seemed to fix the problem. But out of curiosity, what would I have to change if I wanted to keep it as float?

You have a byte - 8 bit unsigned, its cast to int (always the case in C),
so you have a 32 bit int with all zeroes in the top 24.

Shifting left by 8 cannot set the sign bit.

If int were 16 bit it would already have the sign bit set.

So normally you’d do something like this:

int a = b0 | (b1 << 8) ;
a = a << 16 >> 16 ; // sign-extend

to get the sign bit set and propagated, or as you found:

short a = b0 | (b1 << 8) ;

[ note that casting a signed type to a wider signed type will automatically sign-extend,
short is signed, so when the result gets cast to (signed) int the sign extension happens]

That makes sense, thanks for the explanation. Last night I did a little research on level shifting and how exactly the code I have works. As with many example codes, the author doesn't tend to do a very good job at explaining anything. I tend to do a lot of coding in python, where stuff like this exists but is rarely ever needed, so a lot of it doesn't make much sense.

I might try messing around with your suggestion though, instead of using short. short might give me the result I'm looking for and might actually be a better choice since it uses less memory, but I prefer to fully understand how things work.

Hi, I am writing you because I have a problem with float using Arduino Mega1280 and might be you could help me. I read your post and i am doing something similar as you are doing and it is that I am working with a robot and I need to get the coordenates X,Y,Z. the thing is that the data arrive at Serial port of Arduino byte a byte. For example I send -25.50 or 150.150 values and they are stored byte a byte. How can I get that Arduino interpret the -25.25 as a float? Ihave tried everyithing as casting etc but it doesn´t work. Could you give me some clue about it?

thanks

Have you tried using short? I don't know for sure if that works with floats. Also, have you checked out stuff like http://arduino.cc/en/Serial/ReadBytes