PDA

View Full Version : My PIC can't do the math! Can yours?



sayzer
- 11th May 2006, 07:14
Is it too early to call this a bug? Or the bug is in my head?

Attached is an excel file (file extension needs to be changed to xls).

There is a match-table in the file. The red cells are incorrect math results from PIC. All other values provide the correct math result.

(16F877 with PBP2.46)

- All variables are word size.
- 20Mhz OSC and 10-bit ADC res.



'
'This is only the loop part.
'

Loop:

ADCIN 1,TempRead
IF tempread>51200 THEN tempread=51200 'Min. temp.
IF tempread<41600 THEN tempread=41600 'Max. temp.


XF=( TempRead /64)-650 'This is the formula with 1 unit increments.

XB=303 'This is the initial matching Temp value.
FOR XA=0 to 150
XB=XB-2 'Each 64 unit increment/decrement is 2˚C
if XF =XA then XF =XB 'We get the actual temp in Celsius.
next XA

Lcdout $fe,1,”Temp:”, #XF


GoTo loop






For example, if the TempRead value is 44864, then I get the XF as 199 which is correct.

However, if the TemRead value is 46464 then I get XF as 3 which is incorrect. I should be getting 149.

From 46464 to 48000 all results are incorrect. Remaining values are correct.


Should we call this a bug, I am not sure.


------------------------

Jumper
- 11th May 2006, 08:17
Hi,

My guess is that you have forgotten to right justify the AD conversion, on the 877 and a 10-bit AD the highest number would be 1024. Start by checking the setup since the numbers coming out seems tooo big.

There was a post some time ago with a similar problem, search and see if you can find it.

The bug is probably not in the PIC :-)

/

paul borgmeier
- 11th May 2006, 09:00
Sayzer,

Your PIC's math is working great!

Change the last part of your code to this:

FOR XA=0 to 150
XB=XB-2
IF XF = XA THEN
XF = XB
GOTO HERE
ENDIF
NEXT XA

HERE:
LCDOUT $FE,1,”Temp:”,#XF

Your code is actually changing the value of XF twice in the region you thought was flawed (e.g., for 46464, XB = 149. Your If Then sets XF = 149. Your loop continues and finds XF = 149. 303 - (149+1)*2 = 3 ... the math is correct)

Paul Borgmeier
Salt Lake City, Utah
USA

sayzer
- 11th May 2006, 10:39
Thanks Paul. I fixed the problem considering your catch.
I make the loop value the end number so it exits the loop.





XB=303
for XA=0 to 150

XB=XB-2
if xf=XA then
xf=XB
XA=150 'once we have the match, lets exit immediately as Paul mentioned above.
endif

next XA




Also, Thanks to you Jumper. I see what you are saying about ADCON1 but I have no issue with that register. I am now getting the correct results;

I found the bug :-)


------------

Ingvar
- 11th May 2006, 10:40
If this is all your program is supposed to do, i'd use something like this instead. Much faster.



ADCON1.7 = 1 'right justified
Loop:
ADCIN 1,TempRead
IF tempread>800 THEN tempread=800 'Min. temp.
IF tempread<650 THEN tempread=650 'Max. temp.
XF = 301 - ((TempRead - 650)<<1) '301-((TempRead-650)*2)
Lcdout $fe,1,”Temp:”, #XF
GoTo loop

/Ingvar

sayzer
- 12th May 2006, 07:28
Thanks for all replies.

When I use "right justified" ADCON1 register, as Jumper and Ingvar suggested, the scale does not behave linear. Thus, I can not match the temp reading with Celsius.

Currently, “left justified” ADCON1 register provides a scale that is perfectly linear and the formula works great (thanks to Paul's catch).

By the way, Ingvar's code is indeed nice but I can not use it.



----------