Bouw een DCC-commando station voor modelspoor met Arduino – gratis app inclusief
Onderdelen en benodigdheden
| SparkFun Arduino Pro Mini 328 - 5V/16MHz | × | 1 |
| LMD18200T H-brug | × | 1 |
| PCB (printplaat) | × | 1 |
| Lineaire regelaar 7805 (5V) | × | 1 |
| Zenerdiode 3.6V 0.5W (1N4732A) | × | 1 |
| HC-06 Bluetooth Module | × | 1 |
| Weerstand 0.1 Ω 2W | × | 1 |
| Condensator 220 µF 16V | × | 1 |
| Condensator 10 µF 16V | × | 1 |
| Keramische condensator 0.1 µF | × | 3 |
| Weerstand 10 kΩ | × | 2 |
| Weerstand 4.7 kΩ | × | 1 |
| Schroefklem 2-polig 3.5 mm | × | 1 |
| Schroefklem 6-polig 2.54 mm | × | 1 |
| Socket 4-pin 2.54 mm | × | 1 |
| Socket 12-pin 2.54 mm | × | 2 |
Apps en online diensten
- LocoMotive – gratis versie (Google Play Store)
- LocoMotive DCC – uitgebreide versie (€5,99, met CV 1-255 read/write)
Over dit project
Wat maakt dit systeem uniek? Een heel simpel elektronisch circuit genereert het DCC-signaal en de baanvoeding, maar de app op je smartphone doet het echte werk. De processor van je telefoon stelt de DCC-pakketten samen (instructies voor locomotieven, wissels, functies), wat de Arduino taak enorm vereenvoudigt.
Updates & versies
- 16 aug 2019: Nieuwe app "LocoMotive DCC" met CV 1-255 read/write (betaald).
- 18 mei 2019: App update: tot 28 functies met bewerkbare titels, zichtbaarheid, momentaire opties; 4 locs tegelijk met snelheidsbalken (betaald, ~€3).
- 17 feb 2019: HC-06 antenne verlengen met 31,2 mm koperdraad (¼ golflengte 2,4 GHz) voor bereik.
- 29 jan 2019: Momentaire optie op F2/F3 voor hoornsignalen; preset max snelheid per loc.





Dit is het meest efficiënte DCC-commando station dat je kunt bouwen: minimale componenten, maximale functionaliteit. De gratis app LocoMotive werkt op Android 4.1+.
Kenmerken
- Besturing van 1 tot 20 locomotieven
- Ideaal voor kleine tot middelgrote banen
- 2A belasting (tot ~16 OO/HO locs) met LMD18200; uitbreidbaar met zwaardere H-brug
- Kortsluitbeveiligd met instelbare overstroombeveiliging (in code)
- Lichten, rijrichting, functies F1-F8
- Functienamen, zichtbaarheid, momentaire actie bewerkbaar
- Wissels/accessoires: tot 8 paren uitgangen met eigen namen
- Eigen locnamen en max snelheid per loc
- Programmeren CV1 (adres)
- Read/Write CV 1-255 (alleen betaalde app)
- Eigen accessoire-adressen toevoegen
- DC voeding 12-20V (Z/N/OO/HO/O/G schaal)
Totale kosten: ~€20 (onderdelen via eBay). PCB beschikbaar op eBay.
Stap 1: Arduino Sketch
De Arduino ontvangt via Bluetooth (HC-06) complete DCC-pakketten als tekststrings van de app, decodeert ze en genereert de NMRA-standaard klokpulsen (preamble, separator, data bytes, XOR-check). De LMD18200 krijgt het DCC-signaal op de DIR-pin, PWM-pin blijft HIGH.
Hoofdloop (vereenvoudigd)
void loop() {
if (bluetooth.available() > 0) {
inString = bluetooth.readStringUntil('\n');
}
if (inString.substring(0,1) == "D") { string(); } // DCC pakket ontvangen
delay(20);
}
Voorbeelden ontvangen strings
DD, 3, 63, 12, 48→ 4-byte snelheidspakket: Loco 3, snelheidstap 12, XOR=48DD, 1, 129, 128→ 3-byte functiepakket: Loco 1, F1 aan, XOR=128
NMRA standaard: S-9.2.1
Stap 2: Fritzing Schema & Opbouw

