converting adc results to decimal display

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I need to convert the result from my atmega328 ADC to a format where I can display it on a seven segment display. I am using a 5V reference for the ADC (which is 10 bit) so 1 bit = 5/1028=4.89mV . I have to multiply the result form the ADC by this number to get the actual voltage in, but I want the result to be as accurate as possible - I don't want to round up to 5.

What are some ways I can do this? Do i have to use fixed / floating point maths? 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

value_mv = (read_value *5 *(uint32_t) 1000)/1024;

 

Every multiplications are done first, without loss of precision; read_value has 10 bits; 1000 is ten bits, too; product -23 bits - fits into 32 bits;

BTW : what is the accuracy of your supply/reference "5v"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

5.0V/1024=4.8828mV

Multiply ADC result by 4883UL and display the high order decimal digits.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

value_mv = (read_value *5 *(uint32_t) 1000)/1024;

 

Every multiplications are done first, without loss of precision; read_value has 10 bits; 1000 is ten bits, too; product -23 bits - fits into 32 bits;

 

Note that when you have fixed values like this, I always look for the simplifications.  5000/1024 is the same as 625/128.  625*1023 just fits into uint16_t.

 

[In a trivial test program, the inclusion of 32-bit operations doesn't matter much for cycles and space.  FP could be used.  But in a "full" e.g. Tiny or Mega48 app it can make a sizable difference.]

 

There is an age-old debate about the /1023 and /1024, and whether the ADC result should ever be 5.00V for a 5.00V signal and a 5.00V reference.  A 0-5V control signal from the outside world rarely reaches each extreme.  For a "voltmeter" app I usually call below 10 counts or so 0V, and 1000 counts over that (and above) 5V, so 5mV/count.  In practice that works quite well.

 

If arithmetic simplification as I did above isn't as clear cut, I have a VisualBASIC (and C#) program that tries all possible usable ratios.  In nearly all cases, one can find a ratio of small numbers that is good to many decimal places and obviates the need for wider arithmetic.  Let me try an example:  Let's say in this case we want 5000/1023 which has no obvious simplification...to stay within 16 bits with 1023 ADC counts:

 

4.887585533 8.5533E-005 ==> 391 / 80
4.887585533 5.4916E-005 ==> 435 / 89

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Wed. Feb 18, 2015 - 06:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Theush : I did not dare to simplify (makes things unpleasant to read... and typo-prone ) but using unsigned integers instead of unsigned longs / uint32_t  avoids a multiplication and makes division 4 times faster -and shifts (1024 is a power of 2 ) 2 times faster- ....