Maker Pro
Maker Pro

Arduino control of model train signalling (was: LED Power Supply for Control Panel)

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
List of Changes that need to be addressed:

The posts in "code form" in post 172-175 should address some of these


Typo Errors


CFY_UD Panel


1. Input Signal CFY_UD_I_FTA : typo ERM_UA_O_CFY_UFA should read LFY_UA_O_CFY_UFA
2. Output Signal CFY_UD_O_ERM_FSRD: typo ERM_DA_I_UFRD should read ERM_UA_I_UFRD
3. Output Signal CFY_UD_O_ERM_STRD: typo ERM_DA_I_TWA should read ERM_UA_I_TWA

ERM_UA Panel

1. Input Control ERM_UA_I_RS Delete (ERM_UA_I_FRS instead)
2. Input Signal ERM_UA_I_UFA: typo LFY_UD_O_ERM_UFA should read LFY_UA_O_ERM_UFA

ERM_UD Panel

1. State Identifier ERM_UD_S_RSIE should be ERM_UD_S_RSIL
2. State Identifier ERM_UD_S_SDIC should be ERM_UD_S_SDIE
3. State Identifier ERM_UD_S_SAIE should be ERM_UD_S_SAIL

LFY_UA Panel

1. Output Signal LFY_UA_O_ERM_UFA: typo ERM_DA_I_UFN should read ERM_UA_I_UFN

2. State Identifier LFY_UA_S_RSIE should be LFY_UA_S_RSIL
3. State Identifier LFY_UA_S_SDIC should be LFY_UA_S_SDIE
4. State Identifier LFY_UA_S_SAIE should be LFY_UA_S_SAIL

Output Signals

As far as i can ascertain at the moment because output signals are not in sync this is giving spurious input signals
at other panels , especially hard to track in fast train movements.

What i have noticed is that the output signals are being set at present for the next state without a button press on the associated panel. This is hence why you will see 2 post for the same signal but in different states, 1 says [Unchecked] the next says [Checked]

In theory even in "Automatic" mode the program should only go as far as the next "user interface" button press. I'm uncertain at present that it does. The panel that has a button press will change to the "next state" before the other even if by on a few millis;

It may be easier to check these against the existing code


CFY_UD Panel

1. State CFY_UD_S_RSIE Output Signal CFY_UD_O_ERM_STRD presently true; [Checked]
Change to false; [Unchecked]

2. State CFY_UD_S_SDIC Output Signal CFY_UD_O_ERM_STRD presently false; [Unchecked]
Change to true; [Checked]

3. State CFY_UD_S_FDIC Output Signal CFY_UD_O_ERM_FSRD presently false; [Unchecked]
CFY_UD_O_LFY_FSRD presently false; [Unchecked]
Change Both to true; [Checked]

4. State CFY_UD_S_FRSE Output Signal CFY_UD_O_ERM_FSRD presently true; [Checked]
CFY_UD_O_LFY_FSRD presently true; [Checked]
Change Both to false; [Unchecked]

ERM_UA Pane
l

1. State ERM_UA_S_SAIE Output Signal ERM_UA_O_CFY_SUTA presently false; [Unchecked]
Change to true; [Checked]

2. State Transition ERM_UA_S_FRSE --> ERM_UA_S_FAIL Input Signal ERM_UA_I_UFN not received?

1. Panels CFY_UD, ERM_UA, LFY_UA in State S_FRSE
2. Input Control LFY_UA_I_UFA pressed and "Step" on this panel pressed
3. LFY_UA Panel goes to State S_FAIL
4. LFY_UA Output Signals LFY_UA_CFY_UFA set true; [Checked], LFY_UA_ERM_UFA set true; [Checked]
5. Panel CFY_UD in State S_FRSE
6. Panel CFY_UD Input Signal CFY_UD_I_FTA [Checked]
7. Panel CFY_UD "Step Pressed" = State Transition to S_FAIL


All Above is Correct

9. Panel ERM_UA ... Signal ERM_UA_I_UFN [Unchecked] should be [Checked] not linked ?????
10. Panel ERM_UA "Step Pressed" = State Transition does not work, manually check ERM_UA_I_UFN transition works

ERM_UD Panel


1. State ERM_UD_S_RSIL Output Signal ERM_UD_O_LFY_STRD presently true; [Checked]
Change to false; [Unchecked]

2. State ERM_UD_S_SDIE Output Signal ERM_UD_O_LFY_STRD presently false; [Unchecked]
Change to true; [Checked]

3. Transition Missing State ERM_UD_S_SAIL --> ERM_UD_S_RSIE
(goes to inital/reset at present ...correct signal at panel)


The Good News is that the "codes" i posted in posts 172 to 175 support the above findings, well good for me anyhow
 
Last edited:

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
<edit>posts 172 to 175 cover your changes better. I'll do them first and cross check with your later posts..

So you can pretty much ignore everything below... </edit>

Going back to states and transitions, we have (for CFT_UD)

States:

Code:
S_INIT
    Output Indications 
        [All Unchecked]
    Output Signals
        [All Unchecked]

S_RSIE
    Output Indications 
        CFY_UD_O_ANS [Checked]
    Output Signals
        [All Unchecked]

S_SDIC
    Output Indications
        CFY_UD_O_TRD [Checked]
    Output Signals  
       CFY_UD_O_ERM_STRD [Checked] ( to ERM_UA)

S_SAIE
    Output Indications 
        CFY_UD_O_TA [Checked]
    Output Signals   
        [All Unchecked]

S_FDIC
    Output Indications 
        CFY_UD_O_FRSD [Checked]
    Output Signals  
        CFY_UD_O_ERM_FRSD [Checked] (to ERM_UA)
        CFY_UD_O_LFY_FRSD [Checked]

S_FRSE 
    Output Indications 
        CFY_UD_O_FRS [Checked]
    Output Signals 
        [All Unchecked]

