24 IN / 48 OUT card for JMRI

nopxor Apr 16, 2018

  1. nopxor

    nopxor New Member


    It's a SMINI C/MRI clone with an Arduino Nano.

    It can control turnouts, lights, signals leds.
    You can connect block detection modules or push buttons.


    The card is connected to the PC with a RS485 bus. There are USB-RS485 adapters @ 1$ on Ebay.
    With such bus, you can connect many cards to JMRI. Each card has a node identifier in JMRI.

    The board uses 6 IC 74HC595 for the 48 outputs and 3 IC 74HC165 for the 24 inputs (pulled-up)



    I used Eagle for the schematic & PCB (100 x 100 mm).
    I ordered the PCB at JLCPCB (2$ for 10 pcs !)
    For ordering PCB, you can directly upload the file "Arduino-CMRI_Gerber.zip" on the site.

    The Nano's sketch is very simple with the CMRI and Auto485 libraries from Michael Adams: https://github.com/madleech
    You just have to define the node number.

     * C/MRI -> JMRI via RS485
     * =======================
     * Sets up an SMINI 24 inputs, 48 outputs with an Arduino Nano.
     * Uses an RS485 bus to transparently talk support multiple ArduinoCMRI nodes on one bus.
     * By passing in an Auto485 object to the CMRI constructor, we are able to automatically
     * control the DE and RE pins on our RS485 bus transceiver.
     * The PC with JMRI has an USB-RS485 adapter connected to the bus.
     * IN control:
     * Nano pin:             74HC165 pin:
     *     9        LATCH ->     1
     *     13       SCK   ->     2
     *     12       MISO  ->     9
     * OUT control:   
     * Nano pin:             74HC595 pin:
     *     6      verrou ->     12
     *     7      donnee ->     14
     *     8     horloge ->     11
     * Change the CMRI_ADDR for each board.  Each node must have its own address.   
     * ====================================
    #include <Auto485.h>
    #include <CMRI.h>
    #include <SPI.h>
    #define CMRI_ADDR 0                  // select the CMRI node address
    #define    DE_PIN 2                  // Arduino pin 2 -> MAX485 DE and RE pins
    // pin 74HC165
    const byte LATCH = 9;
    // pins 74HC595
    const byte verrou = 6;
    const byte donnee = 7;
    const byte horloge = 8;
    Auto485 bus(DE_PIN);                 // RS485 bus transceiver
    CMRI cmri(CMRI_ADDR, 24, 48, bus);   // sets up an SMINI. SMINI = 24 inputs, 48 outputs
    void setup() {
      bus.begin(9600, SERIAL_8N2);       // open the RS485 bus at 9600bps
      pinMode(verrou, OUTPUT);
      pinMode(donnee, OUTPUT);
      pinMode(horloge, OUTPUT);
      SPI.begin ();                      // serial data protocol used to control 74HC165
      pinMode (LATCH, OUTPUT);
      digitalWrite (LATCH, HIGH);
    void loop() {
      // 1: main processing node of cmri library
      // 2: update output
      digitalWrite(verrou, LOW);                                // on commence par mettre le verrou
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(5));    // on envoie la sixieme donnée d'abord
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(4));    // on envoie la cinquieme donnée ensuite
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(3));    // on envoie la quatrieme donnée ensuite
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(2));    // on envoie la troisieme donnée ensuite
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(1));    // on envoie la seconde donnée ensuite
      shiftOut(donnee, horloge, MSBFIRST, cmri.get_byte(0));    // et on envoie la première donnée
      digitalWrite(verrou, HIGH);                               // et on relache le verrou pour mettre à jour les données
      // 3: update inputs
      digitalWrite (LATCH, LOW);                                // pulse the parallel load latch
      delay(1);                                                 // wait while data loads
      digitalWrite (LATCH, HIGH);
      cmri.set_byte(0, ~(SPI.transfer(0)));
      cmri.set_byte(1, ~(SPI.transfer(0)));
      cmri.set_byte(2, ~(SPI.transfer(0)));
    There are two jumpers on the board connected to TX and RX.
    You mut disconnect them during the USB Nano upload.

    The 5V power supply must be disconnected during the USB Nano upload.

    There are two RS485 connectors on the board for easy chaining.
    No need to use 120 ohm termination resistors for RS485.
    For small distances (several meters) they may be omitted.

    The connectors pitch is 3.5mm as here:

    Load currents should not exceed 35 mA per output and 70 mA total for one 74HC595 (8 outputs)

    Attached Files:

    Crisco and vasilis like this.
  2. TwinDad

    TwinDad TrainBoard Member


    And a new cheap board vendor to add to my list, to boot!

    Very cool.

    Two questions about the design, pondering your preferences vs. mine...

    (1) I see you soldered the Nano down... I tend to socket them, even though it costs a bit more, in case I want/need to change them out. Your rationale for soldering is??

    (2) Why such a large IO count? Is this planned for a particular area where there is a great concentration of sensors/signals/turnouts/etc.? Like an urban area or a yard or something? Are you concerned about maximizing utilization of the Nano? So far I've tended to build smaller, more specialized boards (less than 8 IO each, generally) so that they can be placed close to the (geographically spaced-out) devices under control, with relatively longer (LocoNet) bus wires for connectivity. I know I'm (relatively) under-utilizing the Arduino's horsepower, but they're so cheap these days... I have about a dozen scattered about 50 square feet of layout.

    I'm certainly not implying that you are wrong at all. But clearly you had different thoughts on the design than my usual assumptions, so I'd like to understand your thinking. I may learn something!
  3. nopxor

    nopxor New Member

    I soldered the Nano because it's more simple and I don't know which socket I can use for a Nano.

    The I/O count match the exact SMINI count of a node recognized by JMRI. And I need many outputs for signaling on my layout.
  4. TwinDad

    TwinDad TrainBoard Member

    Ah. OK. That makes sense.

    For the Arduino ProMini, I use two of these 12-pin headers, but unfortunately the 15-pin version is rarely if ever in stock. One could cobble together shorter length sockets I guess. Mostly I use the ProMini because I like the slightly smaller size and don't care about the lack of built-in USB port.

    As for the I/O count, I can definitely think up some scenarios where signaling, especially say on a multi-track main or in an congested area, could eat up a lot of pins very quickly in a small space.

    Well done on the design. My hat's off to you.
  5. KE4NYV

    KE4NYV TrainBoard Member

    This is interesting. I would be interested in making an all SMT version of this and going to 2.54 MM terminal blocks to squeeze it down into a smaller foot print.

    Recently I started playing the idea of making a Raspberry Pi Zero W based DCC decoder/controller that could be duplicated easily and cheaply to place several around my layout. I like the idea of it being either a standalone option that get's everything from the DCC buss directly or network them all wirelessly and feed it commands through the network. I started looking at whether JMRI supported any kind of TCP/IP socket to do this and so far I'm not really finding what I am looking for.

    One more point to TwinDad's comment on soldering the Nano on directly. I too would socket it using 2.54 mm header sockets (I buy the 40 pin version 100 at a time) and just cut them down. However, this is a good candidate to just put the Arduino Nano (Pro) right on the board as an integrated part of the design. I recently did a board (in Eagle) for a customer that has a product based on the Pro Mini 5V version. I embedded the Pro Mini circuit into the board, so there is no module to solder on now. Just included the ICSP header to flash the 328P with the Arduino bootloader after I reflow the board. So far that is working out well for them.

    For me, I'm a PIC guy ;)
    John Balogh likes this.
  6. vasilis

    vasilis TrainBoard Member

    (y)Very very nice, thank you.
    With a socket for arduino, as twindad suggests and sockets for shift registers will be a little better.
    Nice simple sketch and the arduino gives the abillity to add special i/o handlers (buttons with debounce, turnouts servos with spdt swithces for feedback, smd rgb leds,...)
    I'm newbie in all this and i'm wondering if the shiftpwm library (pwm shift registers for rgb leds) can be used with spi lib without conflicts. (i found some interesting posts)
    Thanks again for the strong kick start for speculations.
  7. William E Van Buskirk

    William E Van Buskirk TrainBoard Member

    Very cool NOPXOR, I just received my box from JLCPCB :) At $2 per board it's very hard to build a less expensive SMINI node. I plan to use up some Pro Micros I have, gathering dust. A couple jumpers and a slight change to the sketch, very easy. Will post my progress (was going to post @Locodinuo but no skillz at speaking/writing French).
    By the way, for other builders, this deal also comes with a $18 shipping charge. So the total is ~$20 for 10 boards, still cheap and shipped very FAST via DHL. Stick to the 10 boards per order; I found that if I changed to 20 boards there were Eng and Layout fees. So the price jumped quite a bit. Better to do two orders if you need a ton of boards. Also thought I'd combine two of your ULN driver boards into a panel, to fit the JLCPCB 10cm x 10cm '10 for $2' deal.

    One can scale down the OUTs/INs but at $.20 or less per shift registers, just seems prudent to go ahead and stuff the board and use as much or little of the SMINI. Rather then having some boards with 8&8 or 16&8 or ...
    @TwinDad I agree with the idea of a minimal Pro Mini node but I have been eyeing https://www.diymore.cc/products/diy...a16u2-microcontroller-compatible-with-arduino Really like the 3pin layout and the price is not too bad.

Share This Page