View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
float math |
Posted: Thu Oct 08, 2015 12:08 pm |
|
|
Hello Friends,
I know that floating point are so hard for PCM,PCH micro. I want to use example "ex_tank.c" for simple level tank volume measurement system.
Is it possible without float math ? Any suggestion and advice for math and which MCU for this project ?
Best Regards! |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Thu Oct 08, 2015 5:17 pm |
|
|
It's more what other things the mcu is doing, to decide what mcu to use. All will do the job. Math operations are hard on cpu cycles. Using an int32 or int64 will reduce cpu cycles to get the job done depending on the accuracy needed. But for basic use and convenience just use the float. 16f part will be the slowest, 18f will be faster, 24fj will be faster yet and the fastest will be the 24E, that is if you have the pcd compiler.
drolleman |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Oct 09, 2015 3:20 am |
|
|
Thanks for your answer mr. "drolleman".
In "ex_tank.c" has math with trig function.
Code: |
temp1 = PI/2 + 4*offset_height*temp1/(diameter*diameter)
+ asin(2*offset_height/diameter);
|
Is it possible to do this calc with same precission without floats?
P.S. With PCM device like 16F1459 this simple example take more than 80 % of Flash ROM. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Oct 09, 2015 4:53 am |
|
|
it all depends on the precision you need .
you can do this with scaled 32 bit integers where lets say
your dimensions are in centimeters.
* multiply all you dimensions by 100 or 1000
* define PI as say PIX at 314 or 3142
then doing the same math with 32 bit integers will leave lots more prog space free.
you can use printf with %w formatting to insert the decimal place where you want it for output
Last edited by asmboy on Fri Oct 09, 2015 7:02 am; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Oct 09, 2015 5:53 am |
|
|
also..
don't do 'PI/2'. Instead define a variable say halfPI = 1570. division takes a LOT of memory and CPU time.
if you want to get real clever precompute(use a PC or calculator) so the math uses binary divisors or multipliers( /8 instead of /10, /32 instead of /100.It is far easier and faster for the PIC to work in binary.The 'math' then becomes simple for the PIC, though harder for you .
when you 'think like a PIC' you'll be able to do more complicated math faster taking less memory.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 09, 2015 6:34 am |
|
|
temtronic,
PI is a constant in math.h, and the compiler does the division at compile
time, not at run-time. See the ASM code below from the .LST file.
The compiler is loading PI/2 (1.57079637051 in Microchip 4-byte
floating point format) into temp1. No division routine is called:
Code: |
.................... float temp1;
....................
.................... temp1 = PI/2;
06D8: MOVLW DB
06DA: MOVWF temp1+3
06DC: MOVLW 0F
06DE: MOVWF temp1+2
06E0: MOVLW 49
06E2: MOVWF temp1+1
06E4: MOVLW 7F
06E6: MOVWF temp1 |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Oct 09, 2015 7:17 am |
|
|
The example here is just that. An example. It is trying to show that the PIC can do some quite complex maths if you are not worried about size or speed.
Now the powers can more efficiently be done by simple multiplication. It is much more efficient (and more accurate...), to generate x*x*x than to generate x^3!. So a lump of the code can be shrunk straight away. You may be surprised at how much this alone can save!... Then the accuracy is in part 'fallacious'. The actual sin functions for instance do not give the full accuracy of the maths. Basically it takes too long to solve things really well. You can do a remarkably good 'integer cos' (giving the results in something like 1/100000th parts), that is quicker and smaller than the standard functions. I've done fast LCD libraries like this, using just a look-up table, and interpolation.
Now, I'd say any of the reasonably experienced programmers here could re-write 'ex_tank', in an afternoon, to give results accurate to a small fraction of a mm^3, and using probably 1/4 the time and space. However it'd involve some thought, and so if you want to do this, the _you_ are going to have to do this....
However just try getting rid of the pow terms and using *. It might save all the space you need. Just tried it using the example code for the 452, and generating this function:
Code: |
float pwr3(float x)
{
return x*x*x;
}
|
which I substituted for the two calls:
pow(......,3)
Size dropped from 32% to 20%.
Shows how one tiny bit of thought, can make a huge difference!. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Oct 09, 2015 12:03 pm |
|
|
Thanks for all advice and suggestion. It will be very helpful for me. I did not understand how to replace trig function without float. Any example ? |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Fri Oct 09, 2015 1:33 pm |
|
|
1st why are you using a 16f part?
Is this a large scale product, is the cost of the mcu important in the calculation? Can you add a couple of $$. if so go to a 18f or 24f part.
If you are at 80% already you will run out very quickly. The way 16f parts uses memory should have been retired a long time ago. I don't know why it still is used. When they retired the 17f they should have done the 16f as well.
1st guess of how much program memory requirements are. Then get a device that has double that or more. Start here then find the part to fit the job.
Trying to stuff in a shoebox in harder than placing the item in a large box.
Get it functionally working first, even if it is bloated. Then trim it down like the previous posts suggest.
drolleman |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Oct 09, 2015 4:58 pm |
|
|
come clean. WHAT are you trying to accomplish ? |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Fri Oct 09, 2015 11:49 pm |
|
|
Thanks for all suggestion developers! All they are Welcome!
I'll use 18F it's no problem , but I was wondering that above simple math calc take so much ROM memory.
Because "asmboy" ask I will tell the project requirements:
Horizontal cylinder tank volume meausurment system (max 6 tank). In all tanks there are level meausure device which return level in "mm".
Returning level, volume over serial protocol like modbus rtu.
Thanks and Have a Nice day! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Oct 10, 2015 5:04 am |
|
|
OK.
If you look at the example, the complexity is because the tank here has elliptical ends. A simple tubular tank doesn't.
The area is just PI*R^2, and the volume, this * height.
Your actual maths size will be tiny compared to the example. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Sat Oct 10, 2015 6:31 am |
|
|
Ttelmah wrote: | OK.
If you look at the example, the complexity is because the tank here has elliptical ends. A simple tubular tank doesn't.
The area is just PI*R^2, and the volume, this * height.
Your actual maths size will be tiny compared to the example. |
Hi mr. "Ttelmah" this is calc for vertical cylindrical tank. In my case tank is horizontal cylinder.
Thanks, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Oct 10, 2015 8:22 am |
|
|
That doesn't make things much worse. Look for the solutions for the area of a segment of a circle. It's just the area of a sector of a circle, with the area of a triangle removed. Obviously, the volume is just this area times the length of the tank. Still doesn't get involved in the complexities of the elliptical ends involved in the example given. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Sat Oct 10, 2015 9:12 am |
|
|
Hi again mr."Ttelmah",
In "ex tank.c" the volume of ellipsoid ends are calc with :
Code: |
offset_height = height - diameter/2;
temp1 = pwr(offset_height,3) - 3*diameter*diameter*offset_height/4
- pwr(diameter,3)/4;
cap_vol = -PI*cap_length*temp1/(3*diameter); |
which does not require trig function. Volume of horizontal tube cylinder :
Code: |
temp1 = sqrt(diameter*diameter/4-offset_height*offset_height);
temp1 = PI/2 + 4*offset_height*temp1/(diameter*diameter)
+ asin(2*offset_height/diameter);
tube_vol = tube_length*diameter*diameter*temp1/4; |
which require trig func.
And all Volume :
Code: |
volume = tube_vol + 2*cap_vol; |
And the main question still are how to calc "Only" volume of tube h-Cylinder without using floats ?
Thanks, |
|
|
|