DCC++ accessory decoder, bus architecture options: what to choose?

Erik84750 Dec 23, 2019

  1. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    For accessory decoders there are multiple options on how to program, address and activate/use accessories. Below is a list of different option/architectures/approaches to this subject. I made this list because there are major contributions from very knowledgeable people, and an overview will help me (and hopefully others) to see the forest through the trees.

    To make this broad subject a bit more comprehensible I adapted my overview to accessory decoders (not function decoders), such as for example driving of servos for turnouts.

    I. Geoff Bunza: SMA25 (selfcontained command station for accessory decoder access and control)
    1. no JMRI
    2. Arduino Mega + LCD/keypad shield + motorshield
    3. DCC bus communication
    4. can be programmed as either accessory or function/loco command station
    5. no PC interface needed
    6. can be used with accessory decoders from SMA20
    II. Geoff Bunza: SMA20 (mobile function or accessory decoder)
    1. taps info/commands from DCC bus, from a dedicated command station via DCC bus (for example from item I. , or from David Bodnar or Geoff Bunza or this or this from Atani or....)
    2. 17 channels (ie up to 17 servos per decoder)
    3. very small form factor (Pro Mini)
    III. Geoff Bunza: SMA29 (data out) or SMA28 (data in from sensors,..)
    1. data out = direct control per Arduino pin, from PanelPro
    2. Arduino Mega is programmed with JMRI_Turnout_Scan software from Bunza
    3. plus a script (py) to be run in JMRI (listening to PanelPro Switch Control output, commands are forwarded via USB to Arduino Mega; or to listen to the Mega inputs and update JMRI input panels accordingly and directly)
    4. communications via USB; JMRI preferences connection tab set to "Digitrax LocoNet Simulator"
    5. the concept is to use PanelPro output to directly drive accessories via USB and Mega, or to use the Mega to receive inputs from sensors and directly update JMRI sensor or other input panels.
    IV. Atani: ESP32 command station (trainboard.com and Github)
    1. full command station software with HMI via Nextion touchpanel and accessory commands
    2. about 50 pages of postings, very active subject; yet I am not knowledgeable enough to write a summary
    V. Arduino Mega command station + Uno (from Brendanf on trainboard.com; "Mega" + "Uno via RX/TX with I2C to 16ch PWM servo controller ")
    1. Arduino Mega with adapted DCCpp_Uno.ino software: changes have to be deduced from Brendaf postings on Trainboard.com
    2. Arduino Uno sketch, from same thread: here
    3. Uno connected to Mega via RX/TX
    4. Uno connected via I2C to single or multiple chained 16ch PWM servo drivers
    5. Direct control from JMRI PanelPro Switch control panel
    6. command station with accessory control (servos) included
    This last approach seems to be the most innovative, yet has very little "publicity". However, since I am not sufficiently knowledgeable and all those having contributed above have done so with utmost professionalism I woul like to know which approach has what advantage/disadvantages.

    I tried to upload a zip containing the two programs needed for V. but I keep getting an error?

    Thanks for your response!
    Erik
     
    Last edited: Dec 23, 2019
    Sumner likes this.
  2. bocabob

    bocabob TrainBoard Member

    47
    22
    6
    From my perspective there are three approaches or rather, architectural interfaces being DCC, LCC, stand-alone. There are a ton of examples using libraries to interface an Arduino to DCC in order to drive one or many servos. Easy and cheap to do. Easy to interface with JMRI. The main drawback is that DCC does not provide a means to feed back state information from the device. LCC solves this though it is still early in the adoption curve. But it is (I think) the future. There are some CAN bus shields out there and some schematics. I have only progressed to the point collecting the parts and am not yet ready to bench test anything. I am currently distracted with scenery :) Of course stand-alone is wide open on implementation.
    DCC Turntable Decoders and Controllers
    DCC Interface – Model Railroading with Arduino
    The OpenLCB Group – The People, Ideas and Technology powering the NMRA's Layout Command Control (LCC)
    GitHub - openlcb/OpenLCB_Single_Thread: OpenLCB stock based on ArduinoIDE
     
    Sumner likes this.
  3. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    Nice to know, but before broadening the discussion I would like to keep the subject to accessory decoders in DCC++.
     
  4. vasilis

    vasilis TrainBoard Member

    110
    39
    10
    If the jmri is a component then cmri is a low cost and easy option. The rs485 is a reliable bus. The jmri is a powerful tool, with the logix you can logically associate the inputs and the outputs. The arduino nodes inputs/outputs are transmitted/received to/from jmri so the code of your arduino nodes remain simple.
    Some links
    The Utrainia.com (Michael Adams) seems is down, but you can open the cached pages.
    https://github.com/madleech
    http://webcache.googleusercontent.c...s-with-arduino-cmri+&cd=2&hl=en&ct=clnk&gl=en
    https://www.jmri.org/help/en/html/tools/Logix.shtml
    https://www.trainboard.com/highball...-in-48-out-card-for-jmri.116454/#post-1053654
    http://www.motorhomesites.org.uk/jmri/
     
    Erik84750 likes this.
  5. vasilis

    vasilis TrainBoard Member

    110
    39
    10
    You can experimenting with a simple setup with two arduinos. Connect a push button to an input of arduino one, connect a led or a servo to the output of arduino two. The pushbutton changes the value of a bit sended to jmri. The led, the servo change their state based on a bit received from jmri.
    In the jmri setup the pushbutton as sensor and the led as light, and servo as turnout. Setup the logix to set the led or the servo accordin to the pushbutton. Happy testing.
     
    Erik84750 likes this.
  6. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    That is a C/MRI hardware emulator! Good idea, I add that to my list above. Nice project to investigate.
     
  7. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    In follow-up to Vasilis' post I add the following to my original post:

    VI. JMRI C/MRI emulator: developped by contributor nopxor and presented on trainboard forum
    1. Arduino controller emulates C/MRI controller on DCC++ bus and JMRI connection to C/MRI
    2. 24 in- or 48 outputs according to C/MRI standard
    3. purely digital I/O (EDIT per Vasilis, post below: servo control possible, but I have still to figure out how to)
    4. Eagle schematic, board and gerber files available from author
    5. JMRI connection over USB (requires USB-to-RS485 converter: 2USD)
    6. great for signalling and digital sensor inputs
     
    Last edited: Dec 24, 2019
  8. vasilis

    vasilis TrainBoard Member

    110
    39
    10
    You don't have to use the 24in/48out pcb exclusively, but even here you have 11 arduino pins to use for servos.
    From https://github.com/madleech/ArduinoCMRI
    Limitations
    With rs485 you can have max 32 nodes. The maximum combined number of addressable inputs and outputs is 2048

    You can have a servo controller (like G. Bunza's based on softwareservo lib) too. Everything that has two states (on/off, right/left) can be controlled with one bit (0/1). The jmri sends a bit for the turnout and the arduino controlls the servo accordingly. You can have a 17 servo controller, but you will use 1 bit from the 3rd byte or 16 servo controller with 2 bytes, or 8 servo controller and some shift regs i/o or use the outputs to setup the node adress by using switches. 8 servos on arduino pins, and only input regs or output regs, so you have 6 arduino pins free to use for the node adressing.
    http://www.motorhomesites.org.uk/jmri-arduino-servo-control/
     
  9. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    Thanks for that, Vasilis: my post above updated accordingly. But I do not understand how to integrate the servo control demonstrated on this page from (? madleech, nopxor,.. ?) inside the sketch from nopxor' thread here.
    I would be very thankful for some help with this!
     
    Last edited: Dec 24, 2019
  10. vasilis

    vasilis TrainBoard Member

    110
    39
    10
    hmmm you want the end of the trip. :) Please read the example and the description here https://github.com/madleech/ArduinoCMRI. The two sketches read/send (cmri.process())the cmri bytes and then they do something. The nopxor's sketch updates the i/o, the Steve's (motorhome sites) takes one bit of the data and controls a servo connected to the arduino pin via the servo.lib.
    So, to control servos we need arduino pins and a lib (softwareservo, servo, or...).
    Let's modify a little the nopxor's card. We through out an output register and use eight of the free arduino pins for servos. The eight bits (one byte) received from cmri instead the discarded register have the info for the servos. We update the 5 remained output registers and we set the servos according the sixth byte. For each bit we set the servo as in Steve's example (please understand it is a quick attempt)

    //in the loop after the cmri.process()
    for (servo_number = 0; servo_number < 8; servo_number = servo_number + 1)
    {
    servo_bit_number=servo_number+40
    servo_state = (cmri.get_bit(servo_bit_number)); //servo_bit_number=40,41,...,47 the 6th output register
    if (servo_state == 1){
    servo_obj[servo_number].write(90);
    }
    else{
    servo_obj[servo_number].write(0);
    }

    of course we have to declare the vars, the servo objects and the pin for each servo
    byte servo_number //index
    int servo_bit_number // stores the bit number associated with the servo
    int servo_state // stores the state, the value of the bit associated with the servo (received from cmri)
    servo servo_obj[8] // 8 servo objects
    int servo_pin[8]={8 arduino pins} // you have to write the arduino pins you will use

    and in setup() attach them
    for (servo_number = 0; servo_number < 8; servo_number = servo_number + 1)
    { servo_obj[servo_number].atach(servo_pin[servo_number])
    }
    Hopefully i made the things a little bit more clear.:confused:
    Please make small steps, like Steve in his videos. Look at his youtube channel. You will see that is not so hard. :) You have to make test setups like in any other case. Keep in mind i'm not a guru :)
     
    Last edited: Dec 24, 2019
    Erik84750 likes this.
  11. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    Ok, now you got me, and I will take and study this slowly the coming days, weeks.. And yes you are my guru. Until soon...
     
  12. Erik84750

    Erik84750 TrainBoard Member

    334
    134
    12
    Last edited: Dec 22, 2021

Share This Page