Simple Code Example -- Arduino to DCC++ Arduino ???

Joey Paul Jan 13, 2019

  1. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Folks,

    My first post here! I am a little successful with Arduino but not yet started DCC++ nor do I have a DCC decoder as yet. I think I understand the DCC++ Arduino and motor shield build, but all I want to do (at first) is hard code in an Arduino sketch a few lines that will do very simple things like just start a loco in one direction at a fixed speed, and stop it later. So I guess that means serial out from one Arduino to serial in on the DCC++ Arduino/motor shield set-up. I learn by examples, so if someone can point me to some simple code examples, I would be able to take it from there, hopefully. I looked at Dave Bodnar's examples, but I cannot pick out just what I need. Perhaps I am missing the forest for the trees, or just naively thinking it's going to be simple.

    So once I receive my new hardware (another uno, a motor shield and a decoder that will handle a 0.5 amp motor), I want to see if I can get the JMRI running from a MAC (I am not a MAC aficionado, but it's a new machine), but later all I want to do is very simple control from an Arduino that may also be running other things, like controlling servos for animation, no computer or Raspberry Pi afterward. (I am not a model railroader but on the fringe of the 3 rail O gauge hobby. An HO decoder will work for some of my unusual projects.)

    Thanks!

    Take care, Joe.
     
    Last edited: Jan 13, 2019
  2. Onizukachan

    Onizukachan TrainBoard Supporter

    752
    1,198
    24
    I have jmri on a Mac mini (my otherwise dedicated home server mac) , running to my dcc++ system to run a short test track and programming track in front of the tv. I chose to use a mega in case I ever wanted to run it via WiFi from the Mac instead of serial.
    I later decided to do JMRI on a 3b+ PI with a 5” touchscreen as the head, and build another mega based dcc++ for table top railroad duty.

    I am not sure what you mean by running dcc on the Arduino itself, to me the benefit of dcc++ is that it is a low cost way to make JMRI useful without having to spend $200 on a manufacturer control system and adapter.
    I think you will find that the Arduino is marginal on performance for what you have planned to do with it, but I may be wrong! Best of luck.
     
  3. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Thanks for the reply and info! Sorry I wasn't more clear. I just want to control a DCC loco from an Arduino which would send commands by serial to the Arduino that has DCC++ installed with the motor shield on top. So, at first, I'd like to just get a loco to run forward at a fixed speed, then stop when I want, hard-coded in a sketch, serial out to the other Arduino running DCC++. So I know this doesn't seem like it's worth the effort, but it is a beginning for more complex automation later, but not a throttle that I control or JMRI automation, just pre-sets from an Arduino sketch. Similar to what is done in this vid, but not exactly, I guess:



    Take care, Joe.
     
  4. Jimbo20

    Jimbo20 TrainBoard Member

    274
    178
    11
    My setup works in a similar way to your suggestion. I have dcc++ running on an Arduino Nano, then I have an ESP8266-01 serially connected to the Nano. The ESP serves two functions:
    1) It allows Wifi access of a modified Dave Bosnar Throttle.
    2) It runs an automatic railbus shuttle sequence. This is done by sending serial railbus operating commands to DCC++ and monitoring the magnetic sensor data sent back from DCC++. The railbus is brought in to platform 1, there it pauses for a minute or so, then drives away again out of site, pauses again. then a couple of turnouts are automatically thrown, and the railbus comes back in to platform 2. The whole sequence repeats continuously and the controlling code that does this is all on the ESP8266-01. There is no reason why the code couldn't be installed on a second arduino instead of an ESP. The reason I used the ESP is that I wanted its WiFi capabilities to allow wireless manual control of a second loco (and also I can stop/pause the railbus manually if wanted).

    I wrote the code over a year ago. It isn't pretty and developed more by trial and error! A problem is that my hobby is on hold at the moment due to my recent house move and everything is currently still boxed up. I can't wait to get it all out and continue again in the next month or two!

    Here is a video I made of the railbus. Note that it was running completely under the automatic control of the ESP8266-01.



    Jim
     
    Mark Ricci likes this.
  5. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Jim,

    Thanks for the reply and info! Great video, too! I can certainly wait until you can share a snippet of your code. No rush for me; I still need to get the hardware together. My coding is never elegant. I judge success by how it works. And you got a perfect result!!!

    (I still haven't fully unpacked from a move 25 years ago!)

    Take care, Joe.
     
  6. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Folks,

    I waiting for the Arduino motor shield and looking at the "<Minimalist Dcc Controller sample>" which is the first sketch that loads when opening the "DCCpp_Uno.ino." Is this sketch controlled buy your computer keyboard and the serial monitor?

    Thanks! Take care, Joe.
     
  7. John W Zerbe

    John W Zerbe TrainBoard Member

    96
    59
    7
    Hello Joey,
    Yes, absent anything else to talk to your new dcc++ controller, you can use the serial monitor in the arduino dev package to type in the commands that dcc++ acts on.
    example: the first one you want to send is "<s>". This tells dcc++ to send you what it knows about its status.

    There are a number of "dcc++ throttle" projects that do exactly what you describe that you want to do with the second arduino. ie your second arduino can connect to the first one via usb and do things like watch for button presses, potentiometer changes, etc and send text strings (dcc++ commands) to the serial interface in response.

    I did a little of this myself when I first build the DCC++ project. I then got a raspberry pi 3b, installed JMRI on it and connected it the arduino. I also have the arduino dev software on the pi as well.

    With the jmri software running I can now control trains from my phone which talks to jmri.
     
  8. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi John,

    Thanks for the reply!

    So the base station can receive serial data from either the IDE or another Arduino. So that seems simple enough!

    I am still waiting for my boards from Banggood.

    Take care, Joe
     
  9. Robert Owen

    Robert Owen TrainBoard Member

    51
    5
    6
    Hi Joe. Did you find code to implement PWM on the track? I am just starting with Arduino and trying to get an engine to go forwards and backwards so I can develop other features from there. The DCC packet structure I understand but am trying to find a sketch that places '0's and '1's onto the track. As I understand a '0' is a 116microsecond square wave and I need a sketch to command a motor shield to produce this.
     
  10. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Robert and Everyone,

    I just got my first decoder today https://amzn.to/2WL8i3P Digitrax DH126D, and it is so tiny! So I also finally built the DCC++ base station. I've only tested JMRI Panel Pro with the base station (nothing on track yet). Tomorrow I will install the decoder. I now want to try to get one Arduino to send serial commands to the Arduino/motor shield base station. I don't want to use JMRI. So this is a new learning experience for me. These decoders are so small, you can fit them anywhere, even a slot car. I had a hard time getting to the correct port for JMRI, but all seems good. If anyone has just the briefest code example for sending serial DCC++ packets from one Arduino to another, please let me know.

    Will keep everyone posted! (I followed this tutorial for the base station: I am using a MAC for both the Arduino IDE and JMRI Panel Pro.)

    Take care, Joe.
     
  11. Robert Owen

    Robert Owen TrainBoard Member

    51
    5
    6
    Great news Joe. Let us know how you got on. The code I wrote to get the train to move in one direction is given below.

    Robert

    const uint8_t In3 = 7;

    const uint8_t In4 = 6;

    const uint8_t bit_timings[2] = {100, 58};



    struct Packet{

    uint8_t address[8];

    uint8_t command[8];

    uint8_t XOR[8];

    } train_1 = {{0, 0, 0, 0, 0, 0, 1, 1}, // 8-bit address

    {0, 1, 1, 0, 1, 1, 1, 1}, // 8-bit commando

    {0, 1, 1, 0, 1, 1, 0, 0}; // 8-bit XOR error check. Manually set XOR, needs to change every time direction is changed. May be replaced by XOR code below, but not tried yet.

    };



    //train_1.XOR = train_1. address^ train_1[command ; // XOR first two bytes. I have not tried this yet



    void output_bit(uint8_t bit_val)

    {

    digitalWrite(In3, LOW);

    digitalWrite(In4, HIGH);



    delayMicroseconds(bit_timings[bit_val]);



    digitalWrite(In3, HIGH);

    digitalWrite(In4, LOW);



    delayMicroseconds(bit_timings[bit_val]);

    }



    void goStraight(struct Packet train)

    {

    uint8_t i;



    //Send Packet preamble. send 12 Ones

    for (i = 0; i < 12; ++i) {

    output_bit(1);

    }



    output_bit(0);

    //send Address byte

    for (i = 0; i < 8; ++i) {

    output_bit(train.address);

    }



    output_bit(0);

    //send Instruction byte

    for (i = 0; i < 8; ++i) {

    output_bit(train.command);

    }



    output_bit(0);

    //send Error Detection byte

    for (i = 0; i < 8; ++i) {

    output_bit(train.XOR);

    }

    output_bit(1);

    }



    void setup()

    {



    pinMode(In3, OUTPUT);

    pinMode(In4, OUTPUT);



    // Initialise outputs(?)

    digitalWrite(In3, HIGH);

    digitalWrite(In4, LOW);



    }



    void loop()

    {



    goStraight(train_1);



    }
     
  12. FlightRisk

    FlightRisk TrainBoard Member

    548
    237
    14
    Sorry if I am a little confused as to what you guys are trying to do, but the whole point of DCC++ is not having to know how to code at the level of packets, let alone 1's and 0's. It generates the packets and creates the PWM signal for you. You just send simple text commands. So your other Arduino would do what JMRI does, send this:

    https://github.com/DccPlusPlus/BaseStation/wiki/Commands-for-DCCpp-BaseStation

    Maybe I misunderstood your need.

    Also, if you want automation, take a look at what Gregg already built into DCC++. It is here:
    https://github.com/DccPlusPlus/BaseStation/tree/development/DCCpp_Uno

    If you know how to navigate GitHub, this is his development branch. You can figure out his autopilot and eggtimer code that sends simple strings to control everything. His video with random trains that leave the staging area and come back on their own is pretty amazing.

    We have picked up development of DCC++ and have updated the current version and are creating the next version DCC++ EX. The DCC++ update project 2020 thread is an ongoing discussion. We are trying to move everything over to the GitHub.com/DCC-EX repository and organize all the documentation.

    On top of all that, the Locoduino library version of DCC++ may be a possible way to do what you want.
     
    Mark Ricci and Joey Paul like this.
  13. Robert Owen

    Robert Owen TrainBoard Member

    51
    5
    6
    Hi FlightRisk. I realise that DCC++ includes all code for an Arduino based DCC system but I want to write my own code. This includes putting 0s and1s onto the track after constructing a DCC train control packet. Joey Paul appears to have the same idea and asked if any member had code to place 0s and 1s on the track to move a train. I added my code to this above.
     
  14. FlightRisk

    FlightRisk TrainBoard Member

    548
    237
    14
    Ok, I understand now :) I've been researching for a while to see what else is out there while we work on expanding DCC++ to DCC++ EX and while some people are re-inventing the wheel because they didn't know about other resources, there is so much out there! There are at least two DCC libraries, on from NMRA and one from MynaBay. I've seen a lot of other people write their own code to do the same thing. Then there is the Locoduino library that is a wrapper around DCC++ which has it's own code for packet generation. I'm still compiling lists of it all so we can try to have links to things all in one place. I'll try to keep up with what you are doing too. Are you reading and writing CVs too? That would require the ability to read the current pulse acknowledgement. Or are you just interested in moving the trains?
     
  15. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi FlightRisk, Robert and Everyone,

    So later today I will try to send commands to the DCC++ base station from the serial monitor in the Arduino IDE. (I still haven't installed the decoder in my motorized item.) So after that, I want to try to write a sketch that will send serial data from one Arduino to the Arduino/motor shield base station. Once I can successfully send serial to the base station, I think I'm good. I have used a Bluetooth module with the Picaxe 18M2, but I've never done serial in/out with the Arduino. I'm very rusty with the code. This is all an experiment at this point. This is not a typical installation. I am using O gauge 3 rail track with a motorized unit (similar to what's in my Avatar) that pulls only 0.5 amps and I rum on about 7-8 VDC, so the HO decoder should work. But in the O gauge environment, there might be spikes since the solenoids in the turnouts are track powered, part of their non-derailing feature. And I have used a capacitor-discharge circuit with them. So I don't want my computer connected while I try these things. So nothing risky with the computer attached to the Arduino; no turnouts, just a simple loop of track. My main reason for going with a DCC decoder is their very tiny size, and I want to try the back-EMF feature of these decoders. I will keep everyone posted (and have a little video of it). At this point in my life, I get more enjoyment from experimenting than running, but I still love running stuff. If I don't fry the decoder, then I'll go Robert's path and try to write code for the shield, but that's way over my head at this point.

    Thanks for the kind help!

    Take care, Joe.
     
    FlightRisk likes this.
  16. Robert Owen

    Robert Owen TrainBoard Member

    51
    5
    6
    Hi Joe and Flight Risk.
    I am interested in writing code to control real time hardware, such as trains. I did not go the DCC++ route because it is to complex for what I want. I have a planned layout with 5 trains that I want to completely automate, with no involvement from an operator. On one line trains will run in opposite direction on the same track. In other parts trains will go across crossings while another train is heading for it on a different track. I want Arduino to know where each train is and stop crashes either by temporarily stopping one of the trains or by temporarily routing a train via a switch. Getting a cost effective way of train location will be the tricky part. Each train to move randomly where I can sit back and look at what happens. I have an N gauge layout in my head which will be modeled on a Canadian Rockies mining scene and inclines dated around the 1900's to 1920's (getting steam trains from this era will be a challenge). N gauge because I am space limited. I may never get round to building scenery as the real time control by Arduino is what I am interested in.
     
    FlightRisk likes this.
  17. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Robert,

    I saw somewhere where RFID with Arduino was used with model trains. They may be able to tell you where a certain train is at any given time. I saw these little FRID tags https://www.sparkfun.com/products/15116 They might fit inside N scale rollingstock.

    The DCC++ base station sets up in no time and cost me about $11 for both components. If all I'll need to do is send a serial string like <t 1 03 20 1> to the base station, that saves a lot of code writing. All I eventually want is basic stop/start with consistent speed up and down grades, and throw turnouts from the Arduino (which I already have done). With 3 rail track, train detection is easy if you insulate an outside rail. I know in the UK they had 3 rail OO with the center "stud" rail.

    I have cheated the minimum curve in HO and N scale quite a bit (12" radius in HO). You might be able to use HO in the same amount of space as an N scale plan, especially with old-style steam, like little 0-4-0 Porters. Just a thought.

    Take care, Joe.
     
  18. Robert Owen

    Robert Owen TrainBoard Member

    51
    5
    6
    Hi Joe.
    I thought of RFID but the readers are expensive. If I know where a train is at the start I should be able to track it as it moves past Hall Effect or IR sensors. I will probably put in one or two RFID sensors just to make sure that tracking using Hall Effect is accurate. If I know a train is moving clockwise round a track, I can predict the next sensor it will pass and take note when it passes it. RFID sensors are quite big as well which makes them hard to hide. N is a challenge as there is not much room onboard to place electronics, particularly small steam trains.

    Best wishes
    Robert
     
  19. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Everyone,

    Well, thanks to Everyone here, before I get carried away!

    I used info in the link FlightRisk posted above: https://github.com/DccPlusPlus/BaseStation/wiki/Commands-for-DCCpp-BaseStation

    I couldn't see the forest for the trees!

    This morning I realized how simple it might be to do. I thought it would be much more complicated. Just serial out (Serial.print) from one Arduino into another! My first attempt worked!

    The DCC++ base station with the following test code on another Arduino Uno connected together by the TX to RX pin on the base station, ground and 5 VDC also:

    Code:
    void setup() {
      Serial.begin(115200);
    }
    
    void loop() {
    
      Serial.print("<1>"); // turns track power on
      delay(10000); //delays 10 seconds
      Serial.print("<t 1 03 100 1>"); // loco #3, 100 speed (0-126 possible) the last "1" is for forward
      delay(10000);
      Serial.print("<t 1 03 40 1>");  // speed at 40
      delay(10000);
      Serial.print("<t 1 03 70 1>");  // speed at 70
      delay(10000);
      Serial.print("<t 1 03 70 0>"); // the last "0" for reverse
      delay(20000); // delays 20 
      Serial.print("<t 1 03 70 1>"); // back to forward
      delay(20000);
      Serial.print("<0>");  // turns track power off
      delay(30000); // delays 30 
    
    }
    
    I'll have a video later!!!!

    Take care, Joe
     
    OzLodger, FlightRisk and Jimbo20 like this.
  20. Joey Paul

    Joey Paul TrainBoard Member

    34
    11
    3
    Hi Robert,

    I am no expert, but I have used the Arduino to control relays and servos, and now just starting with the DCC++ base station.
    Here is how I used a servo for animation, the code is so very simple:


    Take care, Joe
     

Share This Page