![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
AshrafAbuBaker
Joined: 07 Jan 2015 Posts: 4
|
Finite State Machine , pointer to functn , transition table |
Posted: Wed Jan 07, 2015 6:55 am |
|
|
Hi every One,
i had working on this for two days and i didn't know what is wrong with my code.
i am trying to implement a finite state machine to control a relay.
i did this with transition table and transition function.
the code can't execute the function .
any help, please
Code: |
#define MAX_LEGAL_TRANSITIONS 4 // FSM maximum transitons
typedef void (*doact) ();
void Close_Relay();
void Open_Relay();
void Do_Nothing ();
enum State {sNormal,sVoltageERROR};
enum Event {eNormal,eVoltageERROR};
typedef struct
{
State init ;
Event even ;
doact *doAction ;
State final ;
// MY_FN doAction ;
} TABLECONTROL;
/* Control table used with the table driven implementation.
reflects the full FSM.
*/
State CurrentState = sNormal ;
TABLECONTROL ControlTable [MAX_LEGAL_TRANSITIONS] =
{
{ sNormal, eNormal , &Do_nothing , sNormal } ,
{ sNormal, eVoltageERROR , &open_relay , sVoltageERROR},
{ sVoltageERROR, eVoltageERROR , &Do_nothing , sVoltageERROR},
{ sVoltageERROR,eNormal,&close_relay,sNormal}
} ;
//TABLECONTROL open_state ={sNormal,eVoltageERROR,open_relay,sVoltageERROR};
void StateTransition(Event eve)
{
int i=0;
int found=FALSE;
while ( (i <MAX_LEGAL_TRANSITIONS) && (Found == false))
{
if ( ( CurrentState == ControlTable[i].init) && (eve == ControlTable[i].even) )
{
/* Perform the action */
(*ControlTable[i].doAction) () ;
CurrentState = ControlTable[i].final ;
Found = true ;
}
// printf(lcd_putc,"\fC:%d S:%d E:%d\ni:%d",currentstate,controltable[i].init,ControlTable[i].event,i);
//delay_ms(500);
++i ;
}
}
.
.
void Open_Relay()
{
output_low(pin_b5);
delay_ms(20);
output_high(pin_b5);
delay_ms(20);
printf(lcd_putc,"\fOpening Relay");
delay_ms(1000);
}
void Close_Relay()
{
output_low(pin_b6);
delay_ms(20);
output_high(pin_b6);
delay_ms(20);
printf(lcd_putc,"\fCloseing Relay");
delay_ms(1000);
}
void Do_Nothing ()
{
}
.
.
void main
{
Event OccurEvent=eNormal;//Default event at the beginning
while(true)
{
.
.
.
if((Vrmsp<=120)||(Vrmsp>=270)) //voltage protection
OccurEvent=eVoltageERROR;
else if ((Vrmsp>140)&&(Vrmsp<260))
OccurEvent=eNormal;
StateTransition(OccurEvent);
}
}
|
_________________ I am an electronics Engineer, interesting in designing electronics systems related to renewable energy and energy saving. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 07, 2015 12:11 pm |
|
|
I made some changes to your code to get function pointers working.
It now works. The program gives the following output in MPLAB Simulator:
(Tested with MPLAB vs. 8.92 and CCS vs. 5.035)
Code: |
Start
Do Nothing
Opening Relay
Do Nothing
Closing Relay
Do Nothing
Opening Relay
Do Nothing
Closing Relay
Do Nothing
Opening Relay
Do Nothing
Closing Relay |
See the changes marked in bold below:
Quote: |
#include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define MAX_LEGAL_TRANSITIONS 4
typedef void (*doact) ();
void Close_Relay();
void Open_Relay();
void Do_Nothing();
enum State {sNormal,sVoltageERROR};
enum Event {eNormal,eVoltageERROR};
typedef struct
{
State init;
Event even;
doact doAction; // *** Removed asterisk '*' in front of doAction.
State final;
}TABLECONTROL;
State CurrentState = sNormal;
// *** Removed ampersand '&' in front of function name:
TABLECONTROL ControlTable [MAX_LEGAL_TRANSITIONS] =
{
{ sNormal, eNormal, Do_nothing, sNormal},
{ sNormal, eVoltageERROR, open_relay, sVoltageERROR},
{ sVoltageERROR, eVoltageERROR, Do_nothing, sVoltageERROR},
{ sVoltageERROR, eNormal, close_relay,sNormal}
};
void StateTransition(Event eve)
{
int i=0;
int found=FALSE;
// *** FOR TESTING - Call the function in each ControlTable entry:
i=0;
(*ControlTable[i].doAction)(); // *** FOR TESTING ***
i=1;
(*ControlTable[i].doAction)(); // *** FOR TESTING ***
i=2;
(*ControlTable[i].doAction)(); // *** FOR TESTING ***
i=3;
(*ControlTable[i].doAction)(); // *** FOR TESTING ***
/*
while((i < MAX_LEGAL_TRANSITIONS) && (Found == false))
{
if((CurrentState == ControlTable[i].init) && (eve == ControlTable[i].even))
{
(*ControlTable[i].doAction)();
CurrentState = ControlTable[i].final;
Found = true;
}
++i;
}
*/
}
void Open_Relay()
{
printf("Opening Relay \r");
}
void Close_Relay()
{
printf("Closing Relay \r");
}
void Do_Nothing()
{
printf("Do Nothing \r");
}
//===================================
void main()
{
int16 Vrmsp = 0;
printf("Start \r");
Event OccurEvent = eNormal; //Default event at the beginning
while(TRUE)
{
if((Vrmsp<=120)||(Vrmsp>=270)) //voltage protection
OccurEvent=eVoltageERROR;
else if ((Vrmsp>140)&&(Vrmsp<260))
OccurEvent=eNormal;
StateTransition(OccurEvent);
printf("\r");
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
AshrafAbuBaker
Joined: 07 Jan 2015 Posts: 4
|
|
Posted: Thu Jan 08, 2015 3:34 am |
|
|
thanks alot you are the best.
your code have worked very well
but when i test mine with state_transition function
Code: |
void state_transition (EVENT event)
{
int i=0;
int found=false;
while((i < MAX_LEGAL_TRANSITIONS) && (Found == false))
{
if((CurrentState == ControlTable[i].init) && (event == ControlTable[i].even))
{
(*ControlTable[i].doAction)();
CurrentState = ControlTable[i].final;
Found = true;
}
++i;
}
}
|
if doesn't work when the condition is true to change the event and make different action.
Do_nothing () is executed, but open_relay(), close_relay() aren't executed.
I am sure there is something silly and a common mistake I have did in this code, but I can't find it. _________________ I am an electronics Engineer, interesting in designing electronics systems related to renewable energy and energy saving. |
|
![](templates/subSilver/images/spacer.gif) |
AshrafAbuBaker
Joined: 07 Jan 2015 Posts: 4
|
|
Posted: Thu Jan 08, 2015 5:09 am |
|
|
it can not enter if statement enless in the first row in state transition table, when it has to execute Do_nothing _________________ I am an electronics Engineer, interesting in designing electronics systems related to renewable energy and energy saving. |
|
![](templates/subSilver/images/spacer.gif) |
AshrafAbuBaker
Joined: 07 Jan 2015 Posts: 4
|
|
Posted: Thu Jan 08, 2015 5:17 am |
|
|
ok, Now it works
But do you know what was wrong with it ??
I only did this modification on the if statement
Code: |
if ( ( ControlTable[i].init == CurrentState ) && ( ControlTable[i].even==event))
|
instead of
Code: |
if ( ( CurrentState == ControlTable[i].init) && (eve == ControlTable[i].even) )
|
So what is the difference between two statements?
It took me 3 days to figure it out ![Embarassed](images/smiles/icon_redface.gif) _________________ I am an electronics Engineer, interesting in designing electronics systems related to renewable energy and energy saving. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|