Truncating in multiplication problem

MearCat

Member
I am reading a 0-5V range of voltage using readadc10 and need to multiply the word value (0-1024) by 0.488 (which happens to be 5/1024*100)
I use this :

readadc10 2, Voltage
let Temp = Voltage * 5 / 1024 * 100

A voltage that returns a word value of 311, therefore Voltage * 5 / 1024 = 1.512 but it truncates the result to 1.0 before dividing by 1024 so the result of Temp ends up being 100 when it should be 151. Is there a way to get around this truncation problem?

I can't simply make the formula :
let Temp = Voltage * 5 * 100 / 1024 because any value of "Voltage" over 131 will cause the Word to overflow
 

BeanieBots

Moderator
It's really just a question of playing around with your equation "Voltage * 5 * 100 / 1024" and "Voltage * 5 / 1024 * 100".
If your input covers the full range of 0 to 1023 then it is a little harder because the first multiplication must be limited to <16.
If it has a limited range range then work out the maximum value and work back from there.
eg (Voltage * 10 / 1024 * 50)
or (Voltage * 20 / 1024 * 25)
or (Voltage * 10 / 512 * 50)
I am not aware of any special technique to work out the contants required but good results can be acheived simply by playing around with a calculator.
You could even do a test on the ADC result and change the equation acordingly.

ERRATA:
As correctly pointed out by Hippy later in this thread, a 10-bit value can be multiplied by up to 64. It is a 12-bit value that must not be multiplied by more than 16 to avoid a word overflow.


Edited by - beaniebots on 10/31/2005 7:36:21 PM
 

pha555

Senior Member
The division by 1024 is causing the truncation.

The trick is to do as much multiplication as you can without overflowing before doing any division.

Another possible approach.

'TC_10 = 4.88 * ADVal

Tc_10 = ADval * 4
Tc_10 = ADval * 8 / 10 + Tc_10
Tc_10 = ADVal * 8 / 100 + Tc_10

Hope this helps.

P H Anderson, http://www.phanderson.com/picaxe/picaxe.html
 

evanh

Senior Member
The upper limit of the first multiply is 2^16 = 65536 which is 64 times the size of your maximum 1024 reading so you can gain one decimal place simply by shifting a digit from the 100 to the 5 which gives: let Temp = Voltage * 50 / 1024 * 10

That said, looking at the final times 10 figure, you are still loosing atleast one digit. This is an effective shift left by one digit. It's not actually the multiply that is the cause of this, rather, the single divide is still too large. Reducing their sizes by a common factor will help giving: let Temp = Voltage * 50 / 512 * 5

You can introduce a little scaling error: let Temp = Voltage * 64 / 131

Or use Mr Anderson's more accurate method if speed is not a concern.


Evan

Edited by - evanh on 10/30/2005 7:36:37 PM
 

hippy

Ex-Staff (retired)
If you need to multiply the READADC returned value by 0.488 ...<code><pre><font size=2> 488 244 122 61
n * 0.488 = n * ---- = n * --- = n * --- = n * ---
1000 500 250 125 </font></pre></code> With a maximum value of 'n' being 1023, 61*1023 won't overflow ...

- LET Temp = Voltage * 61 / 125


The moral is to always reduce the divisor and dividend by factors of two until an odd number is reached, before trying to apply any other clever tricks. And don't get hung up on using 1024 ( or 1023 ) as a divisor :)

Edited by - hippy on 10/31/2005 2:02:33 AM
 

hippy

Ex-Staff (retired)
I note that there are some unintended errors as to what maximum values can be in this thread, so just to set the record straight ...

READADC10 returns a value 0..1023

The maximum value in a word is 65535 = (2^16)-1

The maximum allowed multiplier of 1023 without causing overflow is 64; 64*1023 = 65472
 
Top