S_FAIL
    Output Indications 
        CFY_UD_O_FTA [Checked]
    Output Signals  
        [All Unchecked]
And this is achieved by:

Code:
procedure TfrmERM_UA.SetState(iState: integer);
begin
  case iState of
    S_ERM_UA_S_INIT:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

    S_ERM_UA_S_RSIE:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := true;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := true;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

    S_ERM_UA_S_SDIC:
      Begin
        chkERM_UA_O_TWA.Checked := true;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

    S_ERM_UA_S_SAIE:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := true;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

    S_ERM_UA_S_FDIC:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := true;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

    S_ERM_UA_S_FRSE:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := true;
        chkERM_UA_O_UFN.Checked := false;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := true;
        chkERM_UA_O_CFY_FRS.Checked := true;
      end;

    S_ERM_UA_S_FAIL:
      Begin
        chkERM_UA_O_TWA.Checked := false;
        chkERM_UA_O_AUT.Checked := false;
        chkERM_UA_O_RNS.Checked := false;
        chkERM_UA_O_UFRD.Checked := false;
        chkERM_UA_O_FRS.Checked := false;
        chkERM_UA_O_UFN.Checked := true;

        chkERM_UA_O_CFY_SUTA.Checked := false;
        chkERM_UA_O_CFY_RNS.Checked := false;
        chkERM_UA_O_LFY_FRS.Checked := false;
        chkERM_UA_O_CFY_FRS.Checked := false;
      end;

  else
    begin
      Showmessage('Illegal State');
    end;
  end;

  // pass on the output states
  frmCFY_UD.chkCFY_UD_I_STA.Checked := chkERM_UA_O_CFY_SUTA.Checked;
  frmCFY_UD.chkCFY_UD_I_ANS.Checked := chkERM_UA_O_CFY_RNS.Checked;
  frmLFY_UA.chkLFY_UA_I_FRS.Checked := chkERM_UA_O_CFY_FRS.Checked;
  frmCFY_UD.chkCFY_UD_I_FRS.Checked := chkERM_UA_O_CFY_FRS.Checked;
end;
and transitions:

Code:
When in state 

S_INIT
    CFY_UD_I_ANS --> State S_RSIE

S_RSIE
    CFY_UD_I_TRD --> State S_SDIC 
    CFY_UD_I_FRSD --> State S_FDIC

S_SDIC
    CFY_UD_I_STA --> State S_SAIE

S_SAIE

S_FDIC
    CFY_UD_I_FRS --> State S_FRSE

S_FRSE
    CFY_UD_I_FTA --> State S_FAIL

S_FAIL
You have left the transition from S_SAIE and S_FAIL back to S_RSIE undefined (and this is one reason to keep the states and transitions separate).

I believe that in both cases the transition is:

Code:
    ERM_UA_I_RNS --> S_RSIE
And this is achieved by:

Code:
procedure TfrmERM_UA.ProcessTransitions;
var
  iState: integer;
begin
  iState := cmbState.ItemIndex; // get the current state

  // no see if we can transition to another state
  case iState of
    S_ERM_UA_S_INIT: { 0 }
      Begin
        if chkERM_UA_I_RNS.Checked then
        begin
          GoToState(S_ERM_UA_S_RSIE);
        end;
      end;

    S_ERM_UA_S_RSIE: { 1 }
      Begin
        if chkERM_UA_I_TWA.Checked then
        begin
          GoToState(S_ERM_UA_S_SDIC);
        end
        else if chkERM_UA_I_UFRD.Checked then
        begin
          GoToState(S_ERM_UA_S_FDIC);
        end;
      end;

    S_ERM_UA_S_SDIC: { 2 }
      Begin
        if chkERM_UA_I_AUT.Checked then
        begin
          GoToState(S_ERM_UA_S_SAIE);
        end;
      end;

    S_ERM_UA_S_SAIE: { 3 }
      Begin
        if chkERM_UA_I_RNS.Checked then
        begin
          GoToState(S_ERM_UA_S_RSIE);
        end;
      end;

    S_ERM_UA_S_FDIC: { 4 }
      Begin
        if chkERM_UA_I_FRS.Checked then
        begin
          GoToState(S_ERM_UA_S_FRSE);
        end;
      end;

    S_ERM_UA_S_FRSE: { 5 }
      Begin
        if chkERM_UA_I_UFN.Checked then
        begin
          GoToState(S_ERM_UA_S_FAIL);
        end;
      end;

    S_ERM_UA_S_FAIL: { 6 }
      Begin
        if chkERM_UA_I_RNS.Checked then
        begin
          GoToState(S_ERM_UA_S_RSIE);
        end;
      end;

  else { illegal }
    begin
      Showmessage('Illegal State');
      GoToState(S_ERM_UA_S_INIT);
    end;
  end;

  // simulate edge sensitivity by turning things off
  chkERM_UA_I_AUT.Checked := false;
  chkERM_UA_I_RNS.Checked := false;
  chkERM_UA_I_RS.Checked := false;
  chkERM_UA_I_FRS.Checked := false;
end;
 
Last edited:

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
Panel ERM_UD

Steve Please Read Notes (Concerns) about this panel at end of this post.
NOTE also that State Identifiers are incorrect for this panel and have been changed ( this
may be because its easier to code, in which case i can live with that. Identifiers changed in Red)

Internally I was using exactly the states you wanted. I had simply forgotten to change the labels in the drop down list!
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
I'm glad you're about. I'm about to release a new version for you to look at.

For anyone following along at home, the source will be attached here as a zip file. (I can't attach the executable)

The code is written using Delphi XE which won't run on an Arduino, but the end result can be converted to C++ fairly simply. I just find it easier to write windows GUI apps in Delphi.

edit: Mark -- Be expecting email!
 

Attachments

  • TrainControl.zip
    10.6 KB · Views: 79
Last edited:

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Hi Steve

Thank You for the email :)

A greatly improved version...apart from typos mentioned in post181 The Program Runs Perfectly Fine. Just 1 little alteration missed.

Code from post 174

1. State ERM_UD_S_RSIL (Ready Service next Initiated LFY) [ NOT RSIE]

Output Indicators

ERM_UD_O_TRD = Off
ERM_UD_O_TA = Off
ERM_UD_O_ANS = ON

Input Signals

ERM_UD_I_UTA = Off
ERM_UD_I_ANS = ON

Output Signals

ERM_UD_O_LFY_STRD = Off
Code:
Begin
        chkERM_UD_O_TRD.Checked := false;
        chkERM_UD_O_TA.Checked := false;
        chkERM_UD_O_ANS.Checked := true;
        
        chkERM_UD_O_LFY_STRD.Checked := false;
    end;

2. State ERM_UD_S_SDIE (Slow Dispatch ready Initiated ERM) [ NOT SDIC]

Output Indicators

ERM_UD_O_TRD = ON
ERM_UD_O_TA = Off
ERM_UD_O_ANS = Off

Input Signals

ERM_UD_I_UTA = Off
ERM_UD_I_ANS = Off

Output Signals

ERM_UD_O_LFY_STRD = ON



Code:
Begin
        chkERM_UD_O_TRD.Checked := true;
        chkERM_UD_O_TA.Checked := false;
        chkERM_UD_O_ANS.Checked := false;
        
        chkERM_UD_O_LFY_STRD.Checked := true;
    end;
ERM_UD_O_LFY_STRD is set the opposite way in these 2 states....The code above is the correct way.

Also

Post from post from 181

ERM_UA Panel

1. State ERM_UA_S_SAIE Output Signal ERM_UA_O_CFY_SUTA presently false; [Unchecked]
Change to true; [Checked]

2. State Transition ERM_UA_S_FRSE --> ERM_UA_S_FAIL Input Signal ERM_UA_I_UFN not received?

1. Panels CFY_UD, ERM_UA, LFY_UA in State S_FRSE
2. Input Control LFY_UA_I_UFA pressed and "Step" on this panel pressed
3. LFY_UA Panel goes to State S_FAIL
4. LFY_UA Output Signals LFY_UA_CFY_UFA set true; [Checked], LFY_UA_ERM_UFA set true; [Checked]
5. Panel CFY_UD in State S_FRSE
6. Panel CFY_UD Input Signal CFY_UD_I_FTA [Checked]
7. Panel CFY_UD "Step Pressed" = State Transition to S_FAIL


All Above is Correct

9. Panel ERM_UA ... Signal ERM_UA_I_UFN [Unchecked] should be [Checked] not linked ?????
10. Panel ERM_UA "Step Pressed" = State Transition does not work, manually check ERM_UA_I_UFN transition works


ERM_UA_I_UFN not getting to panel :confused:

You were probably sleeping when i sent this post

Thank You Heaps the rest of the panel is AWESOME :)

Mark
 
Last edited:

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
DAM STEVE YOUR GOOD :D:D:D:D

Thought to myself .... soon Steve will ask about Control Inputs and What State they are locked or unlocked

So i drew up a table

Control Inputs Locked_Unlocked2.jpg

Control Inputs Locked_Unlocked1.jpg

Only to find You have already dealt with this
AND I MISSED IT :eek:

YOU'RE THE MAN
 
Last edited:

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
I will admit to not understanding fully that table.

However the fact that I implemented it from just the states and transitions is indicative of the power of the method.

At this point when writing the code, all I am interested is getting the states right and the transitions correct. I am not thinking of the actual meaning in real life. In fact, their meaning is not important to me so my understanding of the actual "problem" is not improving at all.

However, I am able to easily write code to implement what should be getting close to a correct solution.

And as you can see, your task is getting the states and transitions right, and mine is getting them implemented correctly.

I will admit to having the far easier job!

Once we have that correct, I'll walk you through the process of getting all of this written onto an arduino (or multiple arduinos).

At that point, (I hope) you'll see that all of what you have learned about programming will yield a solution that you could be confident in adapting to other uses (the line in the other direction) and eventually to things even more different (like other track layouts).

edit: yeah, there are a few more changes to make -- but we're almost there.
 

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
At this point when writing the code, all I am interested is getting the states right and the transitions correct. I am not thinking of the actual meaning in real life. In fact, their meaning is not important to me so my understanding of the actual "problem" is not improving at all.

However, I am able to easily write code to implement what should be getting close to a correct solution.

And as you can see, your task is getting the states and transitions right, and mine is getting them implemented correctly.

I will admit to having the far easier job!

Really !! There's me thinking you got the short straw :D

At that point, (I hope) you'll see that all of what you have learned about programming will yield a solution that you could be confident in adapting to other uses (the line in the other direction) and eventually to things even more different (like other track layouts).

I Can, I think i have grasped the concepts well, if not the actual code implentation... i hope this will come with time and hard work . I'm fairly confident that the Down Line will not be beyond my abilities (hopes that this does not bite me in the butt)

I have already decided that Finite State Machine is the way forward for the next part of this project ... Track Routing.

Already i have seen distinct similarities in the code you are using with that of the Arduino platform and am busy studying that :)

Mark
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
I've had to chance ERM_UA_I_UFN to ERM_UA_I_UFA and consequently LFY_UA_O_ERM_UFN to LFY_UA_O_ERM_UFA to make everything work. Considering the description for all of these is "Up Fast Accepted" I think it was a typo.

Amazing. Three people downloaded the source, so I'll upload it again :)

And you have mail...
 

Attachments

  • TrainControl.zip
    10.6 KB · Views: 77

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Hi Steve

:D :cool: :) :D :cool: :) :D :cool: :) :D :cool: :) :D :cool: :) :D :cool: :) :D :cool: :) :D :cool: :)

CONGRATULATIONS works as intended and is totally awesome Thank You :D

A few post back, well OK quite a few post back I talked about getting from the state Fast Train Accepted (S_FAIL) back to Ready Next Service (S_RSIE or S_RSIL). In one of the transcripts i toyed with two methods but actually now I've played with the latest version of your program this problem has been solved as I works well :D

I can also confirm that ALL pushbutton are indeed locked except for the one intended to enter the transition to the next state which is also Fantastic.

For Your Patience, Perserverance and Hard Work I am In Your Debt

Mark
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
Thanks :)

Now it's your turn to think about writing code.

I think we've already decided that each panel will be controlled by its own arduino. That makes it simple.

Pick a panel (I'd start with the one with the fewest inputs and states). Take a look at my code and identify the two main procedures.

1) The one which sets the outputs based on a state

2) The one which transitions between states based on the inputs

Firstly, can you see how these two routines embody all of your states and transitions? Can you see that there is just one other small piece of logic that plays a significant part? (And can you see the parts of the logic which are specific to this being a simulation?) Could you extract your states and transitions from these?

Have a go at doing this for the simplest panel just to verify your understanding. I'll give you a hand if you get stuck.

Then later...

Go back to the arduino state machine code you had and see if you can see how this essential logic will fit in.

Could you translate this code to C++?

But before you do...

A naming standard and a set of defined constants will help make your code easier to understand and debug. Note how my code defined all of the states with meaningful names instead of numbers? That works differently in C++ but you should still use this mechanism.

Also, remember that our inputs and outputs were not so simple as in this example. We need to do some "magic" to get the logic states from our inputs (we handled that before), and we clearly need to do something to translate the outputs since some flash, and others chase a set of LEDs.

And to repeat myself, some of the logic in this simulator exists because we need to simulate edge detection, and to link up the various panels. This is part of the dirty grungy stuff in the simulator that won't happen this way in the real application.
 

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
:eek::eek::eek::eek::eek::eek:

OK Well i give it a GO. May take some time but i'll update asap.
Time for you to have a rest :D

Mark
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
I'm on holiday for a week. Possibly the best time to get me to do stuff! :D
 

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Hi Steve,

Hope your having a Fab Break :D

Well this is very much still work in progress, but i seem to have got my knickers in a twist lol

Because I don't know how the communication between Arduinos works i have included 2 switches from the LFY_UA Panel to get something that will function if built.

Looking back NOW this probably aint a good idea.. but time is getting on so any pointers greatfully received


Code:
// **** ERM_UD FSM ****

// Debounce


// FSM Define States for ERM_UD Panel

int iState;

#define S_ERM_UD_S_INIT  0 // Initial State  
#define S_ERM_UD_S_RSIL  1 // Ready next Service State 
#define S_ERM_UD_S_SDIE  2 // Slow  up Dispatch Ready State 
#define S_ERM_UD_S_SAIL  3 // Slow Down Accepted State

#define S_ERM_UD_S_FDIC  4 // Fast up Dispatch Ready State
#define S_ERM_UD_S_FRSE  5 // Fast Route Set State
#define S_ERM_UD_S_FAIL  6 // Fast up Accepted State

// Declare Input Controls for FSM ERM_UD Panel

const int ERM_UD_I_TRD = 6; // Train Ready Dispatch Button @ Pin ?
bool lastButton_ERM_UD_I_TRD;
bool currentButton_ERM_UD_I_TRD;
long lastButton_ERM_UD_I_TRD_Time;

/*    For the purose of testing 2 additional Input Controls from LFY_UA are needed in this program
      These are listed in Input Controls from Other Panels
      I will use the "Output Signal" Identifiers from this panel to identify the Input Controls on this panel
      This will lest the link between them and this panel
      At the End of the testing these will be removed and added to "Input Signals from Other FSMs
*/


// Declare Input Controls From Other Panels Used for Testing Purposes Only

const int  Test_LFY_UA_O_ERM_SUTA = 7;
bool lastButton_LFY_UA_O_ERM_SUTA;
bool currentButton_LFY_UA_O_ERM_SUTA;
long lastButton_LFY_UA_O_ERM_SUTA_Time;



const int  Test_LFY_UA_O_ERM_RNS = 8;
bool lastButton_LFY_UA_O_ERM_RNS;
bool currentButton_LFY_UA_O_ERM_RNS;
long lastButton_LFY_UA_O_ERM_RNS_Time;



// Declare Output Indications for FSM ERM_UD Panel

const int ERM_UD_O_TRD = 10;    // Train Ready Dispatch LED @ Pin?
bool ledOn_ERM_UD_O_TRD;

const int ERM_UD_O_TA = 11;     // slow Train Accepted LED @ Pin?
bool ledOn_ERM_UD_O_TA;

const int ERM_UD_O_ANS = 12;    // Awaiting Next Service LED @ Pin
bool ledOn_ERM_UD_O_ANS;

// Declare Input Signals for FSM ERM_UD Panel

bool ERM_UD_I_UTA;    // Signal attached to LFY_UA_O_ERM_SUTA
bool ERM_UD_I_ANS;    // Signal attcahed to LFY_UA_O_ERM_RNS

// Declare Input Signals from Other FSM Panels used on ERM_DA
// These will eventually be sent via IC2 ? from LFY

  bool LFY_UA_O_ERM_SUTA = false;    // Signal from LFY_UA Panel used for Up Train Accepted
  bool LFY_UA_O_ERM_RNS = false;     // Signal from LFY_UA Panel used for Ready Next Service    


// Declare Output Signals for FSM ERM_UD Panel to Other FSMs

 bool ERM_UD_O_LFY_STRD = false;  // Signal to LFY_UA_I_STRD Slow Train Ready Dispatch

void inputSignalLogic ()
{
 bool LFY_UA_O_ERM_SUTA = digitalRead(Test_LFY_UA_O_ERM_SUTA);
 bool LFY_UA_O_ERM_RNS = digitalRead(Test_LFY_UA_O_ERM_RNS);
   
  ERM_UD_I_UTA = LFY_UA_O_ERM_SUTA;
  ERM_UD_I_ANS = LFY_UA_O_ERM_RNS;
}



