LDR_Signals3_Class
Header File: LDR_Signals3_Class.h
Constructor: LDR_Signals3_Class( int,int,int,int)
sensor, red, amber and green pins
Public Methods begin( polarity)
argument determines polarity of signals
handle_signals( )
Signals follow sensor -red then red-amber-green sequence
train_over_sensor( )
Returns "1" for the train over the sensor
control_signals(int sig)
sig = 1: Sets signals red.
sig = 0: Signals go to green via red-amber-green sequence.
Abstract/Summary: This HTML page/project will develop a class/library that will detect the presence of a model train and set a signal RED. When the train departs the signal will go through a RED-AMBER-GREEN sequence. This page inherits LDR_Sensor_Class and Signals3_Class
Possible Audience: Model railway enthusiasts who wish to develop code to detect a model train and operate signals and programmers who would like examples of inheritance in C++. Note for both groups some experience in C++ will be necessary.
Keywords: Arduino NANO, Arduino IDE, LDR Sensor, LED, C++, Inheritance, Multiple Inheritance, Scope Resolution Operator
Required Components: Page tested using Arduino NANO but any microcontroller may be used. LDR sensor, RED,AMBER,GREEN Leds for testing.
Required Software (Library Files): LDR_Sensor_Class, Signals3_Class.
Previous projects have
(i) monitored a model train using a LDR (Light Detecting Resistor), and
(ii) controlled a set of signals that turn RED immediately a train is detected and move through a RED-AMBER-GREEN sequence when the train departs.
Those projects developed two C++ Classes or libraries.
1. LDR_Sensor_Class: That contains a public method/function train_over_sensor( ) that returns true when a train was detected. An important consideration here is that there is a 1 second filter to try and avoid "false" departures when the train couplings were above the LDR sensor. This will imply a 1 second delay before train_over_sensor( ) returns false after a train has actually departed.
2. Signals3_Class: This class controls a RED-AMBER_GREEN or 3-aspect signal. This class contains a method control_signals(sen) that sets the signals RED when its argument sen is true indicating a train is present. When a train passes, after 5 seconds the signals turn AMBER and then after a further 5 seconds they return to GREEN.
This page will develop a class LDR_Signals3_Class that will inherint both the LDR_Sensor_Class and the Signals3_Class. The design can handle both negative and positive signals as illustrated in the circuit.
Note: This is a "fun" flashing light project for a model train. Real lights would sense multiple sensors. When a train reaches the first sensor the signal would turn RED, it would not turn AMBER until the train reached a second block of track and GREEN when it reached a third block. This is the subject of other projects.
Note the Signals3_Class is for RED-AMBER-GREEN signals. For RED-GREEN signals use Signals2_Class.
The Signals3_Class maybe programmed to handle external logic that generates the AMBER signal
Signals2_Class maybe programmed to handle an external NOT gate to generate the GREEN from the RED.
Both classes may be programmed to change the timing of the RED-(AMBER)-GREEN sequence.
This page uses the LDR_Sensor_Class. This may be replaced with the IR_Sensor_Class.
Both classes may be programmed to change the timing of the 1 second filter.
The project will be developed using the Arduino IDE.
1. Create a new project:
(i) In the IDE create a new file - give it the label LDR_Signals3_Class. The IDE will give the file the extension *.ino
(ii) In the IDE use the inverted triangle towards the top right of the window to create two new tabs/files: Give them the labels LDR_Signals3_Class.cpp and LDR_Signals3_Class.h. Note they must have the same label but extensions *.cpp and *.h
2. If libraries LDR_Sensor_Class and Signals3_Class are not in list of contributed libraries:
(i) Open both LDR_Sensor_Class and Signals3_Class projects
(ii) Copy and paste supplied code.
(iii) Compile/Verify to check for any embedded formatting characters.
(iv) Use program such as Windows explorer to create *.zip file of *.cpp and *.h files
(v) In Arduino IDE use sketch -->Add Library --> Add .zip library and select files to add to your contributed libraries
3. Include LDR_Sensor_Class and Signals3_Class header files in the new project
i.e. In LDR_Signals3_Class.h use sketch -->Add Library -->and select LDR_Sensor_Class and Signals3_Class from your contributed libraries.
4. Add the following wrapping to the header file LDR_Signals3_Class.h to ensure it is only ever included once.
A major thrust of this project is to demonstrate inheritance. The following definition may be added to the header file:
The header has now defined a type class LDR_Signals_Class that inherits the LDR_Sensor_Class and the Signals3_Class. The class will have a constructor that expects the pins sensor, red, amber and green.
The next step in the program development is to spell out the class in the implementation (*.cpp) file. As illustrated below the constructor has 4 arguments: the sensor (pin), the red (pin), the amber (pin) and the green (pin). These are broken down to those associated with the LDR_Sensor_Class and the Signals3_Class.
As part of the constructor private variables are assigned to the arguments.
This code is the *.ino file and defines how the library under development might be used ( or tested). A possible starting point will be:
In the code an object or instance of the class LDR_Signals3_Class is created. The sensor will be attached to pin A0, the red signal to pin 5, the amber pin 4 and green pin 3. Note A0 is a digital pin with analogue capabilities so Arduino have chosen to label it as an analog pin. In this project it will be used as a digital input.
The next step is to initialise the design. This will involve a method train_control.begin(polarity). This should be added to the three files:
begin( ) will initialise all the input-output used by the two inherited classes. It could do other actions but apart from using the argument to select the polarity of the signals being used all other details are hidden.
In the implementation file the begin is separated into two (i) the begin( ) for the sensor and (ii) the begin( ) for the signals. Since the label "begin" is not unique the scope resolution operator :: is used to distinguish which class the begin( ) refers to. The argument polarity goes with the begin for the signals.
To complete begin( ) must be defined in the header file.
The code at this point should compile and all signals/leds should be on.
Note if the design uses a common pull up resistor, due to differences in the Leds causing current "hogging" the brightness can vary. One led may even appear to be off.
he signals. There are three possibilities:
1. Combine these two methods into one public method. Assume the label handle_signals( ).
2. Make these two methods available for this new class. This has the advantage that code can be inserted between the sensor and the signal to perform other actions.
3. Include both.
Including a public method handle_signals( ) results in the client/application file being very simple.
All the implementation details will be in the *.cpp file LDR_Signals3_Class plus the implementation files of all the inherited libraries. None of these will be visible to the client/end user.
Basically the method uses the train_over_sensor as the argument for the signal_control method. In both methods the source of the method is spelt out using the scope resolution operator for the respective classes.
handle_signals( ) will need to be defined in the header file. ie
These two methods were part of the original classes. They can be made visible to the client/end user. Strictly these are "new" methods that perform exactly the same operations as the original methods and have been given the same label. Users who have used "train_over_sensor" and "signal_control" in previous programs can use it again with the LDR_Signals3_Class. These two "new" methods have to be defined as part of the header file:
In the implementation file the code becomes:
Note this code is basically saying the two methods defined in this class are the same as the methods of the inherited classes. In all cases the label is qualified with the scope resolution operator ::.
The client will use the code as follows:
Testing verified the operation. As given the program will work for positive and negative signals.
Readers who are interested can replace the LDR with IR sensors.
The Signals3_Class can be replaced with Signals2_Class (RED and GREEN signals)
The Signals3_Class may be overloaded to account for external logic generating the AMBER signal.
The Signal2_Class may be overloaded for a NOT gate generating the GREEN signal from the RED
The LDR_Sensor_Class can be overloaded to give different filter times. (Default 1 second)
The signal_control method may be overloaded to give different delay times in the RED-AMBER-GREEN sequence. Currently 5 seconds + 5 seconds.