John Wood
John Wood

Reputation: 21

Unsigned int to signed floating point with python

Ok this has been bugging me for awhile now!

I have a Tri-Metric battery monitor which serial outputs data to an Arduino, where I convert and scale the output to be sent over Modbus TCP to my Raspberry Pi where it is then descaled and added to a mysql table. I,m currently using php to do this but want to move it to python, feeling that it would be more efficient than PHP.

The data say the amphours used by the system which goes negative when the battery is discharging after the sun goes down.

I scale the data by multiplying by 10 and converting to an unsigned 16 bit integer to meet Modbus specifications.

I need to know how i can change this unsigned 16 bit integer back to a signed floating point number to add to my database.

for example this is the raw data from Modbus 65365 the unscaled equivalent should be -17.2 AmpHrs.

Any assistance with this would be much appreciated.

This is how i convert it On the Arduino

cmdData[k] = '\0';        // add termination NULL char for float conversion:                                                       
cmdFloat = atof(cmdData); // convert char array upto NULL to float:                                                                     
cmdValue = int(cmdFloat * 10);  // convert to int16_t and scale up by 10:                                                                     

amp_hours = (uint16_t)cmdValue;
            Serial.print("Amp Hours: ");
}
Serial.println(cmdFloat);  //serial print the float value
}

In python i have tried

amphours = usamphours/10 if (amphours & 0x80000000): amphours = -0x100000000 + amps

Also tried

amphours = amphours&0xffffffff

non of which works

Upvotes: 2

Views: 4453

Answers (3)

Mark Ransom
Mark Ransom

Reputation: 308520

Converting from an unsigned integer to a signed integer of a specific size is easy in Python, if a bit tricky:

signed_value = unsigned_value if unsigned_value < (1 << bitsize-1) else unsigned_value - (1 << bitsize)

Once you have that, just divide by 10:

float_value = signed_value / 10.0

Upvotes: 3

stanleyli
stanleyli

Reputation: 1487

Dealing with signed/unsigned integer, or converting between 16-bit/32-bit/64-bit integers in Python is a nightmare.

You can use bitstring module to convert between these types. For example:

a = bitstring.BitArray(uint=65365, length=32)
print a.float

9.159587412059167e-41

Upvotes: 1

donkopotamus
donkopotamus

Reputation: 23216

This will depend entirely on how you are "converting to an unsigned 16 bit integer".

If this is being done as, for example, a raw cast from float to int (perhaps via a union), then you can decode this buffer within python using the struct module. Pay attention to endianness.

Upvotes: 0

Related Questions