Reputation: 31
this is my problem:
I am writing a program in QtCreator which reads out some battery data (voltage, current,...). Each value is delivered in two bytes and I have to combine them into a UINT16. Sometimes my program does it right and shows the correct value (about 12V). But some other time it does not work and shows about 65V. The problem occurs only if I have connected a load to the battery. Then it sometimes says 65V and sometimes 12V. I have used an older program to oberserve the data I get from the battery and this data says all the time about 12V, so it's not the data what is wrong.
This is what I have written in my acutal program:
voltage = data[6] << 8;
voltage = voltage | data[7];
What I have found out so far:
The problem does NOT occur if the voltage reaches a specefic value (e.g. drops from 12.X V to 11.X V), there seems to be no system in it.
I have already converted the values I get into binary numbers to see if there is just anything swapped. This is not the case.
The old program does this, what is the same like in my actual program:
voltage = data[6]<<8;
voltage|= data[7];
EDIT: - This is what I know about the delivered data:
Format: Unsigned int
Units: mV
Range: 0 to 65,535 mV ==> 1000 = 1V
Some more information about how the program works, could be helpful maybe:
The weirdest thing is that it works sometimes when a load is applied and if I wait for a while it does not work any more then suddenly it works again and so on, no matter what voltage.
EDIT2:
The programs are different, there is everything different except for my passage. I only work on this passage of reading the battery data / I built this area. The old program was written using MSVisual Studio 2009 C++ Express. For the new program I'm using QtCreator with Mingw4.8 as compiler. data[] is of type QByteArray:
In .h: UINT16 voltage;
In .c:
QByteArray data = com_port.readLine(1000);
if (data[0] == '$')
{
switch (data[1])
{
case 7:
voltage = data[6]<<8;
voltage = voltage|data[7];
qDebug() << voltage;
}
}
The target of both programs is the same and I'm using the same battery.
Upvotes: 2
Views: 216
Reputation: 422
Here's my guess: IF your data[7] is signed char (either explicitly or by your compiler handling char as signed value), and IF the scale factor is 0.1 volt, then going from 12.7 volt to 12.8 volt would make data[7] a negative value. You then sign extend it to 16 bits (by an implied cast), hence your result value is something around 65000 - which is equal to around 6500V - similar to the 65V you seem to see (any chance there are a couple of extra zeroes?). The minute you drop to 12.7V or below - you're back to the real voltage.
For example:
12.7 volt = 0b01111111 -> (sign extend to 16 bit) -> 0b00000000 01111111 -> 127 -> 12.7 Volt
12.8 volt = 0b10000000 -> (sign extend to 16 bit) -> 0b11111111 10000000 -> 65408 -> 6540.8 Volt
This is just a hunch - as the actual types/scale factor are not provided.
EDIT:
What you probably want to do is
unsigned int voltage = ((((unsigned int)(data[6])) << 8) | (((unsigned int)data[7])&0xff)) & 0xffff;
You can change the unsigned int to your UINT16. You can lose some of the parentheses (based on operator priority) and drop the last "&0xffff", but this is as explicit as it gets.
Upvotes: 6