Preliminary design for my Arduino-based CMRI node

With the turnout controller nearly done, I started thinkign about my CMRI node design. Like the turnout controller, prototyping is being done using Arduinos, but the final product will be built using bare Atmel ATMegas328P chips since the in use boards don’t need things like extra voltage regulators, USB ports, or unused pins.

To get enough digital pins, I am using Microchip MCP23S17 port expanders. These communicate to the Arduino with SPI, and each one has a pair of 8 bit ports. My basic node will have 5 of these (they are less than $1 each!) for 64 output ports for signal LEDs and turnout control, and 16 input ports for block detectors and switch position feedback (not sure if I am going to do that). That should cover any interlocking I can think of, but just in case I will lay the boards out with a space for an extra chip each on the input chain and output chain (simple code change to add the extra bits - or leave off a chip or two when not needed).

Most implementations (other than Bruce Chubb’s SMINI and SUSIC boards) leave the CMRI node address selection in code, so you have to change and recompile the sketch for each node. Since all I/O on my board comes from the 23S17’s, I have plenty of pins to put in jumpers or a DIP switch to set the address in hardware. So far I have the following pin arrangements:

A0-A5 for the address selection, which allows 64 of these nodes. I looked at my prelimiary track plan and it looks like I will need no more than 1/4 that number at most.

D13 for the SPI SCK clock line

D12 for the SPI MISO line - data from the 23S17 to the Arduino

D11 for the SPI MOSI line - data from the Arduino to the 23S17

D10 for the slave select line for the output bank

D9 for the slave select line for the input bank

(note on the last two, the 23S17 has 3 address pins of its own, which allows up to 8 of them on one SPI line, or the 2317 which uses I2C can do the same). The library for the 23A17 allow

Keep up your Arduino information coming Randy. I for one really appreciate any and all Arduino input. [tup] [tup]

I have a working 14 block signal system using single light three color H5 signal heads driven with an Arduino MEGA as well as three 14 port Arduino UNOs programmed as Random Lighting controllers for three houses.

I also have my remote 180° panable Q5 camera on a depressed flat car working, it uses a pair of Arduino Nanos with Blue Tooth for servo control. It would be nice if I could find a Q5 camera that works right.

I’m working on using Nanos for controlling all kinds of automation, figures, vehicle lighting and operating doors.

If my health holds up I plan on replacing my turnout machines with the SG90 servos driven by Arduino.

I haven’t been successful using an Arduino as a step

I haven’t been successful using an Arduino as a stepper motor controller for operating a wig-wag crossing signal. I need help with the programming, I haven’t been able to stop the swinging pendulum (30°-0-30°) straight down.

Mel

Modeling the early to mid 1950s SP in HO scale since 1951

My Model Railroad
http://melvineperry.blogspot.com/

Bakersfield, California

I’m beginning to realize that aging is not for wimps.

Mel,

I beleive but not sure you can find may be an answer on the following blog for step by step motor contol by Arduino.

In the case of not, you could pr

I’ve tried emailing him a couple of times and didn’t get any response, same thing with Bruce Kingsley.

Thanks for your input Marc.

Mel

Modeling the early to mid 1950s SP in HO scale since 1951

could you summarize what CMRI defines? I assume it’s rs-485 based, so what is the packet structure/size?

is each node fixed? Have you considered making the number of inputs/outputs configurable at startup through a configuratoin command?

are you dedicating 5 inputs for address?

you could use optional pull-up/pull-downs on 5 of the outputs that are read at start up to determine the address before programming the I/O pins as outputs

another alternative is to program the address in the atmel EEPROM

can you explain the purpose of these?

can explain this more? why divide the inputs and outputs?

I assume there are 16-bit transmitted to/from the device during each interval. The master (arduinoe) sends an output bit while the salve (MCP) sends the corresponding input.

It’s been a while since I worked on I2c. Doesn’t it precede data with an address. I see the 23S17 uses a !CS.

WOW and I thought Latin was hard to learn [:S]. you guys are on a whole different level!

