View Full Version : Running a Relay for a Set Time
davidalln
21-02-2010, 17:40
I need to run a relay for a set amount of time while still being able to run the rest of the robot's functions. When I use the tried and true Wait() function from the Watchdog, it (as expected) halts the rest of robot operations. I have looked into separating out this function in a Task/Semaphore formation, but I'm not sure if it will solve this or exactly where to start with this (I have looked through this tutorial (http://www.chiefdelphi.com/forums/showthread.php?t=82398&highlight=semaphore), but I'm still not sure where to start). What is the best way to run a function for a set amount of time while still running drive/other schmazz? :)
mandrews281
22-02-2010, 00:02
One of our programmers got it with a separate task, but what I'd suggest is starting a Timer, polling it in your loop, and as soon as the timer exceeds some length of time, turn the relay off.
This is a C++ example. Its a state machine that starts with a trigger on a joystick. It even includes the 2 second lockout before the kicker can be fired again.
enum Kicker_State {
Kicker_off,
Kicker_going_out,
Kicker_out,
Kicker_coming_back,
Kicker_reload};
Timer kicker_timer;
Kicker_State kicker_state = Kicker_off;
while (IsOperatorControl())
{
GetWatchdog().Feed();
myRobot.TankDrive(left_stick, right_stick); // drive with two sticks
Wait(0.005); // wait for a motor update time
// kicker out-in actuator
switch (kicker_state)
{
case Kicker_off:
// see if go button is pressed
if (right_stick.GetRawButton(KICKER_BUTTON))
{
kicker->Set(Relay::kForward); // turn on
kicker_timer.Reset();
kicker_timer.Start();
kicker_state = Kicker_going_out;
}
break;
case Kicker_going_out:
// see if enough time elasped
if (kicker_timer.Get() >= .25)
{
kicker->Set(Relay::kOff);
kicker_timer.Reset();
kicker_state = Kicker_out;
}
break;
case Kicker_out:
// see if enough time elasped
if (kicker_timer.Get() >= .5)
{
kicker->Set(Relay::kReverse);
kicker_timer.Reset();
kicker_state = Kicker_coming_back;
}
break;
case Kicker_coming_back:
// see if enough time elasped
if (kicker_timer.Get() >= .25)
{
kicker->Set(Relay::kOff);
kicker_timer.Reset();
kicker_state = Kicker_reload;
}
break;
case Kicker_reload:
// see if enough time elasped
if (kicker_timer.Get() >= 2.0)
{
kicker_state = Kicker_off;
kicker_timer.Stop();
}
break;
}
} // end operator control loop
slavik262
22-02-2010, 09:51
I'd recommend using the Notifier class. It automatically calls a callback function after a given amount of time, and works on an interrupt level so it doens't block other code until it runs.
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.