Belangrijk: HC-06 aansluiting: PCB Rx → Module Rx, PCB Tx → Module Tx (geen kruisverbinding!). Antennedraad (31,2 mm koper, geïsoleerd) verlengt bereik.
Stroommeting: 0,1 Ω meetweerstand geeft 0-200 mV op A0 (≈ 50 mA per stap). Bij >2A schakelt Arduino pin 13 (Brake) de LMD18200 uit. Stroomwaarde wordt elke seconde via Bluetooth naar app gestuurd.
Stap 3: Android App
- Gratis: LocoMotive (Google Play Store)
- Betaald (volledig): LocoMotive DCC (Google Play Store, ~€5,99)
- Handleiding bij betaalde versie meegeleverd.
Code: locomotive_dcc_sep19.ino
// 1 Sep 2019 - voor Android App 'Locomotive DCC' met LMD18200
// CV read/write toegevoegd
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(8,9); // RX, TX
int C, sensorValue;
long t=0, lastmillis=0, interval=1000;
String inString;
int a[8];
int preamable_type = 0;
int Address;
float CV_VAL, cv_val, cv_val0, cv_val1, cv_val2, cv_val3, cv_val4, cv_val5, cv_val6, cv_val7;
int test_num, cv_write_val, Cs;
boolean cv_logic, ok;
int num;
#define TIMER_SHORT 0x8D // 58 µs
#define TIMER_LONG 0x1B // 116 µs
unsigned char last_timer=TIMER_SHORT, flag=0, every_second_isr=0;
#define PREAMBLE 0
#define SEPERATOR 1
#define SENDBYTE 2
unsigned char state=PREAMBLE, preamble_count=16, outbyte=0, cbit=0x80;
unsigned char xdata=0, data=0, data_f=0, data_f1=0, data_f2=0;
int locoAdr = 9;
struct Message { unsigned char data[7]; unsigned char len; };
#define MAXMSG 3
struct Message msg[MAXMSG] = {
{ {0xFF,0,0xFF,0,0,0,0}, 3 }, // idle
{ {locoAdr,0,0,0,0,0,0}, 3 } // loco msg (128 stappen)
};
int msgIndex=0, byteIndex=0;
void SetupTimer2() {
TCCR2A=0; TCCR2B= (1<<CS21); // prescaler 8
TIMSK2 = (1<<TOIE2);
TCNT2=TIMER_SHORT;
}
ISR(TIMER2_OVF_vect) {
unsigned char latency;
if (every_second_isr) {
PORTD = B01100000; // D5=DIR, D6=PWM HIGH
digitalWrite(5,1); digitalWrite(6,1);
every_second_isr=0;
latency=TCNT2; TCNT2=latency+last_timer;
} else {
PORTD = B01000000; // D5=DIR signaal, D6=PWM LOW
digitalWrite(5,0); digitalWrite(6,1);
every_second_isr=1;
switch(state) {
case PREAMBLE:
flag=1; preamble_count--;
if (preamble_count==0) { state=SEPERATOR; msgIndex=(msgIndex+1)%MAXMSG; byteIndex=0; }
break;
case SEPERATOR:
flag=0; state=SENDBYTE; cbit=0x80; outbyte=msg[msgIndex].data[byteIndex];
break;
case SENDBYTE:
flag = (outbyte & cbit) ? 1 : 0;
cbit >>= 1;
if (cbit==0) {
byteIndex++;
if (byteIndex >= msg[msgIndex].len) {
state=PREAMBLE;
preamble_count = (preamable_type==0) ? 16 : 24;
} else { state=SEPERATOR; }
}
break;
}
latency=TCNT2;
TCNT2 = latency + (flag ? TIMER_SHORT : TIMER_LONG);
last_timer = flag ? TIMER_SHORT : TIMER_LONG;
}
}
void setup() {
Serial.begin(115200);
analogReference(INTERNAL);
pinMode(13,OUTPUT);
bluetooth.begin(9600);
delay(500);
Serial.println("Bluetooth Started");
bluetooth.println("Bluetooth Started");
DDRD = B01100000;
SetupTimer2();
t=millis(); lastmillis=millis();
digitalWrite(6,LOW); digitalWrite(13,HIGH); // bridge uit
int get_cv_val = cv_calc(test_num);
}
void current() {
int value=0;
for (int i=0;i<5;i++) { value+=analogRead(A0); delay(1); }
sensorValue=value/5;
C = 10.8 * sensorValue; // mA (interne 1.1V ref, 0.1Ω → 10.8 mA/stap)
if (C > 2000) {
Serial.println("Over Current");
bluetooth.println("Short!");
digitalWrite(6,LOW); digitalWrite(13,HIGH);
bluetooth.println(C);
}
}
void loop() {
if (bluetooth.available()) { inString = bluetooth.readStringUntil('\n'); Serial.println(inString); }
if (inString.startsWith("D")) string(); // DCC pakket
else if (inString.startsWith("C")) { digitalWrite(6,HIGH); digitalWrite(13,LOW); } // reset na overstroom
else if (inString.startsWith("G")) { digitalWrite(6,HIGH); digitalWrite(13,LOW); current(); bluetooth.println(C); } // stroom opvragen
else if (inString.startsWith("A")) { digitalWrite(6,HIGH); digitalWrite(13,LOW); get_cv_data(); cv1_prog(); digitalWrite(6,LOW); digitalWrite(13,HIGH); } // CV1 schrijven
else if (inString.startsWith("get")) { cv_val=0; digitalWrite(6,HIGH); digitalWrite(13,LOW); get_cv_num(); cv_read(); digitalWrite(6,LOW); digitalWrite(13,HIGH); } // CV read
else if (inString.startsWith("add")) { cv_write_val=0; digitalWrite(6,HIGH); digitalWrite(13,LOW); get_cv_new_val(); repeat_cv_write(); digitalWrite(6,LOW); digitalWrite(13,HIGH); } // CV write
else if (inString.startsWith("V")) { delay(50); bluetooth.print("CV1 updated"); Serial.println(Address); }
else if (inString.startsWith("E")) { digitalWrite(6,LOW); digitalWrite(13,HIGH); } // noodstop
inString="";
}
// Helper functies: string parsing, packet assembly (3/4 byte), CV read/write/verify, etc.
// Zie volledige code in origineel voor details: cv_calc, cv_read, cv_write, repeat_cv_write,
// reset_packet, page_preset_packet, cv1_write_packet, cv_verify0/1_packet, valid_packet,
// amend_len3/4, assemble_3/4_byte, print_data, get_cv_num, get_cv_data, get_cv_new_val.
Behuizing & Schema

Schema: Fritzing-bestand bluetooth_android_dcc_lmd18200_S8NTVsI4LY.fzz + app-instructies.
Productieproces
- MrRobot: Ubuntu Mobiel-Gestuurde Rapiro Robot met Stem, Touch & Schud Interactie
- Arduino-gestuurde 6-Shooter Drank Mixstation – Bouw je eigen Cocktail Automaat
- Arduino Digitale Dobbelsteen: Bouw Je Eigen LCD-willekeurige Getalgenerator
- DIY Arduino USB Gaming Controller – Bouw Je Eigen High-Performance Gamepad
- Bouw Boeiende LCD Animaties & Games met Arduino UNO
- Slimme Zelfzittende Schoenen met Ingebouwde Energie-opwekking
- Realtime afstandsmeting met Arduino Sonar & Processing visualisatie
- Pixel Chaser: Interactieve één-tik LED-spel met Arduino Nano
- Naadloze LED-dimmer met Bolt IoT en Arduino UNO
- Bouw een $10 Draagbare Arduino Weerstation (AWS) – Eenvoudige DIY met Nano, DHT22, BMP180 & LCD
- Python 3 naar Arduino UNO: Eenvoudige Commando Besturing en LED Demo