void readERM_UD_SwitchStates() {
  // read the current button states
  simpleDebounce(ERM_UD_I_TRD, currentButton_ERM_UD_I_TRD, lastButton_ERM_UD_I_TRD, lastButton_ERM_UD_I_TRD_Time);
  
  simpleDebounce(LFY_UA_O_ERM_SUTA, currentButton_LFY_UA_O_ERM_SUTA, lastButton_LFY_UA_O_ERM_SUTA, lastButton_LFY_UA_O_ERM_SUTA_Time);
  simpleDebounce(LFY_UA_O_ERM_RNS, currentButton_LFY_UA_O_ERM_RNS, lastButton_LFY_UA_O_ERM_RNS, lastButton_LFY_UA_O_ERM_RNS_Time);



bool pressEdge(bool& state, bool lastVal) // detects the leading edge of a button press.
{
  if ((!state) && lastVal)  // button pressed, but state not yet set
  {
    state = true;            // set the state without waiting for debouncing
    return true;             // return a valid edge
  } 
  else {
    return false;            // it's not a press edge.
  }
}

void ERM_UDsetStateI(int &iState, long &lTime, int iValue) {
  if (iState != iValue) {
    iState = iValue;
    lTime = millis();
    //     bChanged = true;
  }
}

// ERM_UD stateChange test conditions to initialize a State Change

void TfrmERM_UD_ProcessTransitions ()     // Transistion From ERM_UD_State
{
  switch (iState) 
  {
  case S_ERM_UD_S_INIT:  // Initial State
    if (pressEdge(currentButton_LFY_UA_O_ERM_RNS, lastButton_LFY_UA_O_ERM_RNS))
    {
      iState = (S_ERM_UD_S_RSIL);
    }
    break;

  case S_ERM_UD_S_RSIL:   // Ready Next Service
    if (pressEdge(currentButton_ERM_UD_I_TRD, lastButton_ERM_UD_I_TRD))
    {
      iState = (S_ERM_UD_S_SDIE);
    }
    break;

  case S_ERM_UD_S_SDIE:    // Slow Train Ready Dispatch
    if (pressEdge(currentButton_LFY_UA_O_ERM_SUTA, lastButton_LFY_UA_O_ERM_SUTA))
    {
      iState = (S_ERM_UD_S_SAIL);
    }
    break;

  case S_ERM_UD_S_SAIL:    // Slow Train Accepted
    if (pressEdge(currentButton_LFY_UA_O_ERM_RNS, lastButton_LFY_UA_O_ERM_RNS))
    {      iState = (S_ERM_UD_S_RSIL);
    }
    break;

  default:
    Serial.println("Illegal State");
    iState = (S_ERM_UD_S_INIT);
    break;
  }
}


void TfrmERM_UD_SetState ()  // Set the Output States
{
  switch(iState)
  {
  case S_ERM_UD_S_INIT:
    {
      ledOn_ERM_UD_O_TRD = false;
      ledOn_ERM_UD_O_TA = false;
      ledOn_ERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = false;

      Serial.println("All LEDs Are Off");
    }
    break;

  case S_ERM_UD_S_RSIL:
    {
      ledOn_ERM_UD_O_TRD = false;
      ledOn_ERM_UD_O_TA = false;
      ledOn_ERM_UD_O_ANS = true;

      ERM_UD_O_LFY_STRD = false;

      Serial.println("Awaiting Next Service LED Now ON");
    }
    break;

  case S_ERM_UD_S_SDIE:
    {
      ledOn_ERM_UD_O_TRD = true;
      ledOn_ERM_UD_O_TA = false;
      ledOn_ERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = true;

      Serial.println("Slow Train Ready Dispatch LED Now ON");
      Serial.println("Awaiting Next Service LED Is Now OFF");
    }
    break;

  case S_ERM_UD_S_SAIL:
    {
      ledOn_ERM_UD_O_TRD = false;
      ledOn_ERM_UD_O_TA = true;
      ledOn_ERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = false;

      Serial.println("Slow Train Accepted LED Now ON");
      Serial.println("Slow Train Ready Dispatch LED Is Now OFF");
    }
    break;

  default:
    {
      Serial.println("Illegal Output State");
    }
    break;
  }
}

void writeERM_UD_LEDStates() // writes the current states to the LEDs
// These will be set On until the program has been tested 
// Then set to the correct output (i.e fade, pulse, flash)
{

  digitalWrite(ERM_UD_O_TRD, ledOn_ERM_UD_O_TRD);
  digitalWrite(ERM_UD_O_TA,  ledOn_ERM_UD_O_TA);
  digitalWrite(ERM_UD_O_ANS, ledOn_ERM_UD_O_ANS);
}


void setup()
{
  // initialize pins
  pinMode(ERM_UD_I_TRD, INPUT);

  pinMode(Test_LFY_UA_O_ERM_SUTA, INPUT);    // This is here purely to test the code then it will be removed when IC2 link added
  pinMode(Test_LFY_UA_O_ERM_RNS, INPUT);     // This is here purely to test the code then it will be removed when IC2 link added
  
  pinMode(ERM_UD_O_TRD, OUTPUT);
  pinMode(ERM_UD_O_TA, OUTPUT);
  pinMode(ERM_UD_O_ANS, OUTPUT);



  // initialize serial: This will only be used to verify program and then be removed
  Serial.begin(9600);
  int TfrmERM_UD_SetState (-1);

}
void loop()
{
  void inputSignalLogic ();

  void readERM_UD_SwitchStates();
  
  void TfrmERM_UD_ProcessTransitions ();

  void TfrmERM_UD_SetState ();

  void writeERM_UD_LEDStates();
}


Mark

OH BTW the serial.println in the statements was how i was going to test the panel. Again these will be removed as will any reference to additional switches added to ERM_UD panel
 
Last edited:

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Hi Steve,

How was Your Week ?

I seem to be stuck, here is my code thus far.

Code:
// ERM_UD Train Control Sequence Panel FSM


#define DBTIME 25;  // Time for Debouncing the Switch



// Debounce Function

// [state] = The current state( do we say it is currently on or off)
// [val]  = The current input value ( is it on or off now?)
// [time] = The current time (now)
// [lastVal] = The input value 9 was it on or off last time we looked?]
// [lastTime] = The last time we checked
// [dbTime] = The time for the switch to stabilze (The time the input state must remain unchanged to effect a change in state)

// We will only register a change of state if the input value has not changed for a certain time.

//    ARDUINO FUNCTION STRUCTURE

//    returntype functionName( arguments ){
//    function body
//    return returntype;

bool debounce (bool state, bool val, long time, long dbTime, bool& lastVal, long& lastTime)
{
  bool newState = state;         // by default the newState is the old state
  
    if (lastVal != val)     // if the input value has changed
   {
    lastTime = time;        // set the last time it changed to now
    lastVal = val;          // and store the current value in last value
   }
   else                     // otherwise ( the input has NOT changed)
   {
     if ((time - lastTime) >= dbTime)    // if it has remained stable long enough
     {
       newState = val;      // change the state
     }
   }
   return newState;        //  return this is the new State
}

// A debounce function with a simpler interface

bool simpleDebounce (int inPin, bool& state, bool& lastVal, long& lastTime)
{
  long time = millis ();    // time in milliseconds
  bool val = digitalRead(inPin);    // current pin value
  long dbTime = DBTIME;             // debounce interval
  
  state = debounce(state, val, time, dbTime, lastVal, lastTime);    //Debounce the Pin
  
  return state;                     // return the new state
}

// *** THE FSM STATES: ***

// I have retained states 4 to 6 but these are currently not used so will not be called on this panel
// Later they may be used to do something to this panel when a "fast service" is being Sequenced.

const int  S_ERM_UD_S_INIT = 0;     // Initial State  
const int  S_ERM_UD_S_RSIL = 1;     // Ready next Service State 
const int  S_ERM_UD_S_SDIE = 2;     // Slow  up Dispatch Ready State 
const int  S_ERM_UD_S_SAIL = 3;     // Slow Down Accepted State

const int  S_ERM_UD_S_FDIC = 4;     // Fast up Dispatch Ready State
const int  S_ERM_UD_S_FRSE = 5;     // Fast Route Set State
const int  S_ERM_UD_S_FAIL = 6;     // Fast up Accepted State

int iState;
long lStateTime;
bool bChanged = false;



// Control Inputs

const int ERM_UD_I_TRD = 6;    // ERM_UD Train Ready Dispatch PushButton @ Pin 6
bool lastButtonERM_UD_I_TRD;
bool currentButtonERM_UD_I_TRD;
long lastButtonERM_UD_I_TRDTime;


bool ERM_UD_I_TA = false;    // Signal from LFY_UA_O_ERM_SUTA "Slow Up Train Accepted"

bool ERM_UD_I_ANS = false;   // Signal from LFY_UA_O_ERM_RNS "Ready Next Service"

// Control Inputs from Other Panels for Testing Purposes Only

const int LFY_UA_I_RNS = 7;    // LFY_UA Ready Next Service PushButton @ Pin 7
bool lastButtonLFY_UA_I_RNS;
bool currentButtonLFY_UA_I_RNS;
long lastButtonLFY_UA_I_RNSTime;

const int LFY_UA_I_UTA = 8;    // LFY_UA Up Train Accepted PushButton @ Pin 8
bool lastButtonLFY_UA_I_UTA;
bool currentButtonLFY_UA_I_UTA;
long lastButtonLFY_UA_I_UTATime;

// Input Signals from Other Panels Used on This Panel

bool LFY_UA_O_ERM_RNS = false;   // Signal to ERM_UD_I_ANS "Ready Next Service" indicating button press on LFY_UA Panel 
bool LFY_UA_O_ERM_SUTA = false;  // Signal to ERM_UD_I_TA "Slow Up Train Accepted" indicating button press on LFY_UA Panel 

// Output Indications

const int ERM_UD_O_TRD = 10;     // ERM_UD Train Ready Dispatch LED @ Pin 10
bool ledOnERM_UD_O_TRD = false;

const int ERM_UD_O_ANS = 11;     // ERM_UD Awaiting Next Service LED @ Pin 11
bool ledOnERM_UD_O_ANS = false;

const int ERM_UD_O_TA = 12;      // ERM_UD Slow Train Accepted LED @ Pin 12
bool ledOnERM_UD_O_TA = false;

// Output Signals to Other Panels Indicating Button Press on This Panel

bool ERM_UD_O_LFY_STRD = false;  // Signal to LFY_UA_I_STRD "Slow Train Ready Dispatch" Indicating button pressed on this panel



void writeLedStates ()
{
   // set initial LED state
  digitalWrite(ERM_UD_O_TRD, ledOnERM_UD_O_TRD);
  digitalWrite(ERM_UD_O_ANS, ledOnERM_UD_O_ANS);
  digitalWrite(ERM_UD_O_TA, ledOnERM_UD_O_TA);
}

void readButtonStates ()

{
  currentButtonERM_UD_I_TRD = lastButtonERM_UD_I_TRD = digitalRead(ERM_UD_I_TRD);
  lastButtonERM_UD_I_TRDTime = millis ();
  
  currentButtonLFY_UA_I_RNS = lastButtonLFY_UA_I_RNS = digitalRead(LFY_UA_I_RNS);
  lastButtonLFY_UA_I_RNS = millis ();
  
  currentButtonLFY_UA_I_UTA = lastButtonLFY_UA_I_UTA = digitalRead(LFY_UA_I_UTA);
  lastButtonLFY_UA_I_UTATime = millis ();
}
  

void setup() 
{
  // Initalize the Pins
  
  pinMode(ERM_UD_I_TRD, INPUT);
  pinMode(LFY_UA_I_RNS, INPUT); 
  pinMode(LFY_UA_I_UTA, INPUT);
  
  pinMode(ERM_UD_O_TRD, OUTPUT);
  pinMode(ERM_UD_O_ANS, OUTPUT);
  pinMode(ERM_UD_O_TA,  OUTPUT);
  
  // set initial output LED state
  writeLedStates ();
  
  // get initial state of buttons
  readButtonStates ();
  
//need to add initial state here as an illegal to force change to correct state
  ERM_UD_SetState(-1);   
  
  Serial.begin(9600);
}

void readDebouncedSwitchStates ()
{
 simpleDebounce(ERM_UD_I_TRD, currentButtonERM_UD_I_TRD, lastButtonERM_UD_I_TRD, lastButtonERM_UD_I_TRDTime);
 simpleDebounce(LFY_UA_I_RNS, currentButtonLFY_UA_I_RNS, lastButtonLFY_UA_I_RNS, lastButtonLFY_UA_I_RNSTime);
 simpleDebounce(LFY_UA_I_UTA, currentButtonLFY_UA_I_UTA, lastButtonLFY_UA_I_UTA, lastButtonLFY_UA_I_UTATime);
    
}
 // detect the leading edge of a button press
 
bool pressEdge (bool& state, bool lastVal)
{
  if ((!state) && lastVal)    // button pressed, but state not set
  {
    state = true;             // set state without waiting for debouncing
    return true;              // return a valid edge
  }
  else
  {
    return false;            // it is NOT a press edge.
  }
}


//  void functionSetStateB - Allows you to turn on and off a Boolean Variable and Set the Time, only if the state changes.
                          // Example: If you set LED1 state 10 times to true, the time reflects the first time you set it 
                          // true so it just keeps flashing.
                          // In our previous example:
                                                   // bLed1State was a boolean indicating whether the LED was on or off.
                                                   // lLED1Time was the time that the LED changed State
                                                   
                                                   // ledA3 - Red Flashing - "Ready Next Service" 
                                                   // const int ledA3 = 4;
                                                   // bool ledOnA3 = false;
                                                   // bool ledA3FlashState = false;               <---- THIS ONE
                                                   // long ledA3LastFlashTime = -(FLASH_TIME);    <---- THIS ONE
                                                   
                          // And the Code to Make it Flash:
                                                             //   ** Flashing ledA3 **
                                                             //  long time = millis();                   // get the time
  
                                                             //  if (ledOnA3) {                           // are we flashing?
                                                             //  if (time >= (ledA3LastFlashTime + FLASH_TIME)) { // time to chang LED state?
                                                             //  ledA3FlashState = !ledA3FlashState;   // change LED state
                                                             //  ledA3LastFlashTime = time;           // and set the time 
                                                             //  digitalWrite(ledA3, ledA3FlashState); // Change LED state
                                                             //  }
                                                             //  } else {                                // not flashing?
                                                             //  digitalWrite(ledA3, false);            // turn LED off


void functionSetStateB(bool &bState, long &lTime, bool bValue) // Set State and Time for a boolean variable to use elsewhere, flashing LEDs,
{
  long lDummyTimeStamp = millis();
  
  if (bState != bValue)
  {
    bState = bValue;
    lTime = millis();
    bChanged = true;    // with this you can set all of your states (and then all of your sub-states in the output routine)
  }                     // and check for bChange being true. If it is , write the outputs, if not don't bother. 
}                       // Finally clear bChanged ( or do it at the top of your state setting module. ( void ERM_UD_ProcessStateTransitions ()).
 
 
// void functionSetStateI - Sets the State and Time for a numerical variable
 
void functionSetStateI(int &iState, long &lTime, int iValue) 
{
  if (iState != iValue) 
  {
    iState = iValue;
    lTime = millis();
    bChanged = true;
  }
}
    
    
/* The problem with this is that the first time through, the outputs will probably not be set because bChanged is false.
   We can turn this to our advantage. earlier i said that the initialization "of the FSM " could be as simple as setting a state.
   If we set this initialization state to an invalid state it will force the first time through to generate a change, and place
   the system into the correct state.
   You might initialize with

void setup ()
{
  ERM_UD_SetState(-1);
}
*/


// void ERM_UD_ProcessStateTransitions ()- // Tests for Conditions to Initiate a State Change.
                                           // If ALL of the conditions are met it will change to the State indicated under the test for that State.


void ERM_UD_ProcessStateTransitions ()     // Referred to by Steve as stateChange in early transcript
{
  bChanged = false;    // resets bChanged in void functionSetStateI and void functionSetStateB (described earlier).
  
  switch (iState) 
  {
  case S_ERM_UD_S_INIT:  // Initial State
    if (pressEdge(currentButtonLFY_UA_I_RNS,lastButtonLFY_UA_I_RNS))      // This will eventually be a Input Signal from LFY_UA
    {
      ERM_UD_SetState(1);
      //ERM_UD_SetState(S_ERM_UD_S_RSIL);
    }
    break;

  case S_ERM_UD_S_RSIL:   // Ready Next Service
    if (pressEdge(currentButtonERM_UD_I_TRD, lastButtonERM_UD_I_TRD))      // This will remain unchanged.
    {
      ERM_UD_SetState(2);
      //ERM_UD_SetState(S_ERM_UD_S_SDIE);
    }
    break;

  case S_ERM_UD_S_SDIE:    // Slow Train Ready Dispatch
    if (pressEdge(currentButtonLFY_UA_I_UTA, lastButtonLFY_UA_I_UTA))    // This will eventually be an Input Signal from LFY_UA
    {
     ERM_UD_SetState(3);
      // ERM_UD_SetState(S_ERM_UD_S_SAIL);
    }
    break;

  case S_ERM_UD_S_SAIL:    // Slow Train Accepted
    if (pressEdge(currentButtonLFY_UA_I_RNS, lastButtonLFY_UA_I_RNS))      // This will eventually be a Input Signal from LFY_UA
    {
      ERM_UD_SetState(1);
      //ERM_UD_SetState(S_ERM_UD_S_RSIL);
    }
    break;

  default:
    ERM_UD_SetState(0);
    //ERM_UD_SetState(S_ERM_UD_S_INIT);
    break;
  }
}

 
// void ERM_UD_SetState (int newState) - *** ALL STATE VARIABLES MUST BE GLOBAL ***
                                       // This piece of code sets things when the State Changes.


void ERM_UD_SetState (int newState)                  // Referred to by Steve as machineState in early transcripts
{
  functionSetStateI(iState, lStateTime, true);         // This sets StateI to allow to register the time in the state
     
  switch(iState)
  {
  case S_ERM_UD_S_INIT:
    {
      ledOnERM_UD_O_TRD = false;
      ledOnERM_UD_O_TA = false;
      ledOnERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = false;
    }
    break;

  case S_ERM_UD_S_RSIL:
    {
      ledOnERM_UD_O_TRD = false;
      ledOnERM_UD_O_TA = false;
      ledOnERM_UD_O_ANS = true;

      ERM_UD_O_LFY_STRD = false;
    }
    break;

  case S_ERM_UD_S_SDIE:
    {
      ledOnERM_UD_O_TRD = true;
      ledOnERM_UD_O_TA = false;
      ledOnERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = true;
    }
    break;

  case S_ERM_UD_S_SAIL:
    {
      ledOnERM_UD_O_TRD = false;
      ledOnERM_UD_O_TA = true;
      ledOnERM_UD_O_ANS = false;

      ERM_UD_O_LFY_STRD = false;
    }
    break;

  default:
    {
      Serial.println("Illegal Output State");
    }
    break;
  }
}


void loop() 
  {
 while (true)    // This Statement is Automatic in void loop but helps to see whats going on when reading sketch.
 {
  readDebouncedSwitchStates ();

  ERM_UD_ProcessStateTransitions ();
  
  ERM_UD_SetState (iState);
   
  writeLedStates ();
 }
 
}

It's works... well only in the fact when uploaded to the Arduino ERM_UD_O_ANS @ pin 11 illuminates...looking into why that is as

Code:
const int ERM_UD_O_ANS = 11;     // ERM_UD Awaiting Next Service LED @ Pin 11
bool ledOnERM_UD_O_ANS = false;

So that suggest to me that even without a button press we are in

Code:
case S_ERM_UD_S_RSIL:
    {
      ledOnERM_UD_O_TRD = false;
      ledOnERM_UD_O_TA = false;
      ledOnERM_UD_O_ANS = true;

      ERM_UD_O_LFY_STRD = false;
    }
    break;

NO Other Control Inputs make a state transition, this suggests i am missing the KEY to this part :rolleyes:

On the brighter side... at least i have an Output Indication Now LMAO:)

