![]() |
encoder vs. motor
I have a robot with a mechanical encoder attatched to an arm with a motor to lift the arm.
the encoder is at 50 resolution the arm motor is attatched to pwm_02 the encoder is attatched to rc_dig_in06 I calculated that the encoder will "click" or turn on and off 10.7 times for the distance I need.(the encoder is 50 resolution). basically I need the source so the motor attatched to pwm_02 will stop once the encoder "ticks" 10.7 (or eleven) times. Please keep it simple. I don't have time to go through a tutorial right now. thank you so much for the help. oh yeah, it would be nice If I could have the arm lift at the touch of a trigger on a joystick attatched to p1_sw_trig. and have the arm go back down at the touch of the trigger again. does the operator interface controller provide a way to simply shut everything down immediately in the event of a disaster? please help. thanks, Stephen |
Re: encoder vs. motor
Stephen,
I think it would be best for you to attempt to write this code yourself. It is very simple (count to 11)... If you post your code, I'm sure that one of us will critique it for you before you load it into a robot. Regards, Mike |
Re: encoder vs. motor
can you look at this and tell me if you see any errors.
Code:
//the encoder is at 50 resolution |
Re: encoder vs. motor
Quote:
"encoder" needs to be static or a global, so it retains it's value from call to call. The check on rc_dig_in06 will increment "encoder" more often than every "tick" "encoder" might shoot right past 11 and keep going. But first what model encoder are you using? |
Re: encoder vs. motor
Quote:
|
Re: encoder vs. motor
Quote:
A good start. First of all, you have not initialized your counter (maybe this is done in your actual code... I don't know). Second, what happens the next time through the loop? I'm assuming that you will want to perform this maneuver again and again (once again, I may be mistaken). For now, I will assume that this is a one shot deal... Here is what I think will happen: When the encoder hits 11, the arm is turned off but the encoder micro-switch is still "closed". The count will increase to 12 and the arm will continue to travel. You might want the last test to be "encoder > 11"... Does this make sense to you? |
how about this code.
we tried to keep the motor speed down so the encoder will read each tick before the program refreshes. so the motor doesn't "beat" the program before it reads the encoder.
Code:
//the encoder is at 50 resolution |
Re: how about this code.
Could work.
You still need to initialize "static unsigned int encoder= 0;" as Mike mentioned. I still think you're going to count each encoder tick more than once and your arm will end up short of the expected position. ( I have to pickup my daughter and will check back later) |
Re: how about this code.
Quote:
You can see I attempted to reformat your code to make it more readable. Now you can see how your code nests... I agree with Mark. I'm not worried about you missing an encoder ping but rather that you will get multiple hits at one ping. You should consider implementing a state machine. Do you have a mentor on your team (what team are you with anyway?) who can teach you what a state machine is? |
Re: encoder vs. motor
thanks for the help and tips. I'll have to look into state machines. Today I was in a kind of hurry (which was probably obvious). but now I've got more time to think things through. Our team doesn't really have any mentors for programming. We never have, last year we had a wiz kid, and this year its kinda up to me and another guy. neither of us have much experience. I programmed with c#, but that was with Windows, which tends to behave much differently than a robot :yikes: . our team number is, I'm not sure. we're team "lugnut" though, from Ohio.
|
Re: how about this code.
Quote:
|
Re: encoder vs. motor
Quote:
Quote:
|
Re: encoder vs. motor
lol. great! yeah, this chiefdelphi site has been an awesome help.
well, the encoder is an EC202AXXX (with 50 resolution) |
Re: encoder vs. motor
so like with this code
Code:
//the encoder is at 50 resolution |
Re: encoder vs. motor
Quote:
What you have is not a mechanical encoder. It is an optical encoder made by CUI. Here is a spec sheet: EC202A050A2(S or T)D. As you can see, it comes in two flavors a horizontal or vertical mount. More importantly, it has a quadrature output so that you can determine direction in your code. Team 177 used a very similar device last year. I very, very strongly suggest that you download Kevin Watson's example code for optical encoders at http://kevin.org/frc/ and download the file edu_encoder.zip open it up and examine his code very carefully. What Kevin did is for the edubot. You will have to do the same stuff to the RC code. However, over 50% of the work has been done for you. It works like a charm. Trust me... |
Re: encoder vs. motor
Quote:
|
Re: encoder vs. motor
Postscript:
Go to Optical Encoder Tutorial and read the sections "Introduction To Encoders" and "Technical Overview". I'm sure you will have questions... Post 'em here... |
Re: encoder vs. motor
Continue in the direction Mike is sending you. I just want to address some of the previous outstanding questions.
Quote:
The statement “static unsigned int encoder = 0;” will only take effect at compile time, not while the code is running. It sort of nails the variable in place and sets it’s initial value only once. The statement “unsigned int encoder = 0;” will take effect while the code is running. Every time the routine is entered the variable encoder will be “created” and assigned the value of 0. Referring back to Sean’s comment earlier about only counting rc_dig_06 when it changes, not every pass through the code that it happens to equal 1… The following is an example of only counting changes in rc_dig_06. This particular method actually doubles the resolution of your encoder as it counts both when it changes to 1 and when it changes to 0. Code:
static char toggle=1; // Start as TRUE |
Re: encoder vs. motor
Quote:
Quote:
Quote:
-Kevin |
Re: encoder vs. motor
I also highly recommend Kevin's code.
We used it on our FRC last year and it worked PERFECTLY. We also used it with a relatively low-resolution encoder, about 64 ticks per revolution. Some advantages: - Uses interrupts, so that you don't have to worry about missing your encoder ticks. - Reads two quadrature outputs, so that you can detect which direction your encoder is spinning (increment your encoder variable when spun in one direction, decrement it in the other) Things to look out for: - The version I used had one interrupt per encoder, and interrupted only on rising edges - This meant my encoder variable would only increase or decrease after about 4 encoder state changes, dividing my effective encoder resolution by 4 - This wasn't a BAD thing, in fact it was a very good exercise in learning, and implementing two interrupts per encoder, which interrupted on rising AND falling edges, and gave me back full encoder resolution *hint: don't use two interrupts per encoder... to me external interrupts are more expensive than getting a higher resolution encoder. Last year, we had an interrupt or two to spare after we removed our IR after Pittsburgh. Next year, I know we WON'T have any spare external interrupts. I know it sounds crazy, maybe this advice comes a bit late, but buy an encoder with twice the resolution you expect to require. It gave me a great opportunity to teach students about interrupts vs. polling, and the concepts of rising edges, falling edges and such. Even the whole concept of quadrature was quite interesting to them. Most didn't think it was that easy to figure out which way an encoder was spinning. In addition, we purchased an inexpensive mechanical encoder where we opened up the back, and you could physically see how the quadrature signal was generated with just a sweeping arm, and a few contacts. I definitely learned a lot, and so did the students on 188. Thanks Kevin for your code! We used your IR code too =), and were very successful in our empty gymnasium, but weren't so successful on the actual playing field. -Shawn... |
Re: encoder vs. motor
Quote:
Quote:
Thank you for your help. |
Re: encoder vs. motor
Everybody has been focusing on the programming, but nobody has answered the other question:
Quote:
A couple of weeks ago I put together a mini-dongle, with the "disable" toggle switch built into a plastic DB-15 connector housing (the extra channel access is wired to be permanently active, and autonomous control is not available). It's mostly going to be used when someone is working on the robot and doesn't want it to bite them if a joystick gets bumped. It'll also come in handy when we want to have multiple robots running at the same time. |
Re: encoder vs. motor
Alan,
Thank you for catching that. I teach my team to pull the power plug or the tether (depending on how it is powered) to the OI to disable the robot. Also, when loading untested code, one team member is to have their hand on the 120 amp circuit breaker disconnect button until the code is verified. The reason I do not have them use the dongle is that the connection is normally enabled (a broken wire enables the robot). We use the dongle for autonomous mode testing only. |
Re: encoder vs. motor
Shawn,
Quote:
Quote:
Quote:
Quote:
-Kevin |
Re: encoder vs. motor
Quote:
Quote:
-Kevin |
Re: encoder vs. motor
Quote:
Teams will have lots of I/O and interrupt requirements. They need to understand that there is not "one size fits all" and that different timers. interrupts, et cetera, act differently (eventually, you have to read the manual). As to your previous statement, I can't get to your website at all now... Please let us know when everything is resolved. Your's is much to precious of a resource to be lost. Once again, thank you for your guidance and support... |
Re: encoder vs. motor
Quote:
http://kevin.org/frc/frc_encoder.zip and here: http://robotics.jpl.nasa.gov/~kevinw/frc_encoder.zip As I won't get a chance to test it for a few days, please let me know if you have problems with the code. -Kevin |
Re: encoder vs. motor
Where do you wire the 5v and ground to pin 1 and 2 of the encoder. Pin 3&4 to the digital input /output?
Thanks I searched but do not fine anything. |
Re: encoder vs. motor
Quote:
-Kevin |
Re: encoder vs. motor
Quote:
EC202A050A2(S or T)D Sorry about that |
Re: encoder vs. motor
Quote:
Gnd goes to the outside PWM pin, where it's marked "Blk" The A and B outputs go to the inside pins. I don't remember which I/Os are used for the signals, but it will be documented in the readme.txt file and at the top of the encoder.c source file. -Kevin |
Re: encoder vs. motor
Quote:
|
Re: encoder vs. motor
Quote:
-Kevin |
Re: encoder vs. motor
in ifi_aliases.h, there is a reference to adc.h (#include <adc.h>). I looked in the directory with all the c and h, etc. files, and didn't find a file called adc.h. this is a problem, because the code won't compile with mplab untill I find out why it can't find that particular file. can I remove it from the ifi-aliases.h file?
this is the exact error message: "E:\Robotics\defaultcode\FrcCode\ifi_aliases.h :18: unable to locate 'adc.h'" |
Re: encoder vs. motor
This seems to occur frequently. Unless you didn't install MCC18 (which is a requirement), it should be there.
I believe adc.h is the first 'standard' include; so a misconfig is the most likely cause. Check to make sure MPLAB has the right include dir (by default it is C:\mcc18\h ). |
Re: encoder vs. motor
Quote:
or you can search for "adc.h" to get more hits. |
Re: encoder vs. motor
hi,
I've been going through a tutorial for using interrupts ("interrupts for dummies") and another one titled ("quadrature encoders"). this may be a vague question, I'm not sure. but what is "Port_B"? and what is "0xFF". also, what are state machines (based on the current encoder position). are they used to determine what part of the "cycle" the encoder is going through. lastly, just a thought, is does Port_B tell which of the 4 interrupts (4-7 was fired?), because these particular four are all identified under the "same name." it seems that Port_B is used to reference interrupts 4-7, and then the 0xFF, where "FF" identifies which of those four ports was interrupted? anything you can tell me to simplify this would be appreciated, thanks, Stephen P. |
Re: encoder vs. motor
also, if you could explain this segment of code.
Code:
#pragma code InterruptVectorLow = LOW_INT_VECTOR // put this code at address 0x182: what is the purpose of putting the "#" symbol in front of it 3: what are _asm and _endasm thank you so much for the help, Stephen. |
Re: encoder vs. motor
Stephen,
Quote:
Quote:
"Port_B" is a working copy of the input port where the state of the interrupt bits can be read. You need to take a snapshot because their value may change at any time. If, for example, interrupt 6 changes from a zero to a one and then quickly changes back to a zero before you get around to checking it's state, you're stuck servicing an interrupt without knowing which of the four inputs caused it. This is why I grab a copy of PORTB first off. "Old_Port_B" is the state of the port the last time an interrupt was generated. Because four inputs are mapped to one interrupt, you need this information to determine which of the four inputs changed and caused the interrupt. "Port_B_Delta" is the exclusive-or of the above two variables. The exclusive-or of two bits returns a one if the two bits are different, zero if they're the same. Later on, I check all four bits to see if they're a one, meaning that they've changed since the last interrupt was generated. You need to check each bit because one may have changed between the time another bit caused the current interrupt and the time you sampled PORTB. If you didn't do this, you might miss a valid interrupt-causing event, which is a really bad thing to happen. Quote:
Quote:
Quote:
-Kevin |
Re: encoder vs. motor
Stephen,
Quote:
Quote:
Quote:
-Kevin |
Re: encoder vs. motor
I was reading about extern and static variables. I realize that it's considered bad coding technique to declare extern variables, because they are declared outside functions. however, I need this variable available to interrupts.c and user_routines_fast.c. however, I only want this variable to have its value assigned once. where should I place a variable that can be used in both these files, and have the variables value (unsigned int phase = 1000) assigned only once. I did search on google, but it doesn't exactly tell me about how the structure of the default code is set up to work with and where to put such a variable so it will be available to these particular files.
by the way, the purpose of the variable, is so when interrupt #1 fires, 1 is added to its value, and when interrupt #2 fires, 1 is subtracted from its value. the reason it needs to be available to user_routines_fast.c, is because that is where I want to place my functions, as it would be confusing to have the interrupts.c file running a function controlling the robot and a function in user_routines_fast.c controlling the robot as well. thanks a lot, Stephen. |
Re: encoder vs. motor
Quote:
The variable should be declared in one file and extern'd in all the others you need it in. |
Re: encoder vs. motor
where does mplab ide 7.00 send the mcc18.exe compiler file? I did the default settings for the entire installation. where is this at? keep in mind that I don't have a mcc18 folder in the root of the drive. the mplab files were installed into the program files folder. thanks, Stephen.
|
Re: encoder vs. motor
Quote:
Quote:
|
Re: encoder vs. motor
I've been using Kevin Watson's interrupt template code. I want to have a variable increment every time the interrupt fires. that's not a problem. however, is there a static variable type available that I can use between files? I'm not aware of such a thing. also, does the code in interrupts.c execute first, or the code in user_routines_fast.c go first? this affects whether I use the interrupts.c file to handle the motor speed or the user_routines_fast.c file to handle the speed of the motor. if the user routines file comes second, that would be the case where I need the variable. I'm willing to bet there's an easier way, but this is what I've come up with so far. I would use Kevin's template for encoders but it supports two encoders for the wheels, when I want to use the one we already have set up on digitals 1 and 2 with one motor. we'll probably have to use his eventually on the wheels in addition to this encoder.
thanks, Stephen. |
Re: encoder vs. motor
Quote:
extern unsigned char MyVar; In a source file that includes the header, define the actual variable: unsigned char MyVar; Any source files that use the header now have access to MyVar. I would declare all of your shared variables in one header file and define them all in one source file. To use them you just include the header in the source files where needed. Something like "sharedvars.h" and "sharedvars.c". |
Re: encoder vs. motor
Quote:
Code:
/*** Variables.h ***/ |
Re: encoder vs. motor
Quote:
Code:
/*** Variables.h ***/ |
Re: encoder vs. motor
thanks guys!!! that clears that up.
do you know about the order the files are executed though? I need to know, because if I use interrupts in one file to control the speed of a motor, it needs to be read before the user_routines_fast.c file so that the variable's values (the extern one I was asking for help earlier) can be sent to that file. do you see what I mean? also, can I use the volatile unsigned int my_int; then assign its value to a static variable inside a method in another file? (back to the question obout the file execution order) it would be really cool to be able to tell the controller to rescan the file (or whatever part of the .hex file it is) of course, it's better just to know which ones are done first and which are done last. by the way, I feel dumb for asking this, but what's the difference between frc_rc and edu_rc. |
Re: encoder vs. motor
Quote:
2. Your non-interrupt code executes from main () in main.c and follows whatever tortuous path you lead it on. 3. frc_rc is the full size controller that goes on our robots. edu_rc is the smaller controller for the Edubot. |
Re: encoder vs. motor
as I was looking at Kevin's encoder template, I was wandering how these particular variables are available to all files, as they aren't declared with the "extern" keyword.
examples: long Get_Left_Encoder_Count(void); // call this to get the current left // wheel's encoder count long Get_Right_Encoder_Count(void); // call this to get the current right // wheel's encoder count void Set_Left_Encoder_Count(long); // call this to set the left wheel's // encoder count void Set_Right_Encoder_Count(long); // call this to set the right wheel's // encoder count void Left_Encoder_Int_Handler(void); // left wheel encoder interrupt handler void Right_Encoder_Int_Handler(void); // right wheel encoder interrupt handler do you see what I mean? this is pretty much the only thing keeping me from coding our encoder is understanding why this is. thanks. also, does anyone know an easy way to set up a third encoder easily with his code (attatched to dig_in_01 and dig_in_02 (plus setting them up as interrupts))? I'm semi-new, so I'm proned to mistakes. thanks again, Stephen |
Re: encoder vs. motor
Quote:
All of your examples are of functions not variables... |
Re: encoder vs. motor
yeah, I soon realized that after posting. thanks for the tip though.
|
Re: encoder vs. motor
beware, long question...
ok, I have a couple questions. 1: in Kevin's encoder template, he first uses the Get_Left_Encoder_Count function, and assigns its value to the "count" variable. then he uses the Get_Right_Encoder_Count function and assigns its return value to the "count" variable also. Then he runs the Set_Left_Encoder_Count function, and uses the "count" variable to assign the value of "count" to Left_Encoder_Count. then he uses the "count" variable to assign the value of "count" to Right_Encoder_Count. I don't understand how he can do this without confusing the value of "count" between the left and right encoders. any help would be appreciated. 2:when setting up digitals as low priority interrupts, what do I use to reference the different pins (1-6, or interrupts 2-7). I know the first one is INTCON3bits.INT2IP = 0. but I need confirmation that that one is correct, and what the other five are. I know that interrupts 3-6 (4-7) are ganged together. I would prefer to know how to address each one individually if that can be done easily, if not, I can set them all as low priority interrupts. I think it'd be better to do the other way though, because I need to learn how to address each one individually. 3: similarly to question two, I need to know the names of the pins to set the "edge select" option. also, the names to clear the interrupt flag and to enable the interrupts. I found some of the info in the "interrupts for dummies tutorial," but I don't know how to address each one specifically. I can't be in the dark or guessing on any of this, because interrupts are very finicky. thank you, Stephen |
Re: encoder vs. motor
Stephen,
Find a good primer on C and read it. I highly recommend http://www.lysator.liu.se/c/bwk-tutor.html Understand that I am not trying to be cruel... I just feel that you have not attempted to work things out for yourself. If Mr. Watson gave you all of the answers, what would you learn? As it is, I feel he has given you too much. I think back to my freshman days at college. A fellow student (I'll call him John) was hopelessly lost and in over his head. Another student gave him the program (it was a stack of punchcards for an IBM 360 mainframe). All John had to do was change the job card (the top card on the stack) and run his program... John screwed it up and, after several hours, declared that he had changed all of the variable names and the program still didn't work! John's problem was that he never read the material required by the professor and was too busy talking in class to pay attention. Now to your situation. Your earlier post indicates that you have no real understanding of C. The variable count is a local variable inside of Get_Right_Encoder_Count and has nothing at all to do with the local variable count inside of Get_Left_Encoder_Count. Both functions return a number to the statement which called them. Suppose I asked you to find out how many pennies Marsha has and then how many Bill has? You would go to Marsha and find out she has 3 pennies and report this to me. Then you would go to Bill hand find out he has 2 pennies and report it to me. The face that Marsha had 3 pennies does not influence the fact that Bill has two. I did not ask you to add then together... Just report. The function Get_Right_Encoder_Count has no idea what other functions are available. It just reports the number of clicks that the right encoder has seen. The last line of the function could have been written: return(Right_Encoder_Count); without any local variable... Does this make sense? Bottom line: Mr. Watson's code works. |
Re: encoder vs. motor
your right there. it's just frustrating right now, because I understand the code so well, save that little thing and methods. however, my main problem was not that little variable, but the interrupt names ( the whole TRISBbits. etc. thing ), mainly for accessing the 3-6 interrupts. yeah, I'm the type of guy, who, when I understand it 100%, I can work magic, untill then, I'm in a ditch.
2 days till kickoff :yikes: excitement is bubbling. |
| All times are GMT -5. The time now is 22:26. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi