|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
||||
|
||||
|
More automonous help:ending stuff
OK! I got a line sensor code (verrrrrry basic) and I would like to now a few things:
1. I know the robot will arrive at the T in under 15 secs, so how do I stop it and do something different? 2. If I stop it, we would like to raise our arm (on winch), which is on a PWM. 3. How would I stop the arm? Same way as # 1? Code:
if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 127;
pwm15 = 127;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 1)
{
pwm13 = 139;
pwm15 = 175;
}
else if (rc_dig_in01 == 1 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 175;
pwm15 = 139;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 1 && rc_dig_in03 == 0)
{
pwm13 = 249;
pwm15 = 249;
}
|
|
#2
|
||||
|
||||
|
Re: More automonous help:ending stuff
Ok...well it's difficult to tell you exactly what to do without knowing your robot, but I'll try. There isn't a timing component in your code, it looks like, it just follows the line as far as it can, turning motors to different values when certain sensors see the line. Without some form of timing you won't be able to tell it to stop when you want, or time when the arm raises up/stops.
The simplest form of timer you can have is a program cycle counter, which will operate *around* 40hz, or about 25ms per count (its actually more like 28.something). So, add in a variable "count" (int count = 0; in your initialization) somewhere, and at the end of the loop say "count++;". Then, check when the count is higher than a certain number (the time you want to stop, or raise the arm, or stop raising the arm), and set the pwm values to something different that you want. Make sure to set those values lower in the loop than the sensor code, or they will get overridden. You'll probably just have to time it yourself, or count the number of times a certain sensor sees the line (as in did it just turn?), and then raise the arm. There are better ways of controlling the robot based on time and other factors, but its probably more complicated than you really have time for right now. Hope I helped. |
|
#3
|
||||
|
||||
|
Re: More automonous help:ending stuff
Thanks, but can you be more specific. Put timer where in ins? Could you give and example, I can change the code but I can't write it...++ means add twice to me
|
|
#4
|
||||
|
||||
|
Re: More automonous help:ending stuff
In your User_Initialization create a variable called count (you can create it anywhere but that's probably the best spot for now), with this syntax:
int count = 0; Then at the bottom of the while(autonomous_mode) loop in your code, right above Putdata(&txdata), put in count++; ++ in C means the same thing as "count = count + 1;", so you are incrementing it by one every time you pass through that loop. Multiply count by 40 and you have *approximately* the amount of time autonomous has been running. You'll have to time it and do the math yourself, but when you want it to break off, say something like (below your line following code): if(count > 200){ pwm01 = 254; pwm02 = 254; } else if(count > 300){ pwm01 = 0; pwm02 = 0; } else if (count > 320){ pwm01 = 127; pwm02 = 127; } That won't do much, just go forward and stop after a little over 2 seconds, but hopefully you get the picture on what you can do. Adjust values to your desire, and good luck. |
|
#5
|
|||||
|
|||||
|
Re: More automonous help:ending stuff
I think you'll need to declare that int as 'static' -- otherwise it won't be remembered from one cycle to the next:
Code:
static int count = 0; Code:
// this is global:
static int count = 0;
User_Initialization()
{
static int anotherCount = 0; // this is local to this function,
// and cannot be seen outside of
// this fuction.
count++; // okay
anotherCount++; // okay
}
anotherFunctionInTheSameFile()
{
count++; // okay -- it's global
anotherCount++; // won't compile
}
|
|
#6
|
||||
|
||||
|
Re: More automonous help:ending stuff
Quote:
|
|
#7
|
|||||
|
|||||
|
Re: More automonous help:ending stuff
Quote:
Makes me want to cross-post this in the "Why I hate C" thread. ![]() |
|
#8
|
|||
|
|||
|
Re: More automonous help:ending stuff
There was already a message here which showed how to do some simple state-based autonomous code. THIS IS THE RIGHT WAY TO DO THINGS.
Your autonomous code effectively moves through a series of states. You stay in a state until ready to transition out of this state. Each state have have specific outputs (like a "Moore machine") or have outputs which directly depend on inputs (like a "Mealey/Mealy machine"). There is no reason to have to make your outputs entirely Mealy. Add a state variable -- it really does help. A simple example can also be found in one of our team's (1014) code: http://www.osufirst.org/twiki/bin/vi...04RegionalCode If you look in the user_routines_fast.c in the autonomous section, you'll see the whole thing is based on state. Because we have position feedback, we transit out of states once we reach a particular position. However, this could just as easily be time. In general, it's nice to setup an interrupted-based timer that keeps a moderately real-time clock running on your machine and to use that as feedback timing your operations and calculating important characteristics like speed. Keep your code in terms of state and you'll have a much nicer time coding, especially when adding states, maintaining states, and doing simple things like stopping. Sorry that the 1014 autonomous code has little commenting -- one of the nice things about the states (and the speed controllers) is that we could write our autonomous code on the fly at competition and it was easy to debug there. We never intended to have autonomous code... we just felt it was good to add it in since so few robots at our regional had any. |
|
#9
|
||||
|
||||
|
Re: More automonous help:ending stuff
Just looked at my code way up there and realized that i had >'s instead of <'s...sorry for the confusion.
|
|
#10
|
||||
|
||||
|
Re: More automonous help:ending stuff
HI,
I don't have time to write something lengthly, so I will write one thing: - I placed count++ whatever in user_routines. Is this the right spot? Canadian regoinal starts THURS but we leave TOMORROW, but our hotel has internet so post the answer please |
|
#11
|
|||||
|
|||||
|
Re: More automonous help:ending stuff
Try this. In user_routines_fast.c replace the User_Autonomous_Code function with the function below. It's not a state machine, but it incorporates elements that you probably understand better.
All: Please check this for bugs! Code:
void User_Autonomous_Code( void )
{
static unsigned int Old_Clock = 0;
static unsigned int time = 0; // cycle counter
while (autonomous_mode)
{
if (statusflag.NEW_SPI_DATA)
{
Getdata(&rxdata); // bad things will happen if you move or delete this
// Autonomous code goes here.
if (Clock > Old_Clock) // stay synchronized to beacon data updates (this is important)
{
/////////////////////// CUSTOM CODE /////////////////////////
if ( time < 456 ) // still less than 12 seconds have elapsed
{
// LINE FOLLOWING
// there are 3 bits which means 8 combinations.
// only 4 are tested here. ??
if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 127; // stop
pwm15 = 127;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 1)
{
pwm13 = 139; // turn one way
pwm15 = 175;
}
else if (rc_dig_in01 == 1 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 175; // turn the other way
pwm15 = 139;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 1 && rc_dig_in03 == 0)
{
pwm13 = 249; // go straight and fast
pwm15 = 249;
}
}
else if ( time < 532 ) // 12 seconds have gone by, but less than 14
{
// stop wheels
pwm13 = 127;
pwm15 = 127;
// raise arm
pwm03 = 175;
}
else // more than 14 seconds have gone by
{
// stop raising arm
pwm03 = 127;
}
time++; // count another cycle
/////////////////////// END OF CUSTOM CODE /////////////////////////
Old_Clock = Clock; // take a snapshot of the clock
} // clock > oldclock
Generate_Pwms( pwm13, pwm14, pwm15, pwm16 );
Putdata(&txdata); // even more bad things will happen if you mess with this
} // statusflag.NEW_SPI_DATA
} // while (auotnomous)
}
|
|
#12
|
||||
|
||||
|
Re: More automonous help:ending stuff
OK, here's my take on what's been said, with some minor refinements and details. I took the original code, re-arranged a bit to put it into a state machine (and fix the problem where sensor readings could lock out the code that does the end game), then plopped it all into the User_Autonomous_Code function from the default FIRST code in user_routines_fast.c.
I also added in the loop counter in the right spot and used the constants to give the transitions at 12 and 14 seconds. Since autonomous mode just spins in the one function, there's no reason to mess with global (or static) variables. Code:
enum
{
stateFollowLine,
stateRaiseArm,
stateDone
};
void User_Autonomous_Code(void)
{
int count; /* number of times through the "slow" loop */
int state; /* current state */
/* Initialize all PWMs and Relays when entering Autonomous mode, or else it
will be stuck with the last values mapped from the joysticks. Remember,
even when Disabled it is reading inputs from the Operator Interface.
*/
pwm01 = pwm02 = pwm03 = pwm04 = pwm05 = pwm06 = pwm07 = pwm08 = 127;
pwm09 = pwm10 = pwm11 = pwm12 = pwm13 = pwm14 = pwm15 = pwm16 = 127;
relay1_fwd = relay1_rev = relay2_fwd = relay2_rev = 0;
relay3_fwd = relay3_rev = relay4_fwd = relay4_rev = 0;
relay5_fwd = relay5_rev = relay6_fwd = relay6_rev = 0;
relay7_fwd = relay7_rev = relay8_fwd = relay8_rev = 0;
count = 0;
state = stateFollowLine;
while (autonomous_mode) /* DO NOT CHANGE! */
{
if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */
{
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */
/* Add your own autonomous code here. */
switch (state)
{
case stateFollowLine:
/* we're trying to follow the line */
if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 127;
pwm15 = 127;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 0 && rc_dig_in03 == 1)
{
pwm13 = 139;
pwm15 = 175;
}
else if (rc_dig_in01 == 1 && rc_dig_in02 == 0 && rc_dig_in03 == 0)
{
pwm13 = 175;
pwm15 = 139;
}
else if (rc_dig_in01 == 0 && rc_dig_in02 == 1 && rc_dig_in03 == 0)
{
pwm13 = 249;
pwm15 = 249;
}
/* time to advance the next state? */
if (count > 457)
state = stateRaiseArm;
break;
case stateRaiseArm:
/* now stop the robit, raise the arm */
pwm13 = 127;
pwm15 = 127;
pwm3 = 175;
/* time to advance the next state? */
if (count > 534)
state = stateDone;
break;
case stateDone:
/* all stop */
pwm13 = 127;
pwm15 = 127;
pwm3 = 127;
break;
}
Generate_Pwms(pwm13,pwm14,pwm15,pwm16);
Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
++count; // increment once every 26.3 milliseconds
}
}
}
To do that, just add a few more states to turn left and right a couple of times. Enjoy. |
|
#13
|
||||
|
||||
|
Hey Hey Hey!
I have to hand it to ya, the code did good, but it was our robot who screwed up... I got a big tip that the line sensors power supply does NOT come from the PWM... it comes directly from the breaker. So the sensers don't have the juice to pick up anything... so useless. I found that out just before we left. Another thing is the arm which is now removed... is useless to the winch... so no code for that useless device. off topic but I noticed a lot of teams going for the 'fishingrod' style. I think our robot should have done that, less weight overall. So we play defence and offense. So our now automonous code is drive like hell with our power window motors (I hate them) and plow the goal to the other end...look for my reason on this in strategy. MY team and I reall yappreciate all the work you guys did. I wish I could have seen it in action, but if we switch back at least we can say were 'multi automonistic' Barry PS: I'm in the hilton business/comp. room. I've met one the official/judges (he didn't tell me) and the DIRECTOR of the whole deal. His wive is photocopying using all the complimentary stuff they have |
|
#14
|
|||||
|
|||||
|
Re: More automonous help:ending stuff
Barry,
Let me reply to your first question. I created an auto mode with a "sequence of events" that were timed. I created two files, 'myAuto.c' and 'myAuto.h' (not really -- I'm simplifying). (BTW, the code examples below haven't been compiled and they probably have at least typo bugs.) In the .h file I made a list of named states using the C 'enum' construct: Code:
// myAuto.h
#ifndef MYAUTO_H // don't include it more than once!
#define MYAUTO_H
enum // auton state machine states
{
FIRST_CYCLE,
RUN_TO_TEE,
RAISE_ARM,
STOP
}
Also in myAuto.h I #define some constants. Code:
// machine cycles at about 38 Hz.
// exact rate is 10 MHz / 2^18
#define RUN_TO_TEE_TIME 380 // about 10 seconds ( 38 cycles / sec)
#define RAISE_ARM_RUN_MOTOR_TIME 80 // ~2+ secs
void
runAndRaise( void ); // advertise the function we will create in myAUto.c
// important for calling this function from another file
// that file will need "#include myAuto.h" so it
// knows the form of "runAndRase"
#endif // MYAUTO_H
Okay, myAuto.c has a static int counter that counts each timed phase. Something like this: Code:
// myAuto.c
//
#include "myAuto.h" // pick up the enum and #defines
void
runAndRaise( void ) // call this function from
// the file user_routines_fast.c
// inside User_Autonomous_Code() ,
// inside the "if (Clock > Old_Clock)" conditional
// don't forget to put #include "myAuto.h" at the top of
// user_routines_fast.c
{
static int timer = 0; // times each phase (state) of auton.
static unsigned char state = FIRST_CYCLE; // init to first state.
switch( state ) // executes once every .0262144 seconds
{
case FIRST_CYCLE: // let's initialize some things
timer = 0;
state = RUN_TO_TEE; // next time around, jump to this state
break; // that's all for this cycle.
case RUN_TO_TEE:
timer++;
runMotorsAndStuff(); // your code goes here
if ( timer > RUN_TO_TEE_TIME )
{
timer = 0; // reset timer for use in next state
stopMotors(); // your code goes here
runArmWinch(); // your code goes here
state = RAISE_ARM; // next time around jump to this state
}
break;
case RAISE_ARM:
timer++;
if( timer > RAISE_ARM_RUN_MOTOR_TIME )
{
timer = 0; // for consistency: not actually needed by next state.
stopArmWinch(); // your code goes here
state = STOP; // next state is stop
}
break;
case STOP:
// nothing: just sit there until end of auto.
break;
} // switch( state )
}
Hope that helps! -Norm Last edited by gnormhurst : 28-03-2004 at 19:00. |
|
#15
|
||||
|
||||
|
Re: More automonous help:ending stuff
Wow, I get a head ache reading all that... but I think I get it.
1. Put that static count in 2. Add the PWM for the winch on the timer 3. Calculate the figures One more thing. If say at 2000 I tell PWM 13 & 15 to shut off and the at 2000 tell PWM 3 (winch) to raise till (lets say) 2750 will the timer interfere with any of the line sensors? Does the position of the timer code affect it? Last edited by Robohawk-master : 29-03-2004 at 09:43. |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Please - stop posting needless stuff! | Andy Baker | Announcements | 0 | 13-01-2004 09:13 |
| Free stuff at FIRST | Not2B | General Forum | 7 | 30-09-2003 21:23 |
| What does everyone like to do besides FIRST stuff?? | Katie_269 | Chit-Chat | 45 | 17-07-2002 17:01 |
| who can we buy stuff from?!?! | archiver | 2001 | 7 | 23-06-2002 23:04 |
| How much robotics stuff is on your resumes??? | Robby O | Career | 14 | 03-08-2001 19:51 |