casting

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

hi
i read value from the ADC, and I stored it in an unsigned char
uint8_t Sample_a = ADCH;
Then I want to calculate the input voltage
double voltage = Sample_a*0.01953 (5 volt the reference and i use 8bit)
When I check the time in the debugging mode it turns out 0.2ms is required to make only this calcaultion (CPU 4MHz).
Anybody has a suggestion how can I made this faster?
thanks

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

Do it with scaled integers. Most MCU apps don't require float.

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

Make sure you're linking the optimised floating point library (-lm), not relying on gcc's generic routines. From memory, a floating point multiply is about 160 cycles using the optimised library, which is 0.04ms at 4MHz, about five times the speed you're seeing.

Christopher Hicks
==
PS That's assuming you're using a variant of the AVR which has a hardware multiplier.

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

thanks
Cristopher, I don't understand exactly what do you mean and how can I linking this optimised floating point library?

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

Do you use a Makefile or Studio? If a Makefile than make sure the LDFLAGS includes a "-lm". If using Studio go to project config, libraries and make sure libm.a is copied from the left pane to the right

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

thanks for yours advice, now it is much faster. I try to solve the problem with scaled integer numbers.

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

Quote:

double voltage = Sample_a*0.01953 (5 volt the reference and i use 8bit)
When I check the time in the debugging mode it turns out 0.2ms is required to make only this calcaultion (CPU 4MHz).
Anybody has a suggestion how can I made this faster?

8 bit is 2.5 decimal places of raw data precision. Except on a squeaky-clean analog design there may well be additional loss of accuracy. So what good is the result of a calculation to 4 decimal places? Only half of the result is meaningful anyway.

Quote:
Do it with scaled integers. Most MCU apps don't require float.

Quote:
I try to solve the problem with scaled integer numbers.

I have a brute-force VisualBASIC program that I often use in situations like this. Given a multiplier as you have, it calculates all the numerators and denominators that might work.

Most often it is a conversion factor of some kind to display units, or a ratio representing a slope in a y=mx+b conversion from ADC counts to some other units.

Let's see what happens with your 0.01953 to convert ADC counts to volts. Instead of coming up with volts, let's have a final result of millivolts and look for a ratio for 19.53. There will be no loss of precision here for either 8-bit or 10-bit ADC results.

An obvious ratio then is 1953/100, but then we need to do an intermediate "long" step. Not a killer, and is almost always the way I do it anyway in practice. Still, let's see what else we can do. 332/17 looks very attractive, but can still overflow 16 bits with the multiplication.

Let's relax the rules a bit from E-4 to E-3. Perfect: 254/13 is good to 8.5E-3 which should not lose any precision, and the multiplication result will fit within 16 bits.

Especially with coarse measurements like your 8-bit input, tweaking the conversion ratio a hair can come up with some very low ratio numbers.

You get lower multipliers when the ratio is lower. Going back to your original 0.01953 we find that this is almost exactly 1/51. So we can get hundredths of volts by using 100/51 or 200/102 to E-5.

Lee

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.