![]() |
loosing encoder count
I am having a terrible problem where my encoders gradually loose track of position as if they are dropping ticks or something.
Is it possible that maybie the secret IFI stuff is using High priority interrupts that take a long time and are causing the LP ISR not to execute? I notice that occasionally characters printed to the terminal are dropped as well. Then again the terminal printing thing could be a buffer overrun caused by printing faster than the UART can transmit. The relevant code is below: Code:
All you really need to look at here is the HandleTurretInterrupts() function. Code:
/* |
Re: loosing encoder count
Go to the IFI site and get the recently posted library that addresses a relatively serious problem with interrupts. This might fix your problem.
Eugene |
Re: loosing encoder count
In addition to Eugene's suggestion here are some random observations.
I assume the printf's are only there due to the prior dropped count problem, since they can delay you enough themselves to cause dropped counts. You know you are purposely dropping a count whenever you get to "p!!!!!!!" I also assume you are enabling low priority interrupts in general (GIEL)somewhere. I might add "section("MATH_DATA")" to your pragma to be on the safe side, but it doesn't look like you need it the way the code appears now. Your pan & tilt lines are reversed in code verses your later comments. Certainly crossing the B lines will drive you crazy, e.g., Code:
/*==== ENCODER PINS ==== |
Re: loosing encoder count
Other things such as serial IO are using interrupts as well. It occurs to me that the GIEL flag is disabled while they are working. If an encoder interrupt occured during this time, would its flag be set and would it be correctly handled once the current interrupt handler finished? It looks like it would but i am a little unsure. I'm grasping at straws.
I will try the library update once i get to competition, but i don't think thats the problem. Quote:
Quote:
Quote:
|
Re: loosing encoder count
Quote:
-Kevin |
Re: loosing encoder count
Quote:
The answer is simple enough as you think about what's happening. Here's an explanation for those anonymous readers who haven't caught on to the dynamics of what's going on. The A-line goes high and you count it, because you know the direction for certain. It rolls back and the A-line goes low, but the code is written to ignore that transition. Not a problem if the encoder continued to move back and hit the previous rise of the A-line. It's only an issue when the encoder is poised right at the cusp of the transition from high to low. For instance, think about what happens if just general robot vibration causes the encoder to oscillate just a tiny bit back and forth over that transition point. If the line goes high, then back drives low (so to speak) and goes forward again it looks the same interrupt-wise as constant motion forward. For this type of application no transition of the A line, high or low, can be safely ignored. Each transition of A must be enabled for both directions, going high at one spot and going low at that very same spot. Everywhere the code can add a count it also must be written to subtract a count, allowing for any backward motion of the A line as well as any forward motion at any single transistion point. I imagine Kevin's encoder code to handle this issue must test and count both high and low transitions. |
Re: loosing encoder count
Quote:
Thanks. I will rewrite my code to use the port B interrupt on change and count rising AND falling edges if i get to the regional and see that this is the cause of the issue. I didn't do this initially because i overlooked this problem and thought that both edges would just eat more processing time. |
Re: loosing encoder count
James,
It sounds like Mark has probably identified your problem, however there are two other things that you might want to change. In your HandleTurretInterrupts routine, you need to check for the interrupt enable bit as well as the interrupt flag (INT2IF & INT2IE for example) in your IF statement. Disabling the interrupt enable, doesn't stop the interrupt flag from getting set, it only disables the processor from generating an interrupt in response to the flag. For example, say you have the pan interrupt disabled (INT3IE = 0) and you get a rising edge from both the pan and tilt encoders. Both the INT2IF and INT3IF flags get set, but only the INT2IF flag generates an interrupt. In your code, since you only look at the interrupt flag and not the enable bit, you will handle both interrupt flags even though you want to ignore the pan (INT3IF) one. If you check the interrupt enable flag, you can ignore the INT3IF flag and later, once your main code reenable the pan interrupt (INT3IE = 1), the pending interrupt flag (INT3IF) will immediately geneate a new interrupt and your code can handle it then. Second, if at all possible, I wouldn't use a print statement within an interrupt. You would be better off by incrementing a variable and then printing it from your main loop if it changes (or displaying it on the dashboard). You will get the same information but not delay interrupt processing. Mike |
| All times are GMT -5. The time now is 03:15. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi