24 IN / 48 OUT card for JMRI

nopxor Apr 16, 2018

  1. nopxor

    nopxor New Member

    4
    6
    1
    Hello,

    It's a SMINI C/MRI clone with an Arduino Nano.
    https://www.utrainia.com/65-arduinocmri-and-rs485

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

    [​IMG]

    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.
    http://jmri.sourceforge.net/help/en/html/hardware/cmri/CMRI.shtml

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

    [​IMG]

    [​IMG]

    I used Eagle for the schematic & PCB (100 x 100 mm).
    I ordered the PCB at JLCPCB (2$ for 10 pcs !)
    https://jlcpcb.com
    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.

    Code:
    /**
     * 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
      cmri.process();
     
      // 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:
    https://www.ebay.fr/itm/262957982206

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

    Attached Files:

  2. TwinDad

    TwinDad TrainBoard Supporter

    1,819
    511
    31
    SWEET!

    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

    4
    6
    1
    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 Supporter

    1,819
    511
    31
    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

    159
    225
    14
    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 ;)
     

Share This Page