PDA

View Full Version : State Machine



mminasian
07-08-2009, 01:53 AM
I am trying to setup a simple state machine which activates two pins at a time (to be used eventually in a switching circuit). For now I am hooking up pins 0 through 4 to LEDs on my PDB. I want them to scroll through, with speed determined by a delay, and direction, by a variable. Perhaps someone can point out where I'm going wrong. I currently see no output. Any help is much appreciated. Thanks!




var
Long machine_delay
byte direction

pub run_machine(current_state)
dira[0..4]~~
repeat
if current_state > 5
current_state := 1

case direction
1:
case current_state
1 : outa[0..4] := %11000
2 : outa[0..4] := %01100
3 : outa[0..4] := %00110
4 : outa[0..4] := %00011
5 : outa[0..4] := %10001
current_state++
waitcnt(machine_delay + cnt)
2:
case current_state
1 : outa[0..4] := %11000
2 : outa[0..4] := %10001
3 : outa[0..4] := %00011
4 : outa[0..4] := %00110
5 : outa[0..4] := %01100
current_state++
waitcnt(machine_delay + cnt)
pub get_direction
return direction
pub set_direction (dir)
direction := dir
pub get_delay
return machine_delay
pub set_delay(del)
machine_delay := del







PUB MainLoop
machine.set_delay(2_000_000)
machine.set_direction(1)
'cognew(machine.run_machine(1), @Stack)
machine.run_machine(1)
waitcnt(300_000_000 + cnt)
machine.set_direction(2)




(I eventually want this running on its own dedicated cog, but that's another issue i suppose)

Timmoore
07-08-2009, 02:00 AM
Looks like your indentation has problems, look around the repeat statement, the following lines are not indented and it looks like they should be.

mminasian
07-08-2009, 02:03 AM
Yep that was it! What a stupid mistake. Thanks.

MagIO2
07-08-2009, 02:04 AM
Indentation!

You have to indent the whole stuff inside the repeat, otherwise your program ends faster than you can see the LED blink.


PS: Ok ... you won ;o)

Nick Mueller
07-08-2009, 02:24 AM
Yes, the whole block after the repeat has to move one tab to the right.

BTW:
This is not a state-machine. State-machines have states and events (or transitions).
In your case, you wouldn't increment the state (state++), but send an event "forward" or "backward". The current state will then decide what the next state will be.
<http://en.wikipedia.org/wiki/Finite-state_machine>



case state
1 : case event
forward: state:= 2;
backward: state:= 6;
stop: return;
2 : case event
forward: ....



Note that you have to generate events outside of the outer case. This might be polling a switch, or a timer generating events or ... whatever

Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 02:37 AM
Nick this is somewhat true. What I am doing is a bit of a derivative on that. I am using a Moore machine. I took the easy way out by separating the two directions into two different cases. However, each set of two LEDs EG. 01100, represents a state. The machine holds in a state for a given "delay." It ALWAYS goes to the next state, unless interrupted by a "brake." (Yes brake, not break, we're talking about a go cart here). Eventually (once I get my stupid encoders to interface correctly), I will have a gas pedal, and brake pedal which given their value, will determine the direction, and speed with which they change.

"The FSM uses only entry actions, i.e., output depends only on the state."

Technically this is a Mealy machine because of the directional operator, but its more easily thought of in one direction, as a Moore.

The only way I would really update my code to make it any more like your example (and this is trivial) is in each case "state" to change the value of current_state to the next number, instead of incrementing up.

Post Edited (mminasian) : 7/7/2009 7:42:51 PM GMT

Nick Mueller
07-08-2009, 02:41 AM
> Nick this is somewhat true. What I am doing is a bit of a derivative on that.

It looks quite degenerated. http://forums.parallax.com/images/smilies/wink.gif
Seems as if you could use an array of patterns and move along it with incrementing/decrementing an index that wraps around at the ends. Would be more compact.


Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 02:49 AM
pub run_machine
dira[0..4]~~
repeat
case current_state
1 : outa[0..4] := %11000
case direction
1: current_state := 2
2: current_state := 5

2 : outa[0..4] := %01100
case direction
1: current_state := 3
2: current_state := 1
3 : outa[0..4] := %00110
case direction
1: current_state := 4
2: current_state := 2
4 : outa[0..4] := %00011
case direction
1: current_state := 5
2: current_state := 3
5 : outa[0..4] := %10001
case direction
1: current_state := 1
2: current_state := 4
waitcnt(machine_delay + cnt)




HAPPY!?! haha http://forums.parallax.com/images/smilies/tongue.gif

mminasian
07-08-2009, 02:51 AM
Oh and I'm an EE which might explain my lack of interest in code eloquence :)

Nick Mueller
07-08-2009, 04:38 AM
> HAPPY!?! haha http://forums.parallax.com/images/smilies/tongue.gif

Perfect, but it looks soooo ugly. http://forums.parallax.com/images/smilies/wink.gif (OK, my fault)
I see a shifting pattern, this SHOUTS for a different solution. Look for ROL and ROR.

byte pattern = %11001100;

if forward
pattern<-= 1;
if backward
pattern->= 1;

Hope ROL and ROR works on bytes.

Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 05:16 AM
For some reason the bits are not rotating through, they just scroll through once and end...




Byte current_state

dira[0..4]~~
current_state := %11000
repeat
outa[0..4] := current_state
if(direction == 1)
current_state ->= 1
if (direction ==2)
current_state <-= 1

Nick Mueller
07-08-2009, 05:20 AM
> they just scroll through once and end...

Then it is a SHL / SHR
If you draw each pattern below the other (I didn't), it gets most obvious what has to be done.

Patterns! Patterns! Gang of three (bad book).


Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 05:23 AM
That's what I was trying to do...

11000
01100
00110
00011
10001

This should be a rotate, using shift yields the same result

Nick Mueller
07-08-2009, 05:31 AM
> This should be a rotate, using shift yields the same result

You'll notice the minor difference after more than one pass on the round robbin. http://forums.parallax.com/images/smilies/wink.gif


Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 05:36 AM
I understand what the difference is SUPPOSED to be. I'm not seeing a bitwise rotate as I'm expecting to. Using a rotate (<-=) yields the expected result from a shift. What gives?

Nick Mueller
07-08-2009, 05:51 AM
I think the motor will have to make more than one revolution. With shifting, the pattern is lost, with rotating, it will be fed back.
Like a 74595 that has the SerIN connectet to the SerOUT or not (register preloaded, of course).
Connected: ROL/ROR
Disconnected: SHL/SHR


Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

mminasian
07-08-2009, 06:04 AM
Totally agree. For some reason, rotating is losing the patten.

mpark
07-08-2009, 07:01 AM
Apparently the rotate works on a 32-bit intermediate result. Storing the result in a byte variable loses the high bits.