Spoken like a programmer, instead of a hardware designer. Why, and how is a SWITCH-CASE any different or any more readable than an IF-THEN construct?...(though I shudder at Mike's solution); for readability and future ease-of-maintenance, having the state machine set up as a switch-case works best,
Since all the State Variables, Inputs and Outputs are global to ALL states, why bother with Functions?..but put the functionality for each state into separate functions (unless the code for each is small - say less than 10 lines). Finally - use plenty of comments, as always...
Spoken like a programmer, instead of a hardware designer. Why, and how is a SWITCH-CASE any different or any more readable than an IF-THEN construct?
Since all the State Variables, Inputs and Outputs are global to ALL states, why bother with Functions?
My code is written so that it mimics the State Transition Diagram, which I always draw first before starting to code. I use '***********' to enclose the States, so it is easy to go from code to diagram and vice versa...
if( A <= B) then
do something;
else if (A>=B) then
do something else;
else if (A=B) then
do something else still
end if;
BOTH will produce loads of GOTO lines in order to function - particularly on a PIC
Please post an example coded in C which implements this State Transition Diagram that I posted in this thread.
void main() {
int state = 0; // wait for button
int floor = 1; // start on first floor
int button = 0; // no button pressed
loop {
switch (state) {
case 1: // get direction
direction = getDirection(button, floor);
state = 2;
break;
case 2: // move in direction
motorOn(direction);
state = 3;
break;
case 3: // check limit
if (atLimit(button)) {
state = 0;
floor = button;
}
break;
default:
button = getButton(); // returns 0, 1, 2, or 3 for whichever button is pressed
state = (button > 0) ? 1 : 0;
}
}
}
int getDirection(int floor_wanted, int floor_on) {
int direction = 0;
if (floor_on > floor_wanted) {
direction = 1; // down
}
else if (floor_on < floor_wanted) {
direction = 2; // up
}
return (direction);
}
void motorOn(int direction) {
switch (direction) {
case 1:
// motor on "down"
break;
case 2:
// motor on "up"
break;
default:
// motor off/stop
}
}
int atLimit(int limit) {
int currLimit = getLimit(); // returns 0, 1, 2, or 3 for whichever limit switch is tripped
return ((currLimit == limit) ? 1 : 0);
}
void main() {
int state = 0; // wait for button
int floor = getLimit(); // returns 0, 1, 2, or 3 for whichever limit switch is currently tripped (0 if between floors)
int button = 0; // no button pressed
int direction = 0; // motor off
loop {
switch (state) {
case 1: // get direction
direction = getDirection(button, floor);
state = 2;
break;
case 2: // move in direction
motorOn(direction);
state = 3;
break;
case 3: // check limit
if (atLimit(button)) {
state = 0;
floor = button;
}
break;
default:
motorOn(direction);
button = getButton(); // returns 0, 1, 2, or 3 for whichever button is pressed
state = (button > 0) ? 1 : 0;
}
}
}
int getDirection(int floor_wanted, int floor_on) {
int direction = 0;
if (floor_on > 0) {
if (floor_on > floor_wanted) {
direction = 1; // down
}
else if (floor_on < floor_wanted) {
direction = 2; // up
}
}
else {
direction = 1; // down
}
return (direction);
}
void motorOn(int direction) {
switch (direction) {
case 1:
// motor on "down"
break;
case 2:
// motor on "up"
break;
default:
// motor off/stop
}
}
int atLimit(int limit) {
int currLimit = getLimit(); // returns 0, 1, 2, or 3 for whichever limit switch is tripped
return ((currLimit == limit) ? 1 : 0);
}
Well, ultimately, down at the assembly/machine-code level, of course there will be GOTOs galore; the statement itself, if the HLL used supports it, should be avoided if at all possible (which is the majority of the time).
cr0sh,
How did you get from seven states to three? You didn't implement the state transition diagram I posted.
void main() {
int state = 7; // send car to first floor on start
while (1) {
switch (state) {
case 1: // FIRST
state = getFloor(1);
break;
case 2: // UP2
goUp(2);
state = 3;
break;
case 3: // SECOND
state = getFloor(2);
break;
case 4: // UP3
goUp(3);
state = 5;
break;
case 5: // THIRD
state = getFloor(3);
break;
case 6: // DN2
goDown(2);
state = 3;
break;
case 7: // DN1
goDown(1);
state = 1;
break;
default: // UNKNOWN
state = 7; // send car to first floor - invalid state
}
}
}
int getFloor(current_floor) {
while (1) {
int button = getButton(); // returns 0, 1, 2 or 3 for button selected
switch (button) {
case 1:
if (current_floor == 2 || current_floor == 3) {
return (7);
}
break;
case 2:
if (current_floor == 1) {
return (2);
}
else if (current_floor == 3) {
return (4);
}
break;
case 3:
if (current_floor == 1 || current_floor == 2) return (4);
break;
default:
}
}
}
void goUp(floor) {
while (getLimit() != floor) {
motorUp();
}
motorOff();
}
void goDown(floor) {
while (getLimit() != floor) {
motorDown();
}
motorOff();
}
int getLimit() {
return (#); // returns 0, 1, 2 or 3 for current set limit switch for each floor
}
If you think your code implements an equivalent state machine to the one I posted, then working backwards from your posted code, it should be possible to draw out a State Transition Table from the code that could be converted to a Present State - Next State Table for implementation into hardware using flip-flops and gates...
For example, the following code... is prefectly fine for this construct, but this logic cannot be coded with the switch/case statement.
switch ((a - b) / abs(a - b)) {
case -1: // a < b
break;
case 0: // a = b
break;
case 1: // a > b
break;
default: // error?
}
Actually - your code wouldn't really work either, as the A=B clause could never be hit (it would hit the A<=B clause).
If(A<=B) then
do something;
else if (A>=B) then
do something else;
else if(A==0) then
do something else still;
end if;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?