Mel - I would think the key would be to count the steps and hope the motor you are using has good repeatability. Another way would be to use a servo, you’d have to run linkage up the post but you could definitely stop it facing the right way.

–Randy

Thanks Randy

I haven’t dinked around with that sketch in several months and I can’t remember where I left off. When I saw Bruce’s Wig-Wag I wanted one, actually several. Bruce used some 4mm diameter 2 phase 5 volt 4 wire stepper motors. I bought a sack full off eBay along with a matching driver board. As I remember it didn’t take much to get it to swing 60°. I’m still interested in getting one going but frustration got the best of me.

I had similar problems with my signal system but conquered it by simply using a truth table. Super simple and easy to do once I got rid of a sample sketch of the Internet.

Inline replies…

[quote user=“gregc”]

is each node fixed? Have you considered making the number of inputs/outputs configurable at startup through a configuratoin command?

The CMRI protocol does provide for a configure packet but my goal was to simplify it and used fixed packet sizes - any unused bits would juet be 0, or 1, whichever. My master computer program (or anyone’s, really) needs to know what devices use what bits on what node - ie, it needs to be programmed such that Signal East 5 is bits 0,1, and 2 of byte 3 on node 6. Rather than customize each node’s definition and have the corresponding code to build the transmission strings of different sizes, I was planning to just always send 64 bits, and the node to always send 16. Even if the node only drives a simple passing siding with 20 LEDs (3+2 on points side, 2 head dwarf on exit to siding, 3 head on main side, x2) , 2 turnouts, 2 locks, and 6 detectors (main in, OS section, siding between turnouts, main between turnouts, other OS section, and other main). My layout will be double tracked so every OS section will have more outputs needed. This is all subject to change, but my main goal was simplification.

thanks for the reference. Not sure this is exactly C/MRI

they describe an RS-422 inteface which is 4-wire, duplex transmission in both directions. They show nodes wired in a daisy chain, so devices must re-transmit packets not intended for them to the next device, in both directions.

You mention using RS-485, which is half-duplex, and I believe more common. Every device sits on the bus and no retransmission is required

Their packet size appears dependent on the reception of an end-of-transmission (ETX) byte. This is why they use a data link escape (DLE) byte, so that data with the same value of ETX can be sent. Adding a packet size byte to the header might simplify things. Not sure about synchronization.

they have 4 types of packets: initialization, poll, transmit and read.

I think CMRInet is a bit complicated for the things being discussed and based on my understanding of the Pacific Southern control system. It’s intended to simplify wiring to obtain state that is constantly in flux which is different than receiving infrequent commands from a device such as a DCC handheld.

Sounds like you’re borrowing ideas from it, not implementing it exactly. Do you intend to have the slaves sends responses only when its input state changes? If so, what happens if the response packet is corrupted?

[quote user=“rrinker”]
The CMRI protocol does provide for a c

Yes, Bruce uses 4 wires for the connection - but it’s still half duplex RS485. The node and master never transmit and receive at the same time. It’s all polled, there is no “input changed, so send a packet to the master” mechanism at all. So there are no collision issues. If you look on the actual hardware, like the SUSIC, SMINI, or cpNode, the TX in and TX out on the boards is tied together, as ire the RX In and RX Out pins. So TX from the master is connected to the RX of all slaves, and the TX of all slaves is connected to the RX of the master.

Any varying transmissioon size must be managed by the master - there is no parameter in the protocol for total packet size. All you have is the start (STX), an address, a command, the data bytes, and an end (ETX). It’s actually ridiculously simple - look at the source for either the CMRI Arduino library, or the cpNode. All I’m really doing is dropping the Initialization message since my sketch will hard code the number of input and output ports on the node. Each Transmit from the host will send 8 bytes in the data portion, even if the particular node only has 5 bytes worth connected to hardware. When polled, the node will send a 2 bytes, even if there are only 8 input devices attached. The master program has to know the number and location of the bits for a given device regardless if there is a fixed packet size or the packet size varies per node. I’m thinking along the lines of a multidimensional array in the master to store each device. 4 dimensions, in fact - one for the node address, one for the byte, one for the starting bit position, and one for the number of bits. So if Signal East 4 is a standard 3 LED signal attached to the the first 3 bits second port of node 3, it’s value might be something like 3,1,0,3 meaning node 3, second byte, bit 0, for 3 bits. The start bit position and number of bits is used directly to extract the values for a specific object.

