Idea: using shift-registers for additional inputs, and outputs.

Travis Farmer Mar 3, 2018

  1. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    I just so happen to have several shift-register ICs (74HC165 8-bit input, and 74HC595 8-bit output).
    as I am taking a small break from adding WiFi to the Arduino DCC++ code I have, out of frustration mainly. it occurred to me, why should it be limited by the number of physical pins on the Arduino for I/O? shift registers use SPI (or the shiftIn(), shiftOut() Arduino functions, as they don't play well with other SPI hardware), and can either output 8-bits of data, or input 8-bits of data, while using much fewer pins. and they can be daisy-chained for even more I/O.
    I remember Greg played around with using the I2C, but I don't remember any work done with shift-registers. I may work on this as a side project, unless the work has already been done by somebody else.
    for those that do not like to solder, there are breakout boards on eBay:
    Output: https://www.ebay.com/itm/74HC595-Register-Breakout-Board-PCB-Module-SN74HC595N/202112989240
    Input: https://www.ebay.com/itm/Shift-In-Breakout-SN74HC165-Conversion-Module-Board-New/272335412579
    (as examples)
    I have 3 16-ch Chinese relay boards, so that would give me 48 relay outputs, using nowhere near that many Arduino pins. once I have a prototype, I can test my idea. I am not sure how much time will be blocked on the Arduino with the number of shiftOut() calls for 48-bits of data. my hope is that it is fast enough that it wont be noticed.

    in order to integrate it, I may have to re-code the accessory I/O for DCC++ to have a one-or-the-other option to setup for hardware I/O, or shift-register I/O. I think both at once may make it too complicated.

    anyway, just thinking out-loud. thoughts are welcome.

    ~Travis
     
    Scott Eric Catalano likes this.
  2. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    lol, after pouring through the code, I think I found why I may have abandoned the idea in the past. the code doesn't seem to want to bend to my will at the moment. ;)

    my line of thought was to provide more I/O for various functions. and perhaps it could be possible that I don't understand fully what the code can do already.
    so, my thinking is, what about stripping out non-DCC functions, and offloading them to a separate Arduino, or network of Arduinos (or ESP32s, for those followers)? my understanding of the hardware, and the code, is that the faster the code handles the "side projects", and returns to the DCC protocol, the more stable everything is.
    the question is, how do we communicate with the secondary Arduino/ESP32? if we use JMRI to control everything, then wouldn't it need to be able to communicate with at least two interfaces? I thought of making a sort of router to divide the command routing, but that loses efficiency, and adds cost. one alternative may be to have a separate "automation control" software by doing this, the DCC++ code could actually remain unchanged, as it only processes what commands are sent to it.
    this automation control software could then be quite powerful (I am no-good at making that particular software), as with occupancy sensors, we can automate switches, according to an operations schedule, and automatically activate gate crossing LEDs, and so forth.

    could this be a possible evolution, or am I barking up the wrong tree?

    ~Travis
     
    Scott Eric Catalano likes this.
  3. SP_fan_1951

    SP_fan_1951 TrainBoard Member

    93
    86
    6
    Try looking into the PCA9685 I2C boards. They are available for a couple of bucks on EBay and each handle 16 outputs at 50 mA each. I am using them as servo drivers to control turnouts, but they would work for relays as well. Another option are the PCA8574/8575 I2C I/O expanders. They are around a buck and a half, but only handle 8 inputs or outputs. I intend to use them to handle local turnout control inputs.
     
    Scott Eric Catalano likes this.
  4. Jimbo20

    Jimbo20 TrainBoard Member

    274
    178
    11
    When I built my small DCC++ system using a Nano, I needed at least 12 sensor inputs (for the hall effect sensors at various places on the track). As there aren't enough spare pins on the Nano, I used a 4067 multiplexer chip that I already had. With a few small code changes it works a treat. It gives me up to 16 inputs using 5 Nano pins.

    Jim
     
    Scott Eric Catalano likes this.
  5. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    i like the look of the PCA9685 I2C boards, as it uses just the I2C bus. do you have them working with the DCC++ code, or are you using a second stand-alone system? I remember I tried a while back to get I2C going with DCC++, but it upset the timer used for the DCC++ output, if I remember correctly.

    That's kinda why I was thinking of dividing the input/output functions away from DCC++. it would open things up, without the worry of interfering with the DCC++ output. with a separated system, one could use a nano for the DCC++ signal generation, and a wide range of hardware for the other ins and outs.
    but I haven't fully thought through how the separate system would work. I have many ideas on how to make it work, but none are very practical, yet.
    I keep thinking about a Raspberry Pi as the automation controller "computer", but I have never coded for a graphical user environment, so somebody else would have to develop that end of it.
    perhaps I am thinking way too far outside the box. I tend to do that now and then. ;)

    ~Travis
     
    Scott Eric Catalano likes this.
  6. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    the shift-register idea may actually work, if I can wrap my brain around how to make it work.
    I like shift registers, as they are latching (current state is retained between writes), but the code has to send the state for all outputs in one write method. in other words, if you want to change bit 3, on shift-register 4 (daisy-chained shift-registers), you have to send the value of all the shift-registers in line, in one process. not difficult, but this requires knowing the state of every pin, and updating only the one you want. I think the original code already stores this information. I just have to figure out how to bend it to what I want, while still retaining original functions.

    I realize I may be jumping all over the place here, but that is just how my brain works. ;) (both a curse and a blessing) mainly just thinking out-loud, with the option for comments. ;)

    ~Travis
     
    Scott Eric Catalano likes this.
  7. WillemT

    WillemT TrainBoard Member

    55
    40
    7
    Hi. Long time lurker, first post.

    Just thought I should mention you could look at the MCP23017 I/O expander. I2C or SPI (using MCP23S17), for simplicity I use I2C although it is the lower speed option. Available as DIL and SMD. There are 3 address bits so you can have up to 8 chips, each with 16 I/O pins - should be enough for most applications. I/O are grouped in 8bit bytes. You can read or write each 8 individually, they are fully latched and any pin can be defined as input or output. I think they are a better option than shift registers. The big advantage is you read or write a single byte, containing your required pin, at a time.

    Hope that helps.

    Willem.
     
  8. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    Hmm, interesting (MCP23017). I even found an Adafruit library to work with it. I already have the datasheet for the chip, so I wonder if maybe I already have some on hand, in my massive collection of chips I ordered in the past for various projects (I really have to inventory those at some point). it may integrate quite well, if I2C doesn't interfere with the DCC++ output timer.

    ~Travis
     
    Scott Eric Catalano likes this.
  9. WillemT

    WillemT TrainBoard Member

    55
    40
    7
    That is such an easy chip to program you hardly need a library (it will probably just create extra overhead). A setup routine and one other to calculate the byte for a bit and write it to the correct chip will do.

    As to creating an inventory for your collection, let me know how you do so I can get started.

    Willem.
     
    Scott Eric Catalano likes this.
  10. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    I will check the library source, see how much overhead it uses.

    I am currently test-driving http://partsbox.io/, I will see if it works for my needs.

    ~Travis
     
    WillemT likes this.
  11. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    I think I may have it figured out for one (so far) MCP23017. code is on my GitHub, for those interested. I haven't tested it yet as I still have to unbox my DCC++ prototype, but it does compile. in config.h, I have added "#define USE_MCP_IO", and the current setting (0) is to not use the MCP23017. one only has to download the Adafruit library (link on my GitHub in the DCCpp readme), and change the above setting to 1.

    on the plus side, I just checked on my DCC++ prototype, and it looks intact. once I have space to set it up again, it looks good to go. :D

    ~Travis
     
    Scott Eric Catalano likes this.
  12. SP_fan_1951

    SP_fan_1951 TrainBoard Member

    93
    86
    6
    Here is my very simple code for using an Arduino Nano and a few PCA9685's to control servo's. To change it to drive relays, just change the min and max positions to 0 and 4095 respectively. It picks up the DCC accessory address off the track using an optoisolator. It's worked well so far. As far as timing goes, it only sends I2C information when there is a change, so its unlikely you would miss any packets, as it takes a while to get another address set up to send, etc.
     

    Attached Files:

    Scott Eric Catalano likes this.
  13. NormHal

    NormHal TrainBoard Member

    138
    126
    12
    Not sure if you've been following @Atani's development work on the ESP32, so just in case you haven't:)... He has added support for multiple S88 busses. Although the S88 concept provides sensor input only, the system is very economical wrt arduino pin use, and can support almost as many input sensors you'd ever need:) (would 2000 be enough?:)

    The system works like multiple shift registers, and can be configured as multiple "strings". A single Arduino Nano (for eg) can easily provide 16 inputs - additional inputs/Nanos are simply added as needed. During testing, I tested a small configuration providing 96 inputs using 6 Nanos. My test bed was configured to have three strings of 32 sensors each...

    Just my two cents:)
    Norm
     
    Scott Eric Catalano likes this.
  14. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    i have poked around in that thread, a bit here, a little there. i caught something about S88, but i wasn't sure what it was, or how the protocol worked. would an Arduino support hosting the bus? i read (or misread) something that the ESP32 can host it due to the more powerful processor.
    is it a one-way bus? can it support outputs as well?

    ~Travis
     
    Scott Eric Catalano likes this.
  15. Atani

    Atani TrainBoard Member

    1,473
    1,775
    37
    It can certainly be hosted by an Arduino. It is an input only system so it would work for sensors only. Outputs you would be better off using an I2C device like MCP23017. Another option is using the Arduino as an I2C device itself, you connect the I2C pins between devices, assign unique addresses to the IO Arduinos and interact with them from one controller device.
     
    Scott Eric Catalano likes this.
  16. NormHal

    NormHal TrainBoard Member

    138
    126
    12
    The Bus control is hosted by the base station. An alternative DCC Base Station (OpenDCC) runs on an ATMega processor (also works on an Arduino Mega) and supports three S88 "Strings". I'm sure some experimentation could get it implemented on an Arduino Uno Base Station... In the configuration I tested, The Arduino Nano performs the latching and shift register function, little more. By design, as I mentioned before:) the bus is input only. IMHO one of the major advantages of the S88 bus is that it is a "Polled" system. Sensor inputs are presented to the input device (an Arduino in my example) and their levels are continually polled by the host system. I haven't done the math, but 2000 sensors get polled every couple of hundred milliseconds.

    I see only minor modifications to make the Bus function as either input OR output, but not both at the same time:). I'm not aware of anyone having tried to configure the S88 concept as an output bus though...
     
    Scott Eric Catalano likes this.
  17. NormHal

    NormHal TrainBoard Member

    138
    126
    12
    One further thought, if anyone is interested in testing the S88 system, I'd be happy to share the code (not mine:)) but open source...
     
    Scott Eric Catalano likes this.
  18. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    i think Greg had started an option, using Arduinos connected via I2C. i don't remember if it worked or not though. i think i removed it from my copy of the code as it was interfering with my implementation of an MCP23017.

    i will read up on S88, but right now i am in full brainstorm on the MCP23017, and don't want to derail my train of thought. ;)

    ~Travis
     
    Scott Eric Catalano likes this.
  19. Atani

    Atani TrainBoard Member

    1,473
    1,775
    37
    I am looking at both options now as I need more outputs than what I have on the esp32 or Arduino. I like the mcp chip but may need more than 8 on a bus so looking at some options for that. The esp32 has two i2c buses so that helps a bit. Arduino has SoftI2C which would work likely.

    Sent from my ONEPLUS A5010 using Tapatalk
     
    Scott Eric Catalano likes this.
  20. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    the MCP23017 has 2 8-bit ports, each can be configured as input or output, individually.

    ~Travis
     
    Scott Eric Catalano likes this.

Share This Page