Electronics > Microcontrollers

ADC/DAC Conversion to "decimal", best practices....

(1/23) > >>

Christopher:
So I'm doing a project with the use of some high-precision DACs and ADCs and am after some advice on how to do the conversion!

Just say I have a 12-bit ADC. I want to convert the output to a string using some kind of itoa() function (included in my C compiler)

I do not want to use Floating points, for obvious reasons.

So, I have 12 bits, which represents 0-10V, so each bit is worth 10/2^12=2.4414mV

My ADC result is 0-4095. I need to convert this to be 0-10V as a string.

Because the numbers aren't very easily divisible by 10 without floats (hardware cannot use an easier reference),  I'm struggling a bit. We were never taught this kinda thing at college either....

Also, the DAC part should be the same, just in reverse?

helius:
Think carefully about how you will handle over-range, and whether you need to compensate for nonlinearity over the whole range.
If you are fine with using itoa() or printf("%d") then the conversion to base 10 is already being done for you. All you need to handle is the conversion from a range (n/4096) to two range parts: (n/10) and (n/10000).
A naive way of doing it is to first multiply the value by 100000 and then divide by 4096:
long voltage = adc_val * 100000UL / 4096;
There are other tricks with tables that can have better performance.
The key word to search for is "fixed point representations" (like floating point, but the exponent doesn't change).

JPortici:
I like the naive way. you want to avoid divisions as much as possible, even when you have an hardware divider and not only because computational speed.
"cheating" like this (multiply then shift out bits) will be FAST and will retain the greatest amount of information after you throw away those 12 bits

Kleinstein:
Performance of the  *100000UL/4096 is not that bad:  4096 is a power of 2 and thus shifts can be used instead of a full division. The 100000 can also be adjusted to do software scaling in case the full scale is not at  exactly 10 V but maybe 10.05 V.

hamster_nz:

--- Quote from: Christopher on June 08, 2016, 06:20:50 pm ---My ADC result is 0-4095. I need to convert this to be 0-10V as a string.

--- End quote ---
First suggestion would be to convert it to milivolts (0-10,000) (maybe more on this in a later post), then convert to a string with repeated subtraction. Here's some pseudocode:

--- Code: ---  set string to "00.000"
while value > 10000
string += 1
value -= 10000

while value > 1000
string += 1
value -= 1000
((( Skip the decimal place )))
while value > 100
string += 1
value -= 100

while value > 10
string += 1
value -= 10

while value > 1
string += 1
value -= 1;