Is anyone here interested in Train Signals and how they work?

This is the bigger picture and the red square is the bit of code I posted.
(give or take the couple of extra debug nodes which were captured on the left side)

And this is a picture of the GUI (train about halfway along the screen.)

Going Right - > Left.

Woo - that's very impressive.
Sounds like you have invested a considerable amount of time and energy into this project.
Are you planning on making a scale model of part of the rail network in Sydney or are you just interested in the 'control' aspects? Either way, it sounds good fun and very challenging.

Before I retired I worked as a computer science lecturer teaching microelectronics and programming.
One project, a group of my students undertook, was to control the speed and direction of a model train using Pulse Width Modulation (PWM) and an H-bridge. They built a track-layout consisting of an outer and inner circular-rectangular track with eight points so a train could move from one track to another.

The points were opearted via a CAN bus and a set of PIC microcontrollers. They also had some track-side signals (just simple twin LEDs) and infra-red beams positioned across the track just before each signal. This enabled the position of the train on the track to be determined and for it to be controlled.

If I had the time to do this project again (with today's technology) I think I would put a small WiFi microcontoller on each train so it could be controlled from Node-RED using a super-duper dashboard.

I wish you every success with your exciting project.

PS: Happy New Year.

I am just naturally curious.

I would like a bit of help getting the train control part working.

This is about iteration 3 of the subflow.

Before I build this one, I sat down with a big piece of paper and drew a basic flow of how it works.

So you are in Sydney too. Good. Your thoughts on this:
I was at Strathfield station. Platform 3. I was going to Rhodes.
Looking west, at the end of the platform signal: Green Yellow.
The next signal - at the points - Green Yellow.
The next train was going west.

Why two Green Yellow signals?

Anyway......

Yeah, I forget the name of the system which was introduced early 80's. DCC - I think.
That allowed multiple trains on the same DC track.

Anyway, the subflow:
It has a few outputs:
1 - to the next downstream block.
2 - Top light
3 - Bottom light
4 - The little light
5 - Text indication of points at this block
6 - Graphic output for point status
7 - Train status output.

I guess output #1 could be used to control speed for that block.
Though there is a bit of contention about if the block is before of after the signal/code.
I think it would be ok if it is after (track to the right side) of the signal.
Then if the signal is STOP, the train could come into/onto that block at low speed.
Then when it gets to the signal; that is stored and so when the signal clears/reduces the train signal is sent to the next block (to the LEFT) of that signal.

But that is where I fall over. I have some of the code there, but something isn't working quite the way I want.

Oh, and sorry. Thanks. Happy new year to you too.

Why do you think that?
I live in the UK, so have no idea about the names of the stations you mentioned.

At the moment I don't have any spare time to wade through your flows, as I'm preparing a set of tutorials and projects for a new group of students that I'll be tutoring starting this month.

One thing I would suggest is getting a small sub-section working (as briefly looking at your flows it would appear that many of the blocks are replicated). So once you get the basics working then you can scale it up.

(Ooops. The bad parser is still active - obviously)

I'll need to track that down and code it out of the flow.

I think the signals are similar to English ones.

No rush or worries.

What is tripping me up is how it holds the state and then releases it when the RELEASE code is received, and back propagating the signals to the previous block.

I may need a bigger piece of paper. :wink:

But thanks, I shall try to cut it down to smaller pieces and see if I can catch where it is falling apart.

Couple of suggestions.

What you're trying to do is implement a 'control system' using a Node-RED flow.
So the first thing to do is work out a specification or algorithm that defines what should happen under certain conditions. You probably have this already on your piece of paper. Having a good 'spec' also means you can create a testbench to prove the system works under all conditions.

For a very basic control system it normally means... "when I have these inputs then create this output".
Just like having a logic gate to detect an input and produce an output.

In your situation you are dealing with a non-trivial control system that has 'states' as well as 'inputs', so the complexity increases. For example detecting if there is a train within a block, about to leave a block or whether the block is empty will affect the track-side signals.

Many real-life (control) situations like getting money out of a cash machine are really a simple state machine. You have to do things in a certain sequence in order to get to the final result and sometimes there may be more than one path to get to a certain point.

I'm a big fan of finite state machines (FSMs) as it's usually a fairly easy task to construct a (graphical) state diagram to show how you can navigate from one state to another. Once the state diagram is complete and providing there are no dead-ends or unreachable states - you can code it.
Which language you use to do this is up to you, but since we are talking about Node-RED then JavaScript is probably the best choice.

If you want to see a simple example of a FSM then have a look at the Mathematical Magic Machine, I published on Discourse over Christmas. Hope you find this useful.

Mathematical Magic Machine

I suppose that if you added lots of delay nodes, it could also run like a British Rail system :roll_eyes:

9 Likes

I don't think Node-RED can run that slowly :slight_smile:

6 Likes

ARGH!

(Stupid me - again)

At least I posted the sub-flow way back near the start.

Today I was getting curious on how to get it working better, and I stuffed up.

Ok, I'll get the sub-flow I posted and stick it back in.

News flash:
All the links inside the subflow aren't there.

Anyone have an idea why that is?
Unless I am missing something.

I'm kinda stuck now because I did such a good job of fixing it until it broke I don't seem able to get the original sub-flow back.

Surely by now you are keeping regular backups of your flow file.
Was the bit you are looking for in the flow you posted earlier?

1 Like

It is no good keeping backups if when I re-import them, they are corrupt, as happened from the forum.

When I re-import it, there are no internal links.

Is this a bug?

Possibly, but if you just replace the whole flow file with your last backup then you will be good to go. Are you using the projects feature? If so then just checkout the previous version.

(Oh boy am I going to cop it for this, but.....)

This is what I see when I boot and use FF.
(Note: ALL those windows are FF.)
(Each window has anywhere from 1 to . . . . . 50? tabs.)

Going to NR ALONE, I have OVER 50 tabs on the NUC.

Backups. Yeah. One day.

I just know I'm going to regret asking... but what is FF.
I know what FNR stands for, I've called it that many times, but what is FF?

FireFox.

The hint is the top right corner of the second screen. Sorry: the other right (wink)

Activities Firefox Web Browser

See new thread about sub-flows. Using Chrome I am having problems with sub-flows using it too.

Chrome has probelms too

1 Like

is anyone here interested in train signals and how they work

YES! & What a great project!!

Years ago I did a LoRa RF & Node-Red POC for monitoring fixed block control equipment for UK rail network. It looks like Sydney in the process of moving from fixed block to moving block signaling.

Great explanation fixed block and moving block signaling
View from 50 sec to 3 min

// Some grossly simplified bits so from my old notes.

Fixed block systems use an electrical track circuit to detect when train is present or not. Original systems used an AC signal to a relay when a train was on the section of track it would short (shunt) and relay would change state to indicate when a block was occupied/not. When continuous tracks were introduced tuned frequencies replaced simple AC signal.

Communications-Based Train Control (CBTC) new systems use Radio (2.4gHz not WiFi) to communicate between central control system track-side equipment and train. Track-side transponders give exact location of a train when passes over it.

For those Brits interested one reason for late completion of Cross Rail is the (CBTC) system is split between Invensys & Siemens for track-side/Central control and Bombardier (on-train controls) looks like systems integration is done from scratch on each rail system! Due to late construction, testing has been delayed and Bugs!! found in both systems along with RF issues at Heathrow.

Lawrence

1 Like

Got a bit bored this afternoon so I knocked-up this demo flow. It has a finite state machine (FSM) for each of the 6 signals and an animated slider to mimic a train journey. To keep things simple there is only one buffer block (caution block) - you can obviously modify that by introducing additional blocks and signals.

BOD means Block Occupancy Detector.

Hope you find it useful.



The Node-RED flow is below as together with the screenshots it exceeded the 32,000 character limit.

Here's the NR-flow.

[{"id":"e6af7661.98a67","type":"inject","z":"7dd0692d.3c26f","name":"Clock Pulse","topic":"","payload":"1","payloadType":"num","repeat":"1","crontab":"","once":true,"onceDelay":"1","x":130,"y":200,"wires":[["f96a8d90.ddf9a","5598a61a.4b0218","82a2afd3.5536f8","322e947e.fe86cc","c3235ddb.872fb","eb6dd745.74aac8","3830eb14.bfe52c"]]},{"id":"bca42931.22a958","type":"ui_slider","z":"7dd0692d.3c26f","name":"","label":"Train","tooltip":"","group":"44ba51bf.ff26b","order":2,"width":"14","height":"1","passthru":true,"outs":"all","topic":"","min":0,"max":"500","step":"10","x":550,"y":200,"wires":[["46e70695.7297c8","379335cb.710c12","40b82f33.63d028","6fe4ada3.bdc7a4","147c6ec9.b34cb9","7c8dc833.268ac"]]},{"id":"3830eb14.bfe52c","type":"function","z":"7dd0692d.3c26f","name":"Check if \"running\"","func":"var status = flow.get(\"status\") || \"stopped\";\n\nif (status == \"running\") {\n    var distance=flow.get(\"distance\") || 0;\n    msg.payload = distance;\n\n    if (distance < 500) {\n        distance = distance + 10;\n        flow.set(\"distance\",distance);\n        return msg;\n    }\n    else {\n        flow.set(\"status\",\"stopped\");\n    }\n}","outputs":1,"noerr":0,"x":350,"y":200,"wires":[["bca42931.22a958"]]},{"id":"46e70695.7297c8","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-1","func":"if ((msg.payload > 20) && (msg.payload < 110)) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_1\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_1\",\"off\");\n    return msg;\n}","outputs":1,"noerr":0,"x":740,"y":100,"wires":[["30ed5c4b.be225c"]]},{"id":"c5a4b482.79a1f","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"24d134c4.309bfc","order":0,"width":"2","height":"2","passthru":false,"label":"Reset","tooltip":"","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"num","topic":"","x":130,"y":80,"wires":[["4801205a.c0f248"]]},{"id":"51bedd23.d1c9d4","type":"inject","z":"7dd0692d.3c26f","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":170,"y":120,"wires":[["4801205a.c0f248"]]},{"id":"4801205a.c0f248","type":"function","z":"7dd0692d.3c26f","name":"Set initail conditions","func":"flow.set(\"block1_fsm_state_register\",\"red\");\nflow.set(\"block2_fsm_state_register\",\"red\");\nflow.set(\"block3_fsm_state_register\",\"red\");\nflow.set(\"block4_fsm_state_register\",\"red\");\nflow.set(\"block5_fsm_state_register\",\"red\");\nflow.set(\"block6_fsm_state_register\",\"red\");\n\nflow.set(\"distance\",0);\nflow.set(\"status\",\"stopped\");\n\nmsg.payload = 0;\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":80,"wires":[["bca42931.22a958"]]},{"id":"1fc6e207.120f26","type":"ui_text","z":"7dd0692d.3c26f","group":"689d4556.e51cb4","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":520,"wires":[]},{"id":"461cfa31.a538d4","type":"ui_text","z":"7dd0692d.3c26f","group":"689d4556.e51cb4","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":480,"wires":[]},{"id":"72632ee.682d2d","type":"ui_text","z":"7dd0692d.3c26f","group":"689d4556.e51cb4","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":440,"wires":[]},{"id":"6480f9c6.cf1818","type":"ui_text","z":"7dd0692d.3c26f","group":"adb35923.fef558","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":760,"wires":[]},{"id":"d8a3d820.0bfbd","type":"ui_text","z":"7dd0692d.3c26f","group":"75a1505d.cf3df8","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":440,"wires":[]},{"id":"981c54c5.36a2e8","type":"ui_text","z":"7dd0692d.3c26f","group":"d303798b.f2b6b","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":600,"wires":[]},{"id":"ef698d0b.f03e68","type":"ui_text","z":"7dd0692d.3c26f","group":"2767fc53.8a4954","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":760,"wires":[]},{"id":"db873d6b.6ac3b","type":"ui_text","z":"7dd0692d.3c26f","group":"35fb7b16.134684","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":640,"wires":[]},{"id":"b7f2633e.8644a","type":"ui_text","z":"7dd0692d.3c26f","group":"75a1505d.cf3df8","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":480,"wires":[]},{"id":"94d277d7.9fa9c8","type":"ui_text","z":"7dd0692d.3c26f","group":"d303798b.f2b6b","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":640,"wires":[]},{"id":"f29c3bb9.88efb","type":"ui_text","z":"7dd0692d.3c26f","group":"2767fc53.8a4954","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":800,"wires":[]},{"id":"c14d64c.f085198","type":"ui_text","z":"7dd0692d.3c26f","group":"adb35923.fef558","order":2,"width":"2","height":"1","name":"Yellow","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":800,"wires":[]},{"id":"4141a06c.d85c","type":"ui_text","z":"7dd0692d.3c26f","group":"35fb7b16.134684","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":680,"wires":[]},{"id":"8cb6a9db.b2bdc8","type":"ui_text","z":"7dd0692d.3c26f","group":"adb35923.fef558","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":840,"wires":[]},{"id":"35f7087.cd7fe78","type":"ui_text","z":"7dd0692d.3c26f","group":"75a1505d.cf3df8","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":520,"wires":[]},{"id":"d0991cd0.5d77e8","type":"ui_text","z":"7dd0692d.3c26f","group":"d303798b.f2b6b","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":680,"wires":[]},{"id":"a3c35e53.6cd858","type":"ui_text","z":"7dd0692d.3c26f","group":"2767fc53.8a4954","order":1,"width":"2","height":"1","name":"Red","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":1130,"y":840,"wires":[]},{"id":"2b2fe5b3.2e0ca2","type":"ui_template","z":"7dd0692d.3c26f","group":"44ba51bf.ff26b","name":"Fix the width of the dashboard to 1000px","order":2,"width":0,"height":0,"format":"<style>\n.masonry-container {\n    width: 1000px;\n}\n</style>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":820,"y":40,"wires":[[]]},{"id":"30ed5c4b.be225c","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"689d4556.e51cb4","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-1","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_1","payloadType":"str","topic":"","x":930,"y":100,"wires":[[]]},{"id":"1699869c.7115d1","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"35fb7b16.134684","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-2","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_2","payloadType":"str","topic":"","x":930,"y":140,"wires":[[]]},{"id":"a2ca93c8.97cf78","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"adb35923.fef558","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-3","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_1","payloadType":"str","topic":"","x":930,"y":180,"wires":[[]]},{"id":"f3641b7e.57cae","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"2767fc53.8a4954","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-6","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_6","payloadType":"str","topic":"","x":930,"y":320,"wires":[[]]},{"id":"453d94d2.44cfc4","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"75a1505d.cf3df8","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-4","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_4","payloadType":"str","topic":"","x":930,"y":240,"wires":[[]]},{"id":"9a4c50fd.8035f8","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"d303798b.f2b6b","order":4,"width":"2","height":"1","passthru":false,"label":"BOD Blk-5","tooltip":"","color":"","bgcolor":"{{msg.background}}","icon":"","payload":"bod_blk_5","payloadType":"str","topic":"","x":930,"y":280,"wires":[[]]},{"id":"d0e0d730.7d789","type":"ui_button","z":"7dd0692d.3c26f","name":"","group":"24d134c4.309bfc","order":0,"width":"2","height":"2","passthru":false,"label":"Start-Stop","tooltip":"","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"num","topic":"","x":150,"y":40,"wires":[["850483db.dc1d8"]]},{"id":"850483db.dc1d8","type":"function","z":"7dd0692d.3c26f","name":"Toggle start-stop button","func":"var status = flow.get(\"status\") || \"stopped\";\n\nif (status == \"stopped\") {\n    status = \"running\";\n}\nelse {\n    status =\"stopped\";\n}\n\nflow.set(\"status\",status);\n","outputs":0,"noerr":0,"x":430,"y":40,"wires":[]},{"id":"379335cb.710c12","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-2","func":"if ((msg.payload > 100) && (msg.payload < 190)) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_2\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_2\",\"off\");\n    return msg;\n}\n","outputs":1,"noerr":0,"x":740,"y":140,"wires":[["1699869c.7115d1"]]},{"id":"f96a8d90.ddf9a","type":"function","z":"7dd0692d.3c26f","name":"block_1_fsm","func":"var fsm_state = flow.get(\"block1_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_1 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( {payload:\"yellow\"} );\n        }\n        else if ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"yellow\":\n        if ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"on\") ){\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"green\":\n        if ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"off\") ) {   \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if  ( (bod_blk_1 == \"off\") && (bod_blk_2 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if (bod_blk_1 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block1_fsm_state_register\", fsm_state);\n\n","outputs":1,"noerr":0,"x":150,"y":480,"wires":[["49640562.765e3c"]]},{"id":"49640562.765e3c","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":330,"y":480,"wires":[["72632ee.682d2d"],["461cfa31.a538d4"],["1fc6e207.120f26"]]},{"id":"40b82f33.63d028","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-3","func":"if ((msg.payload > 180) && (msg.payload < 290)) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_3\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_3\",\"off\");\n    return msg;\n}\n","outputs":1,"noerr":0,"x":740,"y":180,"wires":[["a2ca93c8.97cf78"]]},{"id":"6fe4ada3.bdc7a4","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-4","func":"if ((msg.payload > 280) && (msg.payload < 360)) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_4\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_4\",\"off\");\n    return msg;\n}\n","outputs":1,"noerr":0,"x":740,"y":240,"wires":[["453d94d2.44cfc4"]]},{"id":"147c6ec9.b34cb9","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-5","func":"if ((msg.payload > 350) && (msg.payload < 440)) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_5\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_5\",\"off\");\n    return msg;\n}\n","outputs":1,"noerr":0,"x":740,"y":280,"wires":[["9a4c50fd.8035f8"]]},{"id":"7c8dc833.268ac","type":"function","z":"7dd0692d.3c26f","name":"Check for Blk-6","func":"if (msg.payload > 430) {\n    msg.background = \"red\";\n    flow.set(\"bod_blk_6\",\"on\");\n    return msg;\n}\nelse {\n    msg.background = \"#097479\";\n    flow.set(\"bod_blk_6\",\"off\");\n    return msg;\n}\n","outputs":1,"noerr":0,"x":740,"y":320,"wires":[["f3641b7e.57cae"]]},{"id":"abb8d8db.ab8208","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":330,"y":640,"wires":[["996e0cb.8134bf"],["db873d6b.6ac3b"],["4141a06c.d85c"]]},{"id":"5598a61a.4b0218","type":"function","z":"7dd0692d.3c26f","name":"block_2_fsm","func":"var fsm_state = flow.get(\"block2_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_2 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( {payload:\"yellow\"} );\n        }\n        else if ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"yellow\":\n        if ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"on\") ){\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"green\":\n        if ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"off\") ) {   \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if  ( (bod_blk_2 == \"off\") && (bod_blk_3 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if (bod_blk_2 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block2_fsm_state_register\", fsm_state);\n\n","outputs":1,"noerr":0,"x":150,"y":640,"wires":[["abb8d8db.ab8208"]]},{"id":"996e0cb.8134bf","type":"ui_text","z":"7dd0692d.3c26f","group":"35fb7b16.134684","order":3,"width":"2","height":"1","name":"Green","label":"","format":"<font color={{msg.payload}} ><i class=\"fa fa-circle\" style=\"font-size:24px;\"></i></font>","layout":"col-center","x":490,"y":600,"wires":[]},{"id":"5ec436fa.73c06","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":330,"y":800,"wires":[["6480f9c6.cf1818"],["c14d64c.f085198"],["8cb6a9db.b2bdc8"]]},{"id":"82a2afd3.5536f8","type":"function","z":"7dd0692d.3c26f","name":"block_3_fsm","func":"var fsm_state = flow.get(\"block3_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_3 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( {payload:\"yellow\"} );\n        }\n        else if ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"yellow\":\n        if ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"on\") ){\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"green\":\n        if ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"off\") ) {   \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if  ( (bod_blk_3 == \"off\") && (bod_blk_4 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if (bod_blk_3 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block3_fsm_state_register\", fsm_state);\n\n","outputs":1,"noerr":0,"x":150,"y":800,"wires":[["5ec436fa.73c06"]]},{"id":"67c15f9.dfd772","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":970,"y":480,"wires":[["d8a3d820.0bfbd"],["b7f2633e.8644a"],["35f7087.cd7fe78"]]},{"id":"322e947e.fe86cc","type":"function","z":"7dd0692d.3c26f","name":"block_4_fsm","func":"var fsm_state = flow.get(\"block4_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_4 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( {payload:\"yellow\"} );\n        }\n        else if ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"yellow\":\n        if ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"on\") ){\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"green\":\n        if ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"off\") ) {   \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if  ( (bod_blk_4 == \"off\") && (bod_blk_5 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if (bod_blk_4 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block4_fsm_state_register\", fsm_state);\n","outputs":1,"noerr":0,"x":790,"y":480,"wires":[["67c15f9.dfd772"]]},{"id":"e2c24607.959458","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":970,"y":640,"wires":[["981c54c5.36a2e8"],["94d277d7.9fa9c8"],["d0991cd0.5d77e8"]]},{"id":"c3235ddb.872fb","type":"function","z":"7dd0692d.3c26f","name":"block_5_fsm","func":"var fsm_state = flow.get(\"block5_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_5 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( {payload:\"yellow\"} );\n        }\n        else if ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"yellow\":\n        if ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"on\") ){\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"off\") ) {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        break;\n       \n        case \"green\":\n        if ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"off\") ) { \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if  ( (bod_blk_5 == \"off\") && (bod_blk_6 == \"on\") ) {\n            fsm_state = \"yellow\";\n            node.status({text:\"State register = yellow\"});\n            node.send( [{payload:\"yellow\"}] );\n        }\n        else if (bod_blk_5 == \"on\") {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block5_fsm_state_register\", fsm_state);\n\n","outputs":1,"noerr":0,"x":790,"y":640,"wires":[["e2c24607.959458"]]},{"id":"ff29f5fb.afd138","type":"function","z":"7dd0692d.3c26f","name":"LED decoder","func":"if (msg.payload == \"red\") {\n    node.send( [{payload:\"grey\"},{payload: \"grey\"},{payload: \"red\"}] );\n}\nelse if (msg.payload == \"yellow\") {\n    node.send( [{payload:\"grey\"},{payload: \"yellow\"},{payload: \"grey\"}] );\n}\nelse if (msg.payload == \"green\") {\n    node.send( [{payload:\"green\"},{payload: \"grey\"},{payload: \"grey\"}] );\n}","outputs":3,"noerr":0,"x":970,"y":800,"wires":[["ef698d0b.f03e68"],["f29c3bb9.88efb"],["a3c35e53.6cd858"]]},{"id":"eb6dd745.74aac8","type":"function","z":"7dd0692d.3c26f","name":"block_6_fsm","func":"var fsm_state = flow.get(\"block6_fsm_state_register\") || \"red\";\n\nvar bod_blk_1 = flow.get(\"bod_blk_1\") || 1;\nvar bod_blk_2 = flow.get(\"bod_blk_2\") || 1;\nvar bod_blk_3 = flow.get(\"bod_blk_3\") || 1;\nvar bod_blk_4 = flow.get(\"bod_blk_4\") || 1;\nvar bod_blk_5 = flow.get(\"bod_blk_5\") || 1;\nvar bod_blk_6 = flow.get(\"bod_blk_6\") || 1;\n\nswitch (fsm_state)\n   {\n        case \"red\":\n        if (bod_blk_6 == \"on\") \n        {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( {payload:\"red\"} );\n        }\n        else if (bod_blk_6 == \"off\") \n        {\n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( {payload:\"green\"} );\n        }\n        break;\n       \n        case \"green\":\n        if (bod_blk_6 == \"off\")\n        {   \n            fsm_state = \"green\";\n            node.status({text:\"State register = green\"});\n            node.send( [{payload:\"green\"}] );\n        }\n        else if (bod_blk_6 == \"on\")\n        {\n            fsm_state = \"red\";\n            node.status({text:\"State register = red\"});\n            node.send( [{payload:\"red\"}] );\n        }\n        break;\n   }\n\nflow.set(\"block6_fsm_state_register\", fsm_state);\n\n","outputs":1,"noerr":0,"x":790,"y":800,"wires":[["ff29f5fb.afd138"]]},{"id":"44ba51bf.ff26b","type":"ui_group","z":"","name":"Simulated train journey","tab":"73fa038.3bc0ffc","order":8,"disp":true,"width":"14","collapse":false},{"id":"24d134c4.309bfc","type":"ui_group","z":"","name":"Sim Ctrl","tab":"73fa038.3bc0ffc","order":1,"disp":true,"width":"2","collapse":false},{"id":"689d4556.e51cb4","type":"ui_group","z":"","name":"Block 1","tab":"73fa038.3bc0ffc","order":2,"disp":true,"width":"2","collapse":false},{"id":"adb35923.fef558","type":"ui_group","z":"","name":"Block 3","tab":"73fa038.3bc0ffc","order":4,"disp":true,"width":"2","collapse":false},{"id":"75a1505d.cf3df8","type":"ui_group","z":"","name":"Block 4","tab":"73fa038.3bc0ffc","order":5,"disp":true,"width":"2","collapse":false},{"id":"d303798b.f2b6b","type":"ui_group","z":"","name":"Block 5","tab":"73fa038.3bc0ffc","order":6,"disp":true,"width":"2","collapse":false},{"id":"2767fc53.8a4954","type":"ui_group","z":"","name":"Block 6","tab":"73fa038.3bc0ffc","order":7,"disp":true,"width":"2","collapse":false},{"id":"35fb7b16.134684","type":"ui_group","z":"","name":"Block 2","tab":"73fa038.3bc0ffc","order":3,"disp":true,"width":"2","collapse":false},{"id":"73fa038.3bc0ffc","type":"ui_tab","z":"","name":"Block Signalling","icon":"dashboard","order":41,"disabled":false,"hidden":false}]

Nice.
(I've only just loaded it.)

You mentioned in the first post the fsm.

(I have it installed but never got into it)

Where in the flow it is?

I think you might be thinking of the node-red node called 'node-red-contrib-dsm'.

My flow doesn't use any of those nodes, I've coded the finite state machines using JavaScript in the six function nodes called 'block_X_fsm' (where X ranges from 1 to 6).

Hope you find the flow useful.

My original idea was to have a stationary train sitting on one of the blocks so when the moving train caught up with it, it would stop. I just ran out of time this afternoon - sorry.