The MainControl will decide when to signal the TrackControlSystem, The RailWayCrossingSystem the TunnelSignalLightSystem and the TrainControl. For this, it also needs a timer for being able to let the train wait for a number of seconds at a certain point of the track (End points or Railway stations).
The MainControl component is, like the name suggests, the main component that controls all actions of the Train System. It uses the IrSensorDecoder via the IIrSensorsDecoder (requires interface) to retrieve IR Sensor triggers to be able to decide what to control based on position of the train. The IrSensor triggers to HIGH when a train is detected. It triggers to LOW when the train is not detected anymore. Together with the selected track scenario the received IR Triggers determine how to control the other parts of the system. Each track scenario has its own state, and for each scenario, the trigger of the IrSensors could have a different meaning or has no meaning at all and can be seen as an trigger to ignore (e.g. when train cannot be at that sensor).
Within this design model, you can find examples of using functions to reuse logic. This way you can avoid duplication of logic. If the reusable logic changes, you only have to modify at one location.
The following picture shows a simulation sequence of the MainControl component for the (start of the) UpperLowerTrack1 scenario. A train is moving, and the simulated IR triggers follow the movement of the train.
As you can imagine, a lot of other scenarios could be simulated, including situations in which IR sensors gets triggered while no train is on that part of the track. A full model should be able to deal with this, the current model could be improved on this (will be done in future extensions when a second train will be introduced).
The TrackControl knows about the different track scenarios; it provides an interface (ITrackControl) to activate the correct switches.
The four track switches are controlled by the TrackControl; they can be switched to TrackA or TrackB. The output of a TrackSwitch will control a servo. The figure below shows a simulation of switching to lower track1, switching to upper track and switching to lower track 2. You can see that all switches are set to the correct TrackA or TrackB state.
This system shows the usage of multiple instances of the same component.
The railway crossing system takes care of controlling all parts of the railway crossing; the protection beam and the warning lights. The figure below shows the components of the RailWayCrossing system.
The figure below shows a simulation of the RailWayCrossing; it shows the initialization in which the warning lights and protection beam are deactivated. When a train is detected, the warning lights are activated. After a delay (triggered by timeout) the protection beam gets activated;
Now, when train is passed, the protection beam gets deactivated; After a delay (triggered by timeout), the warning lights are deactivated.
The TunnelSignalLight system is shown in the figure below.
First it initializes the system to the safe state in which green led will be active and red led is off.
When a Train is coming, the green led starts blinking; frequency of blinking is determined by timer and simulated by a few timeouts.
When the train is in the tunnel (SetTunnelStop), the red led is activated and blinking stops and green led switches off.
When train passed tunnel, the SetTunnelSafe is called and Green led is activated again (Red is switched off). The figure below shows a simulation of the TunnelSignalLight.
Using TrainControl you can control the Model Train by sending commands to the train using RF.
The TrainControl translates the ITrainControl interface into messages being sent using RF24. This object uses an external ‘helper’ component to make decisions based on the data. This ‘helper’ component implements the IRf24Helper interface; it has a method to check whether a messageId is the same or not;
The idea of this helper interface is simple. A message id can be the same or not; it either returns true or false; based on these possible results, the model checker will verify all possible situations (good and bad weather scenarios). The IRf24Helper interface will be implemented in an external component.
The TrainControl component has implemented a retry mechanism in case no acknowledge of the message is received; since the TrainControl also has the ability to switch of the power of the railway tracks, it can be used to reset the Arduino board in the model train by switching off its power. This is used as a last resort to try to recover communication to the train (sending a reset command would in this case most probably also fail).
The sequence diagram above shows a few attempts to send a message using RF24. After two timeouts, when no message acknowledge has been received, a power switch of/on retry mechanism is used. This should reset the receiving part (The train on the track that uses the power from the track and powers onboard Arduino with RF24 receiver). After power cycle, another SendMessage is send and a corresponding acknowledge is received this time.
The TrainControl design model also shows how to send different messages with different MessageIds and MessageData. It uses constants defined externally.
The TrainControl design model makes use of the blocking keyword. This is used to make the call blocking (will not return) until another event (in this case a messageAck) is received that will result in a reply to the blocking call; You need to use it when you go from synchronous to a‐synchronous communication like done in this model.
The receiver part of the RF24 messages is a model Train that uses power of the track to power its onboard Arduino with RF Sender/receiver. The System is shown below and has the IRF24Node as input (provides).
The TrainRf24Node translates/decodes the RF24 messages into usable commands for the ModelTrainControl which controls the motor of the train and its front and back lights.
The TrainRf24Node again uses a ‘helper’ component for decoding the messages based on the data received. The helpers is used to compare message_id’s and compare message_data.
The TrainRf24Node uses the ITrainControl interface; so this can serve as an example for remoting the ITrainControl interface using RF24 (or another a‐synchronous communication protocol): ITrainControl ⇒ RF24 messages ⇒ ITrainControl. The ModelTrainControl is able to use the ITrainLightsControl interface to control the lights of the train. (Rf24 message ⇒ ITrainLightsControl)
The output of the ModelTrainControl is the motor control (requires IMotorControl) and two digital outputs (requires two IDigitalOutput) for the front and back light.