PDA

View Full Version : Picbasic Pro divide problem



Hebemabo
- 6th November 2011, 16:13
Hi All , this is my first post. Any ideas?

I have written the following code in my program for a 16F88. It works but I need to free up some memory for other routines. Is there a more efficient way to do this.
I am capturing pulses ( puls ) from an emitter wheel over a varying time. I then divide the pulses by 2.266 to convert pulses to mm. The max. pulses I will receive = 30,000 and the min. = 500.

div var word[6] ' integer of the division
rma var word[6] ' remainder of the division
circ var word

puls=25312 ' this value changes with every reading ie: 500 - 30,000
fctr=2266 ' this is a constant

'convert pulses to mm.
div[1]=puls/fctr :rma[1]=puls//fctr
div[2]=rma[1]*10/fctr :rma[2]=rma[1]*10//fctr
div[3]=rma[2]*10/fctr :rma[3]=rma[2]*10//fctr
div[4]=rma[3]*10/fctr :rma[4]=rma[3]*10//fctr
div[5]=rma[4]*10/fctr

if div[5]>4 then div[4]=div[4]+1 'round to 1mm
circ=(div[1]*1000)+(div[2]*100)+(div[3]*10)+div[4]

Darrel Taylor
- 6th November 2011, 20:19
Hi Hebemabo,

You can get the same results with ...
circ = puls ** 28922 + R2.15
Dividing fractional numbers is fairly difficult.
But multiplying them is easy.

Dividing by 2.266 is the same as multiplying times 0.44130626654898499558693733451015 ... (1/2.266)
And you can do that with the ** operator.

Multiply 0.44130626654898499558693733451015 * 65536 and you get 28922 rounded up.

The ** operator is essentially a multiply with an implied /65536.
So puls * 28922 / 65536 is the same as puls / 2.266.

The R2.15 takes the high bit of the low word from the multiplication.
It acts the same as your "round to 1mm".

Hebemabo
- 6th November 2011, 21:40
Hi Darrel , thank you very much. It works like a dream and I've saved 263 words.
Hebe

Hebemabo
- 7th November 2011, 09:07
Hi Darrel , I looked through the PBP manual to get clarity on the "+R2.15" in the code you sent me but I could not find it. I presume that R2.15 means register 2 bit 15 and that it must be used immediately in the formula else the value will change when the next statement is executed - am I correct?

My project is working very well and I have enough memory to add some refinement. I now want to make the factor a variable and it will generated in the program with a value between about 1.111 and 3.999. Do you have any magic that I can apply.

I did try the PBP manual and searched through some of the floating point threads but I don't find anything that applies. The Microchip floating point routines would use too much flash. I also thought of using a lookup table but I don't have sufficient eeprom.

Thank You
Hebe

Darrel Taylor
- 8th November 2011, 17:16
Yes, R2 is one of PBP's internal "System Registers" and if not used immediately the value would be changed.

Floating point is overrated, and not normally required.
Decimal places can usually be dealt with using integer math.

If fctr is a variable and the value is *1000 (2266 = 2.266), then you can just multiply the pulses by the same amount and use DIV32.


circ = puls * 1000
circ = DIV32 fctr

This one takes longer to execute and uses more code space than the previous example.

Hebemabo
- 8th November 2011, 21:52
Hi Darrel , thanks again. I used your DIV32 remainder tip to do the rounding to 1mm.
I still have enough flash for my refinements
circ = puls * 1000
circ = (DIV32 fctr)
@ MOVE?WW R2, _Remainder ; Get remainder of Div32
if remainder*10/fctr>4 then circ=circ+1

Hebe

Darrel Taylor
- 9th November 2011, 01:41
Great!

Nice addition Hebe.

JTCullins
- 2nd December 2011, 16:10
Darrel, you are a very cleaver guy!