Help on multipling a variable by a fractional decimal
How do I code this in Spin? Hopfully someone will tolorate my lack of learning the basics first.
VAR
Long CH0 ' Should contain an integer from approximately 1 to 4000 max.
PUB
CH0 := MCP3202 ' Return from an ADC Driver chip.
CH0 := 100 - (CH0 * 0.05) ' THIS LINE IS MY PROBLEM CODE -- This is the first time I've worked fractional decimals.
' I'm trying to change ADC results to something that I can use.
Would really appreciate any help,
Robert
VAR
Long CH0 ' Should contain an integer from approximately 1 to 4000 max.
PUB
CH0 := MCP3202 ' Return from an ADC Driver chip.
CH0 := 100 - (CH0 * 0.05) ' THIS LINE IS MY PROBLEM CODE -- This is the first time I've worked fractional decimals.
' I'm trying to change ADC results to something that I can use.
Would really appreciate any help,
Robert
Comments
Maybe have a look at these in the OBEX:
http://obex.parallax.com/objects/689/
http://obex.parallax.com/objects/53/
Multiplying by 0.05 is the same as dividing by 20 as previously noted.
Dividing a value in the range 1 to 4000 by 20 will lose some precision. For example 35 / 20 results in 1 instead of 1.75 because we are working with whole numbers in Spin.
That may or may not be a problem depending on your application and the desired degree of accuracy.
If it is a problem you could store the variable CH0 as a number in the range 20 to 80000 instead. That is to say the units of CH0 are twentieths instead of ones.
Then when you divide by 20 you still have full precision in the result, the example above becomes 700 / 20 = 35. Where the 35 is also twentieths instead of ones and still represents an actual value of 1.75.
This is called fixed point arithmetic and is often used instead of floating point which can be a lot slower and take a lot of space in a small MCU like the Prop.
In general one would scale ones variables up by a power of 2 like 16, 32, 64, 128, 256 etc because this can be done with shift operators "<<" and ">>" which is faster than multiplies and divides.
If you want to avoid using floating point math for this it can be done with integers in most cases.
100 - (ch0 x 0.05) could be rewritten as (2000 - ch0) / 20. If you are outputting the result as a string the divide could be eliminated by shifting the result right one bit and inserting a decimal one digit to the left.
Thanks again,
Robert
Thanks for your valuable response -- you must have responded while I was typing.
Robert
BTW I knew that I could divide instead of multiply I just was using the wrong divisor instead of 20 a number that was so stupid that I am not going to mention what number I was using. I found it easier to think the program just couldn't handle the function I was trying to use.
Thanks again everyone.
Robert
No one here is likely to write something for you, but most are happy to point you in the right direction.
Returned value is off by 1 for negative i with this fraction.
John Abshier
If your centered joystick reads about 2047 (midpoint of 12-bit value) then you can use this call:
...to convert the raw joystick value to your desired range. As others have noted there will be small truncation errors, but I don't think that you can get around this outside of using a larger range for your motor speed input (mine used -500 to +500). Note,too, that joysticks don't ever auto-center exactly as we'd like so you may need to create a small deadband in the center of the pot range so that your motor(s) stop when the joystick is set free and allowed to return to neutral on its own.
I ran a test loop and there is virtually no difference in output of the two methods -- see attached.
An minimal thing which I personally do not like about that is that there is a slight shift in the results due to truncation instead of rounding. Easy to see from the output if you look at the values mapped to -100 and 100 respectively. The result is not symmetric. It can be improved by adding 0.5.
replace (raw ** 209_776_413) with (raw**419_532_825 + 1) >> 1
CH0 := MCP3202.in(0)
CH0 := CH0 / 20
If CH0 < 100
CH0 := 100 - CH0
CH0 := CH0 * ( -1 )
If CH0 > 99
CH0 := CH0 - 100
If CH0 < 8 and CH0 > 0
CH0 := 0
CH0percent := CH0