Other than not using an I

my understanding is that 4-wire RS-422 can be used half-duplex but separate wires are used for transmission in each direction. RS-485 has only 2-wires and transmission in both directions uses the same wires.

RS-422 and RS-485 line interfaces are different. Looks like C/MRI and CMRInet require RS_422.

in your original post you identify an I/O (D2) to be used for the RS-485 transmit enable

are you going use the data link escape when sending date bytes that have the same values as SYN, STX or ETX, or are you not going to worry about synchronization?

It’s not clear if polling only reports inputs that have changed or if a separate msg is sent for each group of input bits that have changed.

why not just send 8 bytes back? Is bandwidth a concern? is each node sequentially updated and polled?

Is the future benefit of being CMRInet compatble that you can possibly use complient boards in the future? But such board would require RS-422

I assure you, it is multi-drop RS485. The nodes are all in parallel along the transmision line. There is no retransmission from node to node to pass the data.

See here:

https://cdn.shopify.com/s/files/1/0947/9088/files/CHG04_SMINI.pdf?4186001288561530172

This is the information (including schematic and parts list) for the SMINI. The main reason for the seperate receive and transmit lines is, as described by Bruce Chubb, to make it easier to debug. One pin of the micro is used to enable the transmit on the serial driver chip of the node that needs to respond to a poll request. All others are held tri-stated.

If you look at the cpNode, they do it differently. They don;t use a controlled pin for TX Enable, they built in what they call AutoRTS using a 555 timer to periodically assert the transmit enable on the MAX489 they use for interface. Schematic here:

http://www.modelrailroadcontrolsystems.com/content/cpNode_Schematic_v20.pdf

Note they use a 14 pin MAX489 full duiplex chip while the Chubb design uses a pair of MAX487 half duplex chips. Also you can see how the serial lines connect through the pair of connectors on each board. You wire them point to point, one board to the next, but the topology is a multi-drop bus. The tap is on the board so you don’t have to rig up feeder drops off the signal bus.

Yes, I will still use DLE, you have to, to handle cases where the data happens to match the STX or ETX. SYN is not escaped, the SYN serves miostly as a spacer in the data stream, the code doesn’t look for it, only the STX to start a data stream, so an in-stream SYN wouldn’t throw the processing loop off like an STX or ETX would.

As for the packet sizes - fromt he host tot he node I would send 8 bytes, that’s

still confused about RS-422 vs. 485. That can wait

Chubb obviously had other applications in mind. Again, what is the benefit of implementing C/MRI instead of just developing you’re own apporoach?

for this type of application, receiving updates from the nodes is critical. The master knows when outputs need to change, but it doesn’t know when inputs change. It doesn’t need to send a TX message, but what if there’s a transmission error. So why not just transmit an update which serves as a poll?

A minimum packet is 6 bytes. A poll requires 6 bytes. Instead of a TX packet (14 bytes), a Poll (6) and a response (8) for each node, total 28 bytes, a TX + response is only 22 bytes and eliminates processing (both generating and recognizing) of the poll packets.

at a modest 9600 bps (1 byte / ~msec) there can be ~35 (with poll) and ~45 (w/o poll) nodes serviced every second.

I’m lazy? Since someone has already done it, I don’t have to design a protocol and the implementation both in C++ on the Arduino and VB or VC# for the PC side.

I actually was initially considering using Loconet, as there is an Arduino library for that as well, since I will already have a Loconet connecting my DCC system. There is even a .Net library, Percli’s RR-Automation, so I wouldn’t be stuck with JMRI (I despise Java as a programming language). However, compared to CMRI, the Loconet protocol is a hundred times more complex. I also considered Ethernet and also various wireless systems, but the last thing I think I need is MORE stuff trying to share the 2.4GHz spectrum, plus there’s still the issue of complexity of the protocol.

