JMRI is a free software application that runs on Windows, Linux or a MAC that can perform a multitude of functions. It makes programming complex DCC decoders much easier. It also is used for dispatching, signaling, switching, route control, train control, interfacing to WiFi controls and cell phone throttles, and more. A number of these options need to know where locos and cars are around the layout. That is, JMRI needs to “sense” where things are. Years ago I might use a thin metal contact pushed to closure by a loco or car wheel. That contact or switch closure might have lighted a panel indicator or even turned on a relay to throw a switch. JMRI can do a hundred things more interesting than that.
This project will show you how to connect up to 68 sensors to JMRI with a single Arduino, and what to do to set up your sensors in JMRI. From there, you are on your own as far as this article goes. It will allow you to choose any kind of sensor that will pull a signal wire to ground (including the switch closure of old) and route it into a JMRI sensor table with minimal load/disturbance to JMRI. It will also automatically initialize all the sensors you have set up, upon connection to JMRI. The hardware connection will be made with most any off-the-shelf Arduino board (unmodified). These will connect via any USB port, to your computer running JMRI. This will be the same USB serial port you use to load the Arduino board. I’ve written several times before about installing and loading Arduino software: in MRH December 2016, A modeler’s introduction to the Arduino http://mrhpub.com/2016-12-dec/online/ and here: in MRH March 2017, DCC projects using the Arduino http://mrhpub.com/2017-03-mar/online/html5/
I’ll also show how to set up the sensor table in JMRI which will keep track of everything for you. If you need more info about JMRI, start here: http://jmri.sourceforge.net/help/en/webtoc.shtml
If you need some more info about Arduinos and sensors, look here: https://www.arduino.cc/en/Tutorial/HomePage-0008 All code for the Arduino and for JMRI is available here: JMRI_Channels_Rev2.zip
Build Details
This “Sensor Channel” is built with an Arduino Mega2560 controller and an optional Mega Sensor shield, for about $12-16 total depending on where you purchase them. Here is what I used:
MEGA 2560 R3 ATMEGA16U2 ATMEGA2560-16AU Board + USB Cable For Arduino https://www.ebay.com/itm/253733606559 11.95 (you can get a Chinese knock-off for $7)
MEGA2560 ATmega2560-16AU Sensor Shield V2.0
Arduino Mega2560
Arduino Mega2560 Sensor Shield
The Arduino Mega2560 controller is loaded exactly like the other Aduino’s I described in the December 2016 issue of MRH A modeler’s introduction to the Arduino http://mrhpub.com/2016-12-dec/online/
With exactly the same free tools that can be downloaded here: https://www.arduino.cc/en/Main/Software
The sensor shield board literally plugs into the top of the Mega2560 board, and has two screw terminals where you can connect a 5 Volt power supply to power the assembly and even the attached sensors. The shield board makes attaching your sensors easy. Each sensor (and its corresponding signal (S) pin) is numbered on the board from 2-53, and then from A0-A15 (corresponding to sensors 54-69). Pins 0 and 1 are taken for USB communication. Each numbered connection on the sensor shield provides a group of 3 pins with the sensor connection (S), a+5 Volt pin (V), and a ground (negative side connection G). Most sensors that are available will act as a switch, connecting the S pin to the G pin. You can use a switch or metal contacts on a relay or tortoise switch motor as a JMRI sensor by connecting the switch contacts to S and G yourself There are jumper wires already made of varying lengths available from many sources including Pololu.com and ebay.com that will slide onto these pins directly. With a little care, you can also solder connections too.
Jumpers from Pololu.com
Sensors can take on many forms. As said previously all the ones that are of interest here set their sensor output to ground when activated. Some are shown below, but there are lots more available. You can get an idea of the many available here: https://randomnerdtutorials.com/21-arduino-modules-you-can-buy-for-less-than-2/
IR Detector.jpg Infrared PIR (Human) sensor
Track Contacts as sensor Toggle Switch Push Button
The Arduino Mega2560 will use all 68 pins as digital sensor inputs. An Arduino UNO, a Pro Mini, and a Nano will have 18 pins available (Digital pins 2-13, and A0-A5 or Digital pins 14-19) for sensors. There are two different pre-configured sketches to load either a Mega or one of the smaller boards. All files can be found here: http://mrhpub.com/files/users/geoffbfiles/JMRI_Channels_Rev2.zip
Both sketches assume all pins are scanned as sensors and will match JMRI USER-DEFINED sensor names from AR:2-69 or AR:2-19 . The AR designation is completely arbitrary, but if you want to change it you will have to edit theJMRI Sensor_Scan Python Script provided. When you download the Arduino sketch into your board, you must make note of the Serial Port on your computer used for communication between the Arduino IDE edior and your board. Your should always plug your Arduino USB cable into the same USB port/socket, so you will get your operating system to assign the same USB port. If your switch computers, it is likely the USB port number will be different. This is important because you must make sure the JMRI Sensor_Scan Python Script is edited (line 82: a = SerialSensorMux("COM5")
with the correct COM port number.
Load the appropriate Arduino sketch onto your favorite board, attach a sensor shield if needed, and leave the board connected to your computer that you will run JMRI. Now before you start JMRI you must either have just powered on your board, or simply hit the reset switch on your board.
Open JMRI and open your sensor table, which may only have one entry for ISCLOCKRUNNING. Go to the bottom of the Sensor table window and click Add…
The System Connection: can be set for either internal or hardware addresses. I usually select “Internal” from the drop down pick.
In the “Hardware Address” space simply put “0” (zero) this can be most anything you want within limits
In the “User Name” space simply put “AR”
Click the box for Add a sequential range
For the Number of items enter 69 for a Mega2560 and 19 for an UNO, Pro Mini, or a Nano
Then click on Create
Go back to your sensor table and click on the “User Name” label at the top of the column to get a clean sort by all the user names you just created
Now delete the entry for “AR” and “AR:1” since we will not be using them. You should now have 68 sensors left in the table with user names AR:2 through AR:68. These will be initialized by your mega at start up. Last save your work as a panel by using Panels-> Save Panels… and name and save for later.
Now locate when you unzipped the Scan_Sensors.py file you edited with the correct COM port. From the JMRI menu go to Panels -> Run Script and find your up to date Scan_Sensors.py file, but before you click on Open make sure you reset the Arduino Mega board (with the push button). Run the script and you should see all your sensor go from “Unknown” to either Inactive or Active depending on what you connected to each pin (remember connecting a digital signal pin (S) to ground (G or GND) will set the sensor active. If for some reason you use sensors that are “Active HIGH” that is when they sense something they go HIGH and are normally LOW, then in line 18 of the Arduino sketch change: #define Sensors_Active_Low 1
To
#define Sensors_Active_Low 0
How This Works
Many Arduinos have a serial line available for general use. It is the same serial port used to load and setup the board. Once configured thee same serial port is available for communication back to your computer. There are actually many components internal to JMRI, and JMRI provides access to its internal structure via "scripts" wrttten in another language called "Python" along with an offshoot called "jython" for Java Python. These scripts allow modelers to add additional capabilities to JMRI without developing a major interface to JMRI like Digitrax, CMRI, or DCC++. The Arduino wakes up on power on to wait for a set of characters from the JMRI script to initiate communications. It is likely that if both are powered on simultaneously, the Arduino will sit waiting for JMRI to start. When the Sensor_Scan.py JMRI script starts it sends the initialization message to the Arduino, when then sets off to update every sensor it is responsible for (that is all valid pins it is configured for). The Arduino then sends a sensor update message in 2 bytes at 19200 baud to JMRI which then updates the appropriate sensor, matching the sensor number received from the Arduino with the user defined name like AR:54. User defined names can be applied to either internal or system hardware numbered sensors -- it doesn't matter. The Sensor_Scan script is robust enough to handle undefined sensor names on the JMRI end, by printing a message on the script output window.
Additional JMRI Notes
Adding buttons to run scripts is pretty easy. Once you open JMRI PanelPro,
from the menu bar click Edit-> Preferences... a Preferences window will open.
Click Start Up then at the window bottom click Add then Add script to button...
Give the button a name (this will be the text on the button) and browse to where
you put the script you want to want to run when you click the button and click OK
If you saved the sate of your panel, you can also click Add-> Open File... and have JMRI open your panel
file at startup
You can also click Add button to main window... to have buttons to open tables, script output windows,
turn on Power, etc.
All of these same actions can be set up to run at power up by selecting Add -> Perform action... in a similar manner
Once you have set all these up, make sure you order the list of start up actions, by selecting an item in
the list (single click) and clicking Move Up or Down at the window bottom.
Once you are done click save on the lower left of the window, and it will ask if you want to restart. When
you restart JMRI it will come up with all the buttons placed in the entry order in the table,
and all the actions you specified to be done upon JMRI startup. Any or all of these can be removed
by selecting the action line and using the Remove button on the lower right of the window.
Before you start JMRI power on the Arduino channel, or hit the reset button on the Arduino.
There is a script called SensorSerialClose.py in the zip file. If you run this
it forcibly closes the serial port it is set up for. If the Sensor_Scan.py script is running,
it has the side effect of terminating that script. If you terminated the Sensor_Scan.py
script via the Kill button in the Thread Monitor window for any reason, JMRI would leave open
the COM port to the Arduino, preventing you from re-running the Sensor_Scan.py successfully.
So running SensorSerialClose.py will close the port and allow you to 1. Restart the Arduino via button push and 2. Then restart the Sensor_Scan script successfully.
The Sensor_Scan.py and the SensorSerialClose.py scripts should both refer to the same COM port.
You can copy and rename these 2 scripts for each COM port channel you create. I should point out that you can have multiple Sensor channels operating at the same time via different serial ports. In the Arduino sketches you will find info on how to set the range of sensor numbers that each channel can be assigned. In order to run multiple sensor channels you will need to make each sensorscan script independent of each other. You will need to edit and copy each script for each COM port and change the following lines:
line 17: global extporta # the name extporta must be unique for each com port
line 22: self.port = extporta # same as above
line 23: extporta = self.port # same as above
line 82: a = SerialSensorMux("COM8") # This COMx MUST correspond to a specific Arduino channel
line 85: a.setName("SerialSensorMux8 script") # Make this a unique name to minimize confusion
For some reason, I could not use export8, export9, etc. These had to be ending with an alphabetic character not a number, like exporta, exportb, exportc, ...
Last Note: There is a "feature" built into the sensorscan script: if it reads Sensor Number 1 as "1" it will terminate the sensorscan scrpt in JMRI. Normally pin 1 (hence sensor 1) is NOT used for data input on the Arduino. If you change the pin mapping beware of this built in termination facility. If you don't want it, you can delete lines 55-60 in the script.
Unfortunately, this does not tell you how to use sensors in JMRI. In the video I provided you can see how 2 sensors are used to operate a back and forth simple shuttle engine (you could use it for a trolley or MOW car too). This is a very simple example, but now you can have lots of sensors with which to be inventive. In the video it demonstrates how you can set up JMRI to automatically load up your sensor channel(s) at JMRI start. … and yes you can operate as many sensor channels has you have USB serial ports, and in MS Windows, that is a bunch!
Have fun! Best regards,
Geoff Bunza