100% found this document useful (1 vote)
187 views7 pages

Reloadstatemachine

The document describes a state machine for reloading a ball for a robot. It includes state definitions like EMIT_IR, MEASURING_PERIOD, and WAITING_FOR_BALL. Event types like GOT_BALL and timeouts trigger state transitions. The state machine measures the IR period to reload balls and notifies a master state machine when ready to shoot or switch to defense.

Uploaded by

api-398062839
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
187 views7 pages

Reloadstatemachine

The document describes a state machine for reloading a ball for a robot. It includes state definitions like EMIT_IR, MEASURING_PERIOD, and WAITING_FOR_BALL. Event types like GOT_BALL and timeouts trigger state transitions. The state machine measures the IR period to reload balls and notifies a master state machine when ready to shoot or switch to defense.

Uploaded by

api-398062839
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

/****************************************************************************

Module
ReloadStateMachine.c

****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
// Basic includes for a program using the Events and Services Framework
#include "ES_Configure.h"
#include "ES_Framework.h"

/* include header files for this state machine as well as any machines at the
next lower level in the hierarchy that are sub-machines to this machine
*/
#include "ReloadStateMachine.h"
#include "ReloadIRCaptureModule.h"
#include "MyPWMLib.h"
#include "MasterSM.h"

/*----------------------------- Module Defines ----------------------------*/


// define constants for the states for this machine
// and any other local defines

#define ENTRY_STATE EMIT_IR


#define RELOAD_TIMEOUT_MS (2000)
#define BALL_TIMEOUT (2000)
#define NUM_PWM (6)
#define PWM_CHANNEL (10)
//TODO TAKE ABOVE OUT!

/*---------------------------- Module Functions ---------------------------*/


/* prototypes for private functions for this machine, things like during
functions, entry & exit functions.They should be functions relevant to the
behavior of this state machine
*/
static ES_Event_t DuringMeasuringState(ES_Event_t Event);
static ES_Event_t DuringWaitingState(ES_Event_t Event);
static ES_Event_t DuringEmitIR(ES_Event_t Event);
/*---------------------------- Module Variables ---------------------------*/
// everybody needs a state variable, you may need others as well
static ReloadState_t CurrentState;
static int CurrentPeriod_US;
static bool HeadedToDefense = false;

/*------------------------------ Module Code ------------------------------*/


/****************************************************************************
Function
RunTemplateSM

Parameters
ES_Event_t: the event to process

Returns
ES_Event_t: an event to return

Description
add your description here
Notes
uses nested switch/case to implement the machine.
Author
J. Edward Carryer, 2/11/05, 10:45AM
****************************************************************************/
ES_Event_t RunReloadStateMachine(ES_Event_t CurrentEvent)
{
//printf("running reload state machine \r\n");
bool MakeTransition = false;/* are we making a state transition? */
ReloadState_t NextState = CurrentState;
ES_Event_t EntryEventKind = { ES_ENTRY, 0 }; // default to normal entry to new
state
ES_Event_t ReturnEvent = CurrentEvent; // assume we are not consuming
event

switch (CurrentState)
{
//Entry state is measuring period.
case EMIT_IR:
{
//if we enter, then we need to start pulsing IR
//if we exit, then we disable pulsing
ReturnEvent = CurrentEvent = DuringEmitIR(CurrentEvent);

if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//if we got an event from the break-beam service
case GOT_BALL:
{
// we are leaving reload state machine and going to shoot state machine
//let upper state machine know we got a ball!
//TODO: make sure we increment ball count in upper state machine!
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
IncrementNumBalls();
printf("Got ball event found! \r\n");
}
break;
case ES_TIMEOUT:
{
//if the reload timer timesout, we go back to measuring IR period.
if (CurrentEvent.EventParam == RELOAD_TIMER)
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
IncrementNumBalls();
printf("Got ball event found! \r\n");
}
}
break;
//if we are entering first offense, then move to waiting for ball.
// this ensures we go shoot instead of trying to reload again (as we have
a ball)
case FIRST_OFFENSE:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true; //mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got first offense event! \r\n");
}
break;

case OFFENSE_STARTED:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true; //mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;

case DEFENSE_STARTED:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true;
HeadedToDefense = true;
//mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;
}
}
}
break;

//state is measuring period.


case MEASURING_PERIOD:
{
//if we enter, then we enable interrupts coming from receive
//if we exit, then we disable interrupts
ReturnEvent = CurrentEvent = DuringMeasuringState(CurrentEvent);
if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//if our ISR tells us we found the period
case FOUND_RELOAD_IR:
{
printf("running measuring period and got found reload ir %d \r\n",
CurrentEvent.EventParam);
//set current period
EntryEventKind.EventParam = CurrentEvent.EventParam;
// move to waiting for ball
//note that upon entering waiting for ball, we will start emitting IR
pulses at the appropriate peiod.
NextState = EMIT_IR;
MakeTransition = true;
//upper state machine shouldn't care about this.
ReturnEvent.EventType = ES_NO_EVENT;
}
break;
}
}
}
break;

