- Published: Wednesday, 13 February 2013
- Written by Jon Chandler
- Hits: 5194
The power monitor I built using a TI TMP-513 and TAP-20 has worked pretty well but has suffered from some occasional glitches in the voltage readings. The problem seemed to be random and I attributed it to noise pickup. The problem always appeared as spikes of higher than the expected level; I minimized the effect by averaging readings.
Yesterday, I was making some measurements and the effect was too big to ignore. It was messing up what should have been nice smooth curves with almost a one volt error on a six volt reading. I repeated the measurements several times and had similar errors, although at different voltages.
My first thought was that there might be glitches in the serial link between the power monitor and PC. Examining the data revealed that real numbers were being sent and not the trash that results from serial port errors.
Looking closely at the data shows readings of 5.988, 5.992, 5.996, 6, 6.4, 6.8, 6.12, 6.16... Wait a minute. The 6.4 and 6.8 readings are clearly not part of the trend. This looks like a coding problem.
Voltage is read from the TMP-513 via I2C in a subroutine in millivolts. The data is read out as two bytes and converted to millivolts. All voltage readings are handled the same way with no range shifting. This subroutine doesn't appear to be the source of the glitches.
Taking a closer look at the data, if the readings were changed 6.4 to 6.04, and from 6.8 to 6.08, they would exactly fit the expected results. It looks like there's an error in the conversion from millivolts to volts and millivolts for display and serial transmission.
The millivolt data is converted to integer volts and millivolts in the two statements that send the data to the LCD and to the serial port. The same routine is used for both and is shown below.
The reading to the left of the decimal point in the conversion from mV to volts is handled by:
Since BusVoltage is an integer value, dividing by 1000 yields only the integer volt term.
The reading to the right of the decimal point is the fractional part of the reading in mV:
This part of the code subtracts the integer voltage term from the entire term, leaving only the millivolt part of the reading.
So, what happens if the reading is 5996 mV?
The left side of the decimal is 5996/1000 which yields 5 - remember integer math truncates, not rounds.
On the right side of the decimal point is
5996 - ((5996/1000) * 1000) = 5996 - 5000 = 996 mV.
What happens if the reading is 6040 mV? The left of the decimal point is 6 as it should be. The right side is:
6040 - ((6040/1000) * 1000) = 6040 - 6000 = 40 mV. The conversion routine yields 6.4 since the mV term is only two digits. D'oh. Leading zeros are lost on the mV term, shifting the remaining digits over. This explains why the glitches are always an increase in value, and why they're never more than ~ one volt.
Fortunately, Swordfish makes this an easy fix. The DecToStr conversion routine provides for leading zero padding.
function DecToStr(pValue as type [, pPad as byte, pPadChar as char = "0"]) as string
pValue - The number to convert. The argument can be of type boolean, byte, shortint, word, integer, longword or longint.
pPad - An optional parameter which will pack the left hand side of the returned string with (pPad - length of numeric string) zeros.
pPadChar - An optional parameter which changes the default packing character.
This function will convert a number and return a string decimal string representation of the number passed. Optional pPad and pPadChar arguments can be used to format the returned string value. For example,
MyString = DecToStr(42) // result is "42"
MyString = DecToStr(42,5) // result is "00042"
MyString = DecToStr(42,5,"#") // result is "###42"
When troubleshooting software, take a systematic approach to determine where the problem may be. When you have isolated a portion of the code that may be the problem, logically try some test cases to see what happens step by step.
Troubleshooting the power monitor code was made easier by having a clear case where the glitches occurred. If the data was random instead of a smooth curve, this fault would have been very difficult to isolate.