Wednesday, February 17, 2021

An ATTiny85 as DCC function decoder

Why?


Back in the starting days of our model railroad I bought some used passenger cars from GDR-based manufacturer BTTB. I wanted to install some lights into these cars now and since we're already using DCC, I had the idea to use a function decoder to switch lights on and off. There also is a small empty space in the base of each car that could contain the parts of the decoder, so let's go ahead. Since proper function decoders are still quite expensive, especially if you compare that to the price of the used cars, I decided to look out for a DIY solution.
Besides the Arduino Nano clones (which are rather bulky due to the micro USB connector) a nice and small contender was the Digispark USB board (when using the chinese clones, they are affordable too).  
The Digispark boards use an Attiny85 micro controller with one interrupt connected input (so you get a callback function call when the input value changes, rather than having to poll for the value in your code) and 4 to 5 outputs, which I will not use completely anyway (I only need 1 output for the internal light and 2 outputs for the front and rear end lights).

Design

As a base I used the following circuitry:




On the left side we can see the full bridge rectifier; contrary to the image above I used a SMD S40 rectifier. Additionally you can spot the input diode at the bottom, together with a voltage divider [^1] that is connected to pin 2 of the digispark board (pin 2 is the interrupt pin). To the left of the digispark board, I used 7805 voltage regulator [^2] which delivers a constant 5V voltage from the rectified 14-16V voltage of the DCC signal. You can also see that I used an electrolytic capacitor for storing some energy in case of loss of connection. The BC547 transistor with series resistor R3 is used to switch the LED with its series resistor. Obviously, this last part needs to be repeated for each LED channel (lighting, front & rear), but for simplicity this was left out of the sketch.

[^1]: Later on, I increased the resistor values of the voltage divider circuit to 2kOhm and 8kOhm to reduce the current going through that path.
[^2]: The 7805 is slightly inefficient and gets at least warm due to excess heat is has to radiate - later on I decided to use one of the smallest electronic buck converters I could find, which were similar in size while having a far far lower heat dissipation.

The Software Side

You can now transfer the required program to the digispark with the source code from the following repository:
 

nagf2rpi-functiondecoder.ino

This code uses the library nmradcc, which you can either download directly from that github page or using the Arduino IDE's library manager. The code is based on an example from the nmradcc library, but some changes needed to be made. The function digitalPinToInterrupt doesn't exist for the ATTiny85, so another initialization routine had to be called as well.

The result on my test track can be seen in this video:


youtube video of testing

And Now?

After I came this far, I decided to not use the Attiny85 for the rest of the cars. The disadvantages were simply to high:

- The electric power consumption of the digispark board alone is rather high, I once measured above 30mA (without LEDs and after the voltage regulator). Keeping the LEDs on all the time would have had a far lower impact. This also reduces the usability of the capacitor(400mF) to zero. The solution came in the form of some Arduino Pro Mini clones I could buy for roughly the same price, which only use 1-2mA at a voltage of 3.3V.
- The Attiny85/Digispark has a standard kernel which needs to check for a USB connection too. That's why it will have a down time of a few seconds after each restart (and a restart happens every time the car loses contact to the tracks). One could replace this kernel, but this brings other problems too.
- The price of each Digispark board is rather high, around 3-4€ per piece and the Arduino pro mini modules are comparable..
- I extracted grey smoke from several of the Digisparks I originally bought (happens when you mix up the cabling...), so I'd have to buy new ones anyway.

I hope this helps, maybe I'll make the planned video about DIY DCC decoders in the future.

Monday, February 15, 2021

Ein ATTiny85 als Funktionsdecoder

Warum?

In den Anfangszeiten unserer Anlage habe ich ein paar alte BTTB Personenwagen gekauft, die ich jetzt einmal mit einer Beleuchtung ausstatten wollte. Da wir ja bereits digital fahren, wurde nach einigem hin und her die Idee geboren, vor die LED-Beleuchtung auch noch einen (Funktions-)Decoder zu setzen, der zwischen Wagenbogen und Boden der Inneneinrichtung passen könnte. Da einfache Funktionsdecoder vergleichsweise teuer sind und den Preis pro Wagen weit übersteigen würden, habe ich mich nach einer Selbstbaualternative umgeschaut.
Neben den doch eher großen Arduino-Nano-Verschnitten kam dafür ein Digispark-Board in Frage, welches zumindest in der Variante als chinesischer Nachbau vertretbar ist.
Der Digispark besitzt einen einzigen Eingang mit Interrupt (als Eingang für das DCC-Signal; ein Interrupt wird benötigt, damit nicht immer der Status des Eingangs gelesen werden muss, sondern bei Veränderung des Eingangs automatisch eine Funktion aufgerufen werden kann) und 4 oder 5 Ausgänge (die ich aber erstmal einmal nicht alle brauche - ich will maximal 3 Ausgänge für die Innenbeleuchtung und die Wagenschlussbeleuchtung in beide Richtungen).

Der Bauplan

Als Grundlage habe ich also folgenden Bauplan gewählt:



Auf der linken Seite können wir den Gleichrichter sehen; im Gegensatz zur Skizze habe ich da einen S40 SMD Gleichrichter benutzt. Weiterhin kann man an der Unterseite der Skizze die Eingangsdiode erkennen, die zusammen mit der Spannungsteilerschaltung[1] R1/R2 auf Pin 2 des Digispark gelegt wurde (Pin 2 ist der Pin auf dem der Interrupt liegt). Links vom Digispark kann man den 7805 Spannungsregler[2] erkennen, der aus der Gleichspannung von ungefähr 14-16V die 5V Versorgungsspannung für den Digispark erzeugt. Direkt rechts neben dem Gleichrichter ist nun beispielhaft sowohl der Stützkondensator (C1) zu sehen, als auch ein BC547 Transistor mit Vorwiderstand R3 und die zu schaltende LED mit Vorwiderstand. Dieser letzte Teil würde für jede zu schaltende LED (Beleuchtung, Schluss- und Frontbeleuchtung) wiederholt, ich habe dies aber der Einfachheit halber weggelassen.

[1] Die Spannungsteilerschaltung habe ich später jedoch mit höheren Widerständen mit 2kOhm und 8kOhm verbessert um den Stromfluss zu verringern.
[2] Der 7805 ist relativ ineffizient und wird relativ schnell warm - deshalb habe ich ihn später durch einen Buck-Converter ersetzt - die kleinsten Buck-Converter die ich finden konnte waren in vergleichbarer Größe aber mit einem vielfach verringerten Stromverbrauch.

Die Software

Der Digispark wird nun mit der Arduino IDE mit dem source code aus diesem repo bespielt:

https://github.com/sengels/nagf2rpi-functiondecoder/blob/master/nagf2rpi-functiondecoder.ino

Dieser Code benutzt die Bibliothek nmradcc, die entweder direkt von github oder aus der Arduino-Bibliotheksübersicht benutzt werden kann.
Ein paar Änderungen müssen hierbei gemacht werden, die Funktion digitalPinToInterrupt existiert nicht für den Attiny85, deshalb muss dann auch eine andere Initialisierungsroutine aufgerufen werden als in dem ursprünglichen Beispiel.

Auf meinem Testgleis sieht das ganze nun folgendermaßen aus:

Test

Und nun?

Nachdem ich soweit war, habe ich mich nun doch entschlossen, nicht weiter mit dem Attiny85 zu arbeiten, die Nachteile sind nämlich relativ hoch:
  • Der Stromverbrauch des Digispark boards ist ziemlich hoch, ich habe im laufenden Betrieb deutlich über 30mA gemessen. Die LEDs für die Beleuchtung benötigen nur einen Bruchteil. Bei diesem hohen Stromverbrauch ist auch der Stützkondensator keine Hilfe mehr. Außerdem hatte ich zwischenzeitlich einen Arduino pro mini clone bestellt und diesen bei 3,3V mit ungefähr 2mA betreiben können.
  • Der Attiny/Digispark muss deutlich aufwendiger bespielt werden, der Standard-Kernel hat eine 6-sekündige Einschaltdauer, die halt bei jedem Kontaktverlust an der Schiene auftreten würden.
  • Der Preis für einen digispark ist immer noch sehr hoch und unterscheidet sich nicht von einem arduino pro mini (ungefähr 3-4€ pro Stück)
  • Ich habe leider mehrere Digisparks in Rauch aufgehen lassen (wenn man beim decoder halt die Anschlüsse vertauscht), werde aber keine weiteren Digisparks mehr kaufen.

Ich hoffe, diese Ausführungen helfen jemandem, vielleicht mache ich tatsächlich noch einmal ein youtube-Video dazu.


Monday, January 2, 2017

beginning

Since more than two years, I am now working on a model railroad for me and my two sons. It all started with just some old tracks (back from the days of my own model railroad), some used engines and carriages bought from ebay set up on the living room table.
Over time, this evolved into a full blown model railroad on wooden fiberboard, sized ~1,5m x 1m in scale 1/120 (TT). At the moment, the whole layout is still analogue; as that only allows one motorized train at the same time, most trains currently are push-trains :-D.

So for quite a while already, I was looking for a solution to let both my sons drive one train at the same time.
All my solutions evolve around a raspberry pi, since I can easily program that, it provides electrical input and output (gpio pins) and was available right away.
My first idea was a layout, heavily split into subsections, and a good mechanism to enable separate subsections using relais. One single DC source was supposed to support two trains using two PWM modulated outputs. The different sections would then be fed with one of the two modulated outputs and thus let the trains go ahead. I bought two L293D H-bridges and did my first tests. This worked in a small proof of concept for half a minute, but when I tried it out for several minutes, the H-bridge overheated (and likely died) due to no installed cooling, melted parts of the breadboard it was installed on and grilled the first rpi.
This made me give up on the project for nearly a year, and then made me reconsider my choices.

So I decided to modify some of the given things:
* instead of the weak L293D use some more powerful motordriver. In the end, I decided to buy two (one spare) LMD18200 motor driver boards ready set up on ebay.
* instead of using PWM and having to manage a complicated track, I would switch to full digital control and use DCC instead.
* using DCC means that I need to buy new DCC-decoders for all my engines, and also that I might need to solder the decoders into my old engines.
* instead of writing the DCC protocol myself, I decided to reuse an existing solution, in this case dccpi by Hector Sanjuan. For testing purposes I also used gpiodcc

Some weeks ago, I managed to drive my first engine digitally using dccpi, the hardware seems to be ok with that, and after some thoughts I realized that I have one issue left: All decoders seem to have address 3 as default engine address. To have at least two trains going, I would have to program the decoders. This is not implemented in dccpi atm, so I am now trying to get a solution for that. In case I manage to find one (and I hope so), I will of course make them available on github.

So far the reasons for this blog, hopefully more documentation to come in the coming months.