Mark
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
OK, I'm going through this.

The first issue is that the control inputs and outputs are REAL inputs and outputs too!

Code:
const int ERM_UD_I_TRD = 6;    // ERM_UD Train Ready Dispatch PushButton @ Pin 6
bool lastButtonERM_UD_I_TRD;
bool currentButtonERM_UD_I_TRD;
long lastButtonERM_UD_I_TRDTime;


bool ERM_UD_I_TA = false;    // Signal from LFY_UA_O_ERM_SUTA "Slow Up Train Accepted"

bool ERM_UD_I_ANS = false;   // Signal from LFY_UA_O_ERM_RNS "Ready Next Service"

Those signals from other panels need to be assigned pins and handled as inputs just like the switches. It's even a good idea to do the debouncing thing on them (it helps if there's electrical noise). The difference is that you don't use the "pressEdge" routine.

The same is true for output signals to other panels, they are real signals and you need to assign them a pin on the arduino.

For testing, you can place a switch on the inputs and a LED on the outputs.

In the simulation I produced, all we did was look at the state-transition model.

In the real case, we need to do 2 more things:

1) get the inputs from the arduino pins and debounce them (this includes capturing timestamps)
2) convert the output logic (true/false) into the outputs on the pins that we require (flashing, chasing, or simple on/off) This includes setting timestamps.

