|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
|||
|
|||
|
Vex Encoder Code
Im just getting started on programming Vex with mplab. I have already worked with simple limit switches to control actions but now I would like to branch out into the more difficult realm of encoders.
I wrote a program that today that works but isnt correct. Code:
void StartRightEncoder(void)
{
oldstate = rc_dig_in05;
state = rc_dig_in05;
if(oldstate != state)
{
rtick++;
}
oldstate = state;
}
It works to the extent that rtick increases, but I have a feeling that due to condition of incrementing rtick, I am missing many ticks from the encoder because it simply doesnt get the ticks quick enough. My emperical evidence is that when I set my motors to go when rtick is less than 270 (3 complete revolutions and with a wheel diam of approximately 3 inches, the code should make the bot go 9 inches give or take for round off error), the bot went more like 3 feet. How does everyone else actually detect all the ticks? I checked the sample code on vexlabs but the encoder code isnt ready yet in the sample code download. Last edited by CircularLogic : 02-08-2006 at 15:42. |
|
#2
|
|||||
|
|||||
|
Re: Vex Encoder Code
Couple of issues.
The code you posted seems to be fundamentally flawed, because "oldstate" always equals "state". Essentially, oldstate = state = rc_dig_in05; rtick will only increase if the encoder happens to "tick" exactly between those first two lines of the setting of oldstate and the setting of state. That can happen sometimes, but it would be pretty random. You want to avoid "windows" like this in your logic where all the ticks happening outside those first two lines are being ignored. I assume you are polling the encoder, but are maybe polling it from the code slow loop? It should be polled from the fast loop. If you are running autonomously that would mean you need to call your function from User_Autonomous_Code() right before the line: Code:
if (statusflag.NEW_SPI_DATA) /* 18.5ms loop area */ Code:
void StartRightEncoder(void)
{
static unsigned char oldstate=0;
state = rc_dig_in05;
if(oldstate != state)
{
rtick++;
}
oldstate = state;
}
You should try both ways to get the experience. - Polling is just checking the encoder every software loop. Polling works if the encoder updates are slow enough. To be safe you should calculate how many ticks per second you expect and compare that to how fast your code is polling. Polling the encoder should be performed in the fast loop, so you are less likely to miss a tick. Polling too slow will cause you to miss ticks and go further than you wanted. As a rough rule of thumb you want to poll at least twice as fast as the ticks will come in. For instance, the slow loop in the vex controller runs at 18.5ms, so it makes 54 loops per second. The vex encoder is 90 ticks per revolution, so if it's more than a quarter revolution per second you'll be dropping counts as it moves. For your case if the robot covers the 9 inches in less than 11 seconds you'd be getting faulty counts. On the other hand the fast loop might give you on the order of a hundred thousand polls per second, so you could safely cover that same distance in 5.4 milliseconds without losing count! -Interrupts are more reliable for higher speed ticks in that whenever the encoder state changes the PIC hardware immediately notifies your software - sort of like a good poke in the side. No matter what else your code is doing it will stop, add the tick, and go back to what it was doing before. P.S. You still must calculate how fast you expect the ticks to arrive to be sure the interrupts don't happen too fast to handle. The danger to watch out for here is getting so many interrupts per second that the PIC gets overwhelmed. Last edited by Mark McLeod : 03-08-2006 at 08:21. Reason: Wanted to mention "window". There's always a window. |
|
#3
|
|||
|
|||
|
Re: Vex Encoder Code
Alright, so I have fixed my StartEncoder functions to eliminate the window in my logic and I placed those function definitions in User_Routine_Fast. I actually want the effect of this function to happen during user control, so I have the call to StartRightEncoder() placed in User_Routine.
I placed all function definitions right before Code:
void Process_Data_From_Local_IO(void) I suspect that I am still not polling fast enough (due to the fact that I dont actually have anything in Process_Data_From_Local_IO) but when I placed my function definitions in Process_Data_From_Local_IO, I recieved a whole bunch of errors. When I placed my call to StartRightEncoder() in Process_Data_From_Local_IO, I got a very odd pulsing of the motors (meaning they would run for a second, stop for a second, and then continue on in that pattern) when combined with the function Code:
if(GetRightTick() <= 180)
{
pwm04 = 255;
}
Thanks for your help Mark, I know I ask a lot. |
|
#4
|
|||||
|
|||||
|
Re: Vex Encoder Code
Your function definitions cannot be placed inside another function such as Process_Data_From_Local_IO(), so that's why you saw all those errors when you tried it. The function definitions can actually go in any file you like (even your own new file). Declaring your functions is like setting up a library of stuff you can call on to do. It's where and how you call them that's important.
Your description of the robot's behavior sounds clear enough. You're right that you have to call your polling function StartRightEncoder() from within Process_Data_From_Local_IO() to get the faster polling during regular user driving. So concentrate on fixing the odd pulsing you're seeing. Offhand I'd say odd pulsing like that is the symptom of a variable overflow. pwm04=255 while GetRightTick() returns values of 0 to 179, then I assume you set pwm04=127 somewhere else. Because of momentum the robot continues to roll forward (or the wheels continue to spin) even though the motors are off. The momentum means you still get encoder counts, so rtick continues to get bigger and bigger. If rtick is declared as an unsigned char, for instance, then when the count tries to increase to 256, rtick will suddenly wrap around to be 0 again and your code will set pwm04=255. Hence, pulsing motors. The same thing will occur eventually with larger variable types as well, e.g., a signed int would buy you 91 feet of travel. Your variable rtick needs to be a pretty large variable type. Large enough to hold the distances you're planning to cover. What type are all your variables? Last edited by Mark McLeod : 06-08-2006 at 14:59. |
|
#5
|
|||
|
|||
|
Re: Vex Encoder Code
Both, rtick and ltick (for the StartLeftEncoder function) are unsigned ints.
If I use GetRightTick() (which returns rtick), the function works fine. However, if I use GetLeftTick(), I get the odd pulsing again. I cant see any differences in my code between the two functions besides the names and the variable returned. Code:
void StartRightEncoder(void)
{
state = rc_dig_in05;
if(oldstate != state)
{
rtick ++;
}
oldstate = state;
}
unsigned int GetRightTick(void)
{
return rtick;
}
void ClearRightTick(void)
{
rtick = 0;
}
void ClearLeftTick(void)
{
ltick = 0;
}
unsigned int GetLeftTick(void)
{
return ltick;
}
void StartLeftEncoder(void)
{
state1 = rc_dig_in06;
if(oldstate1 != state)
{
ltick++;
}
oldstate1 = state1;
}
void Process_Data_From_Local_IO(void)
{
StartRightEncoder();
StartLeftEncoder();
/* Add code here that you want to be executed every program loop. */
}
Those are all my functions and are all placed in User_Routines_Fast Code:
if(GetRightTick() <= 300)
{
pwm04 = 255;
pwm03 = 0;
}
And then when I use GetRightTick(), if i want my wheel to spin twice (which should be 180 ticks), I have to set the tick number to 308 to get close to two spins. Its times like these that I wish someone had a vex encoder function posted on the internet. |
|
#6
|
|||||
|
|||||
|
Re: Vex Encoder Code
There's a typo in StartLeftEncoder.
state gets used in the if check instead of state1. I'd consider standardizing your naming convention, e.g., ltick and lstate and loldstate or all the other way. The typos might make themselves more obvious that way. Consider adding an else to your "<= 300" of pwm04=127;pwm03=127; so it's explicit that the motors are being turned off. I'd try adding a printf to watch what ltick and rtick do when you turn the encoder by hand one revolution. You're learning so much more writing this yourself! Last edited by Mark McLeod : 07-08-2006 at 19:36. |
|
#7
|
|||
|
|||
|
Re: Vex Encoder Code
Doh, darn typos.
I fixed that and the Left encoder functions work just as well as the right encoder functions. I have tried to use some printf()'s but they dont actually print to anything. Nothing shows up in the ifi loader terminal. Am i missing something? |
|
#8
|
|||||
|
|||||
|
Re: Vex Encoder Code
Quote:
Code:
#include <stdio.h> |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Encoder Code | Kevin Watson | Programming | 47 | 18-02-2008 12:56 |
| VEX Shaft Encoder Kit | jeffmorris | FIRST Tech Challenge | 1 | 19-05-2006 12:23 |
| Issues with encoder code | jgannon | Programming | 7 | 26-03-2006 15:12 |
| FRC easy-c vex encoder function? | Gdeaver | Programming | 2 | 23-01-2006 08:03 |
| Updated Encoder Code Available | Kevin Watson | Programming | 2 | 04-01-2005 01:00 |