case WAITING_FOR_BALL:
{
//if we are waiting for ball
// upon entering: start pulsing pwm.
ReturnEvent = CurrentEvent = DuringWaitingState(CurrentEvent);

if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//If our ball-break IR posts an event
case GOT_BALL:
{
//increment num balls
IncrementNumBalls();
// tell main state machine we got a ball.
if (HeadedToDefense)
{
ReturnEvent.EventType = DEFENSE_STARTED;
HeadedToDefense = false;
}
else
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
}
}
break;
//if our ball waiting times out, then we just go try to shoot
case ES_TIMEOUT:
{
IncrementNumBalls();
//make sure it's from the right timer.
if (CurrentEvent.EventParam == BALL_TIMER)
{
// tell main state machine we got a ball.
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
if (HeadedToDefense)
{
ReturnEvent.EventType = DEFENSE_STARTED;
HeadedToDefense = false;
}
else
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
}
}
}
case OFFENSE_STARTED:
{
HeadedToDefense = false;
}
break;
case DEFENSE_STARTED:
{
//we need to measure period again
HeadedToDefense = true;
//mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;
}
}
}
break;
}
// If we are making a state transition
if (MakeTransition == true)
{
// Execute exit function for current state
CurrentEvent.EventType = ES_EXIT;
RunReloadStateMachine(CurrentEvent);
CurrentState = NextState; //Modify state variable

// Execute entry function for new state


// this defaults to ES_ENTRY
RunReloadStateMachine(EntryEventKind);
}
return ReturnEvent;
}

/****************************************************************************
Function
StartTemplateSM

Parameters
None

Returns
None

Description
Does any required initialization for this state machine
Notes

Author
J. Edward Carryer, 2/18/99, 10:38AM
****************************************************************************/
void StartReloadStateMachine(ES_Event_t CurrentEvent)
{
if (CurrentEvent.EventType != ES_ENTRY)
{
printf("Warnign, reload state ,machine was starting with a non-entry
event\r\n");
}
printf("reloading state machine started and emitting at half of %d us\r\n",
CurrentEvent.EventParam);
// to implement entry to a history state or directly to a substate
// you can modify the initialization of the CurrentState variable
// otherwise just start in the entry state every time the state machine
// is started
if (ES_ENTRY_HISTORY != CurrentEvent.EventType)
{
CurrentState = ENTRY_STATE;
}
// call the entry function (if any) for the ENTRY_STATE
RunReloadStateMachine(CurrentEvent);
}

/****************************************************************************
Function
QueryTemplateSM

Parameters
None

Returns
TemplateState_t The current state of the Template state machine

Description
returns the current state of the Template state machine
Notes

Author
J. Edward Carryer, 2/11/05, 10:38AM
****************************************************************************/
ReloadState_t QueryReloadStateMachine(void)
{
return CurrentState;
}

/***************************************************************************
private functions
***************************************************************************/

static ES_Event_t DuringEmitIR(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// set period
CurrentPeriod_US = Event.EventParam;
//start timer for reload timeout
ES_Timer_InitTimer(RELOAD_TIMER, RELOAD_TIMEOUT_MS);

if (CurrentPeriod_US != 0)
{
My_PWM_SetFreq(2000000 / CurrentPeriod_US, 5);
My_PWM_SetDuty(50, PWM_CHANNEL);
printf("freq = %d\r\n", 2000000 / CurrentPeriod_US);
}
}
else if (Event.EventType == ES_EXIT)
{
My_PWM_SetDuty(0, PWM_CHANNEL);
ES_Timer_StopTimer(RELOAD_TIMER);
}
else
//nothing to do here.
{}
// return either Event, if you don't want to allow the lower level machine
// to remap the current event, or ReturnEvent if you do want to allow it.
return ReturnEvent;
}

static ES_Event_t DuringMeasuringState(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// implement any entry actions required for this state machine
CurrentPeriod_US = 0;
//enable interrupts
EnableReloadIR();
}
else if (Event.EventType == ES_EXIT)
{
//deacticve interrupts for reload ir
DisableReloadIR();
ES_Timer_InitTimer(RELOAD_TIMER, RELOAD_TIMEOUT_MS);
}
else
// nothing here
{}
return ReturnEvent;
}

static ES_Event_t DuringWaitingState(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// implement any entry actions required for this state machine
//Start Ball Timer
ES_Timer_InitTimer(BALL_TIMER, BALL_TIMEOUT);
}
else if (Event.EventType == ES_EXIT)
{
//when we exit, we'll simply pass event up.
ES_Timer_StopTimer(BALL_TIMER);
}
else
//we're just sitting and waiting, so don't do anything
{}

return ReturnEvent;
}

You might also like