hsanjuan / dccpi

A simple, easy to use, NMRA Digital Command Control (DCC) Python implementation for Raspberry Pi
GNU General Public License v3.0
54 stars 13 forks source link

NRMA Digital Command Control (DCC) implementation for Raspberry Pi

This module implements the DCC protocol for controlling model trains using a Raspberry Pi.

It is able to output direction and speed DCC-encoded packets on one of the GPIO pins (see example below).

It is based on the:

Attention: Python is too slow and barely gets the job done (and thanks to a C-extension). Therefore I have decided to re-implement dccpi in Go: https://github.com/hsanjuan/go-dcc . The Go implementation gives an overall better user experience and it is easier to install/run.

Index

Features

You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Joe Armstrong

dccpi is a minimal implementation which aims to offer support to control some trains and be easy to integrate in other projects. It is not a support-all, complex, multi-protocol, ui-included, buy-my-hardware solution. For this, there are better solutions like RocRail, JMRI, SPROG, GertBot etc.

Note dccpi does not yet implement any advanced features like decoder registry operations (i.e. set address). I will work to extend it to my needs, which are not too fancy.

Hardware requirements

dccpi should work on any common scale. DCC decoders take a wide range of voltage outputs (up to 24v). This has been tested on N-scale with a 18v booster circuit.

Booster circuit

Here is an example booster using LMD18200 H-Bridge from TI:

Booster schematics

These are the parts:

Here is an image composed of 5 pictures of how my actual working prototype looks like: prototype.jpg

Note that the circuit in the pictures includes an additional 5V DC converter (the black chip with 3 legs) and some resistors which are not necessary nor play any part.

Software requirements

Installation

From PyPI:

sudo pip install dccpi

From Source:

sudo python setup.py install

Usage

There are 3 main componenents:

The Raspberry Pi will output the signal (which goes from 0v-Low to 3.3v-High) on BCM GPIO pin 17, which is Physical Pin 11 (Model B+), which is wiringPi pin 0. The booster is in charge of converting this signal into the DCC signal ranges (i.e. 18v to -18v).

The Raspberry Pi will also output a brake signal (HIGH) when the controller is stopped on BCM GPIO pin 27, which is Pysical Pin 13 (Model B+), which is wiringPi pin 2 (so next to the one above). This can be used to stop signal on the tracks if your booster supports it (see booster schematics). Otherwise locos will receive DC current directly, and either burn or turn into DC mode (at full speed).

See example below and read the code for more info.

Example

Note that dccpi programs must be run as root, or wiringPi will complain.

from dccpi import *
e = DCCRPiEncoder()
controller = DCCController(e)  # Create the DCC controller with the RPi encoder
l1 = DCCLocomotive("DCC6", 6)  # Create locos, args: Name, DCC Address (see DCCLocomotive class)
l2 = DCCLocomotive("DCC7", 7)
l3 = DCCLocomotive("DCC8", 8)
controller.register(l1)        # Register locos on the controller
> DCC6 registered on address #6
controller.register(l2)
> DCC7 registered on address #7
controller.register(l3)
> DCC8 registered on address #8
controller.start()             # Start the controller. Removes brake signal
> Starting DCC Controller      # and starts sending bits to the booster
l1.reverse()                   # Change direction bit
l2.fl = True                   # Change fl function bit
l3.fl = True
l1.speed = 10                  # Change speed
l2.speed = 18
l3.speed = 23
l3.slower()                    # Reduce 1 speed step
l3.faster()                    # Increase 1 speed step
l1                             # Print loco information

DCC locomotive
> Name:               my
> Address:            6
> Speed:              10
> Speed steps:        28
> Direction:          0
> FL, F1, F2, F3, F4: [0 0 0 0 0]

controller                     # Print info from all locos registered
> DCC Controller:
> -----------------------------
> DCC locomotive
> Name:               my8
> Address:            8
> Speed:              23
> Speed steps:        28
> Direction:          1
> FL, F1, F2, F3, F4: [1 0 0 0 0]
> -----------------------------
> DCC locomotive
> Name:               my2
> Address:            7
> Speed:              18
> Speed steps:        28
> Direction:          1
> FL, F1, F2, F3, F4: [1 0 0 0 0]
> -----------------------------
> DCC locomotive
> Name:               my
> Address:            6
> Speed:              10
> Speed steps:        28
> Direction:          0
> FL, F1, F2, F3, F4: [0 0 0 0 0]
> -----------------------------

controller.stop()              # IMPORTANT! Stop controller always. Emergency-stops
> DCC Controller stopped       # all locos and enables brake signal on tracks

Example with dummy encoder

Same as above but pass DCCDummyEncoder() to the controller. The Dummy Encoder will print information to the screen every 10 seconds on what packages are sent and to who, but leave GPIO outputs alone.

License

GPLv3. See LICENSE.