What is the best unit to use when representing voltage and temperature in ints? - Page 1
Forum section: electronics / general

author: technix
author_rank: Super Contributor
timestamp: November 04, 2016, 05:01:23 pm
content: Code:uint32_t analogReadVcc(void);uint32_t analogReadTemp(void);Those two functions uses the onboard ADC on a MCU to read supply voltage and chip temperature. What is the best units to represent those values using only unsigned integers?Does voltage in millivolts and temperature in millikelvin sound nice? I have a wide variety of ADCs to target, with ranges varying from 8 to 24 bits.

author: Andreas
author_rank: Super Contributor
timestamp: November 04, 2016, 05:26:35 pm
content: Depends on the accuracy that you really have.For the chip temperature the accuracy will be around 2 deg C (at the sensor not at the whole chip, that may vary from place to place).The noise (if you have a 24 bit ADC) will be around 50mK with normal sensors.So a resolution of 1 K or 0.1 K in a sint16_t will be good enough.Similar for VCC if using a resistor divider with 1% resistors 10mV steps are sufficient.On the other side: when scaling you are getting rounding artefacts.I usually use the ADC-result left-aligned in variables.So conversion is done at the last step for the display only.With best regardsAndreas

author: Kalvin
author_rank: Super Contributor
timestamp: November 04, 2016, 05:48:35 pm
content: Like Andreas stated above, it is a matter of accuracy you have. But, you can also use millikelvins and millivolts if you want to do it in a sake of consistency. The uint32_t has enough dynamic range for that. The other option is of course represent the temperature in kelvins and the voltage as millivolts. Just make sure you name your functions and variables carefully to avoid any mixup. Typically I would name the functions and variables with a postfix _mK, _mV, _K, _V in order to make sure that I don't make mistake when dealing with the values. For example:Code:uint32_t analogReadVcc_mV(void);uint32_t analogReadTemp_K(void);

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 04, 2016, 06:35:32 pm
content: Dimensionless.The unit is baked into the ADC's range. Software should be agnostic of it until it's time to tell the user, at which point the calibration scale is applied, and other complicated things are done like writing out decimal places.The ADC only ever measures a ratio: Vin/Vref. By tracking everything as that dimensionless ratio, you don't run into problems like error stackups, adding bizarre fractions in software (how many 0.00071825's do I have to add up to remove the offset?), and so on.The nice part about a 32 bit int is, unless your ADC is huge to begin with (24 or 32 bits, with real accuracy near there -- as you might have in a super precision DC voltmeter), you can mostly left-adjust the ADC result (i.e., shift it so the MSB is near the int's MSB), and leave all the low bits as a fractional component that just comes along for the ride. (Why "mostly" and not full left-adjust? Because you can reserve one or a couple bits for sign and overflow, too!) This makes integer math, on dimensionless ratios, very precise. You only need to round off the fractional part when it gets output to a device (user display, DAC output, etc.). You only incur the one  rounding error step, without accumulating significant errors from intermediate steps.Tim

author: technix
author_rank: Super Contributor
timestamp: November 04, 2016, 06:42:31 pm
content: Quote from: T3sl4co1l on November 04, 2016, 06:35:32 pmI do have two dimensionless functions:Code:uint32_t analogRead(uint8_t pin);uint32_t analogReadUnscaled(uint8_t);The first is conforming to the convention set in Arduino project. The latter emits the raw output of the underlying ADC in left-justice mode (e.g. in the STM32F1 implementation you are seeing the output starting at bit 15 and extend right)Those are convenient functions for developers. Some microcontrollers like STM32F1 have their ADC hard-wired to be VCC-referenced, so a convenient function like this can help in case of newbies.

author: Kalvin
author_rank: Super Contributor
timestamp: November 04, 2016, 06:46:19 pm
content: Quote from: T3sl4co1l on November 04, 2016, 06:35:32 pmWell, yes. But the VREF is known, so the function may also return the absolute measured value in Volts, millivolts or microvolts. More importantly the ratio is pretty bad as you need to expose the other parts of the system to the actual hardware implementation and VREF. Returning the absolute value hides the hardware implementation and the rest of the system doesn't need to know what the VREF is.

author: technix
author_rank: Super Contributor
timestamp: November 04, 2016, 06:54:40 pm
content: Quote from: Kalvin on November 04, 2016, 06:46:19 pmThat's the gist. My point of having analogReadVcc is that as long as you have:The 1.1V, 1.25 or 2.5V internal reference on megaAVR, orThe 1.2V internal reference on STM32F103CB, or evenAn ADR03B or REF03 on pin 9 of IAP15W4K61S4-30I-PDIP40calling analogReadVcc and you get your power rail voltage in millivolts, regardless of the actual implementation of the chip or the board.So since I have layered the software into BSP and Application layers and this code sits in BSP layer, I don't need to change a single line of application code and still get a working application when the board changes, or even when porting the application over a different architecture (e.g. 8051 to AVR to ARM Cortex-M3)

author: sleemanj
author_rank: Super Contributor
timestamp: November 04, 2016, 10:05:19 pm
content: mV there is typically plenty enough of range and ability to work in precision at mV level is desirableFor kelvin though , maybe consider using dK (decikelvin), since you probably don't need to work to mK precisions and the extra range you could get would be beneficial (in 16 bits, if you don't mind 32 bits then might as well just use mK to keep things consistent)

author: nctnico
author_rank: Super Contributor
timestamp: November 04, 2016, 10:26:11 pm
content: Quote from: T3sl4co1l on November 04, 2016, 06:35:32 pmI strongly disagree! It makes software much better readable and maintainable if the variables are in standard SI units with a prefix like mV, uA, Centrigrade, mK (milli-Kelvin), kA, etc. A 32 bit variable is (almost always) good enough to hold any value with enough significant digits so there is nothing lost there. If you need to calculate something you'll also get a value in SI units (like dividing voltage by current to get resistance) without contorting yourself by applying both voltage and current scale factors. The second advantage is that by scaling the ADC value (or vice versa for a DAC) in the ADC (or DAC) driver is that the scale factor is in the part of the software where the scale conversion belongs and not somewhere in the part which does the user interface. Over the years I've seen a lot of grief caused by forgotten ADC/DAC scale values. In some cases there can be several hardware versions with different DACs, ADCs and/or hardware scale factors (working on such a project right now) and with the variables in SI units all I need to change/test is the ADC/DAC driver with the new scale factor and the rest of the software still works as it always has been. Supporting different hardware versions from the same source code is also easier.