You've mostly covered (1) except for the control signals from other panels.

I would leave (2) for later. Just set/clear outputs and drive LEDs from them. Work on the other stuff later.

As an aside, for chasing 5 LEDs, you could use 5 separate output pins (there are other ways, but as long as you have the spare pins, go for it).
 

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Hi Steve,

Thanks for the post :)

My intention was to get this FSM working and driving (the correct) LEDs on/off and leave the fancy stuff until i got to that stage anyway.
Creep up the solution...
I retained something you told me :D

As for the code previously posted..
The idea was to include the LFY_UA Panel pushbuttons and work the link "however imaginary" to the correct place and hopefully verify that part of the code aswell. Once done all the code relating to the LFY_UA panel pushbuttons would be deleted leaving just the "link" code..

Well that was my logic however far off it may have been :eek:

As for the HOWs of these arduino's talking to each other and How the signal is sent and received and what happens to it once received I am totally in the dark... and this may explain (I Hope) my logic above

Mark ;)
 

P4 Modeller

Jan 4, 2013
120
Joined
Jan 4, 2013
Messages
120
Back to the Drawing Board Again !!!!!

For the life of me , i cannot seem to get it to work and more frustrating i don't know why?
All i do know now for certain is the code takes me straight to S_ERM_UD_S_RSIL in void ERM_UD_SetState (int newState) yet not a valid transition


Back to the google search bar
Mark
 
Last edited:
Top