View previous topic :: View next topic |
Author |
Message |
John L Guest
|
Strange behaviour at subtraction? |
Posted: Sun Jan 18, 2004 6:14 pm |
|
|
Hi all,
I measure a frequency using the CCP and timer2 to output it on the RS232 every 64ms. It works fine so I figured I should add a simple way to also output the derivative in the same time so I did something like this:
//GLOBAL VARIABLES
int speed; //set by other CCP interrupt
float acc;
#int_timer2
timer_2_isr(){
static int speedold;
acc=(float)((speed-speedold)/0.64);
printf(" %3u %04.2f", speed,acc);
speedold=speed;
}
I've encountered two problems. It works fine as long as the speed is increasing (speed>speedold) but not when it's decreasing. A good output may look like:
108 6.25 --> 114 9.37 [(114-108)/0.64)=9.375] ok!
and a bad:
145 376.56 --> 124 367.18 [(124-145)/0.74=-32.8125 not 367.18]
The second problem is that I do not get leading zeros but I consider this a minor error... :-) Any ideas?
Best regards,
John, (16F874 using PCM3.128) |
|
|
Charlie U
Joined: 09 Sep 2003 Posts: 183 Location: Somewhere under water in the Great Lakes
|
Casting to float |
Posted: Sun Jan 18, 2004 10:50 pm |
|
|
John,
It's good to see that you are using the casting feature, but I fear that you may not be achieving the result you are anticipating. You are dividing the difference of 2 ints by a float, then casting the result to a float. You may want to try casting the difference to a float, then dividing by the float. Also, if speedold in greater than speed, the result is negative and you are using ints not signed ints. This may also cause problems. So look into changing the arithmetic to something like the following or declaring speed and speedold as signed ints:
acc=((float)((signed int)speed-(signed int)speedold)/0.64);
Just a thought.
Floating point arithematic can be a bit time consuming. You might also consider moving the floating point calculation out of the isr. In general, the isr code is best kept to a minimum. |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
Too much in ISR |
Posted: Mon Jan 19, 2004 7:23 am |
|
|
Just expanding on what Charlie said, ISRs need to be kept as small as possible. I had tremendous problems when I had large code in an ISR, lots of seemingly random events started happening. 32 bit floating point on an 8 bit processor is very time consuming, so even though the actual 'C' code looks small, the underlying machine code will _not_ be!
When I have to do things like this now, I create a main loop which cyclicly checks lots of flags which trigger events if they are true.
So, if you set a boolean type flag in the ISR, then in the main loop, test for it being true, clear it, then do your floating point. This I think is the best way of ensuring events are not missed.
Neil. |
|
|
Christer
Joined: 12 Sep 2003 Posts: 3
|
|
Posted: Mon Jan 19, 2004 10:30 am |
|
|
It is a problem with leading zeros. Search the forum and you will find. _________________ Christer TENNSTEDT |
|
|
John L Guest
|
|
Posted: Mon Jan 19, 2004 3:46 pm |
|
|
Thanks for the input! It turned out to be bad type casting so it looks like I'm getting away (at least this time) with a large ISR...
Concerning the leading zeros I'll probably have to fix it in the computer instead. But as long as the PIC does its job it's ok!
Thanks again,
/John |
|
|
|