Yes, Chubb had many other uses envisioned for CMRI, many of them are int he original 80’s series in MR, like Computer Block Control and Computer Cab Control (this being pre-DCC, the object was to let the computer handle all the block toggle flipping so you could just drive the train). But even those boards were controlled via the exact same protocol.

I think you’re missing part of how it works. It’s designed to run with the nodes being purely slaves, answering only when polled. There’s no requirements for the conversation to be TX, Poll, Receive. In fact, the more typical way it works is that the nodes are polled until a node requires an output update, in which case a TX is done. Even if sequential - things are still read plenty fast enough. The inputs are latching, so even a pushbutton press won’t be missed. Even if there is an error on one read, with multiple reads per second, a good value will get through more than fast enough to properly update signals and so forth. There are lots of VERY large layouts using CMRI with no lag issues or bad data.

–Randy

ok, you’re using existing libraries for both you master (PC) and nodes

i believe i understand. that’s why i said it’s intended for more sophisticated applications

you didn’t respond to this. Do the 2 bytes contain all input bits or coding for only the bits that have changed?

For both directions, all bits are sent. Trying to do just changed bits makes for an unecessarily complicated decode process - you’d need to send a lot more than 2 bytes in order to send just the 4 bits that changed since the last poll. By just sending the whole thing every time, it’s a simple operation to shift them to the 23S17’s, or read from the input ones. On the output side, SE(4)'s red LED will always be bit 5 of the 4th byte. On the input side, Block 2 East detector will always be bit 2 of the second byte. If this were all compressed down to only send that one bit if the only thing that happened was that block became occupied, there would have to be a bunch more data to somehow encode that. Not worth the effort, in increased packet size or processing at either end.

If you look at the code for cpNode, look at the bottom for their Loop() function. There’s just 2 lines: Check CMRI (well, the serial buffer) to see if there is any data, and then a call to their function which reads all the input ports and makes the byte stream. Under the CMRI processing, if the message detected is a poll, it does one more read of the input ports, then builds the R message (adds the header infor, inserts DLEs where needed, puts the ETX on the end) and send it. Super simple.

That’s the beauty of CMRI - it’s a very simple protocol but it can be used for nearly anything. Being polled, there’s no need for any sort of collision detection or avoidance. Plenty fast for detection and signalling - modern stuff may be faster, but in the era I model and earlier, the signal and detection systems were relatively slow. A signal would drop relatively quickly, because the track circuit was local, but the indication would take noticeable time to reach the dispatcher’s console. All those heavy gravity operated relays were slow. CMRI is, or at least can be, fast in comparison. Seems most people don’t run it past 19.2kbps even with many many nodes and ports in use. D

RS-485 is basially just RS-422 with the send and receive pairs tied together.

that’s my understanding, RS-422 is 4-wire and RS-485 is 2-wire. I don’t understand why a 4-wire interface is decribed as RS-485.

http://www.modelrailroadcontrolsystems.com/content/cpNode_Schematic_v20.pdf

Randy

I believe i understand the nodes and protocol for communicating with them. A big benefit of using serial communication and I/O nodes is to reduce the amount of wiring, allowing a PC to communicate with a railroad of any size with a single serial port.

How about discussing how your master is organized.

I’m familiar with a system on a large layout where there is a lot of hardcoded logic. In other words, the control program is unique to that railroad.

Another approach is to describe the railroad in a table (file) containing descriptions of the relationships between blocks, turnouts, signals and I/O bits in tables. I don’t know if this is what JMRI is capable of. Which approach are you planning?

i assume transmission and handling responses to/from nodes is handled as a background process and a foreground process monitors inputs and updates outputs which are transmitted periodically (?).

Do you think main (foreground) processing is simply 1) updating signalling by sequentially scanning each block for occupancy and turnout positions and 2) monitoring turnout controls on panels and switching turnouts based on interlocking rules?