DCC++ Throttle on basestation Arduino Uno

Fred001 Aug 23, 2020

  1. Fred001

    Fred001 New Member

    3
    0
    1
    Hi All,

    I am newbie to model trains and to DCC++ and needed some help.
    I set-up my railway with a Arduino Uno Basestation running the latest version of DCC++. My aim is to have a pot connected to one of the analogue pins of the uno that I can use to control the speed of a train on the track.

    I had a look around for inspiration and found some useful pointers on https://www.trainboard.com/highball/index.php?threads/dcc-hardware-throttles.90315/, but not exactly what I wanted to do.

    Having a look through the code I concluded that the serial command inputted into the serial monitor on Arduino IDE is translated into
    Code:
    void SerialCommand::parse(char *com)
    taking this into account I managed to successfully set the speed of the train in the
    Code:
    void loop()
    on the DCCpp_Uno sketch:
    Code:
    SerialCommand::parse("t 1 1 20 1")
    setting the speed to 20.

    From what I understand the data is passed as a char, meaning when typed in between "" it works, but as soon as I introduce a variable to change speed it no longer works because the data passed between the .ino sketch and the .cpp sketch is no longer what the DCC++ code is expecting. I did manage to pass a variable x as an integer like so:

    Code:
    int x = "t 1 1 20 1";
    SerialCommand::parse(x);
    However as soon as I try to swap the x variable to x + a variable speed:
    Code:
    int x = "t 1 1 " + y +" 1";
    I get a error invalid operands of types 'const char*' and 'const char [3]' to binary 'operator+'

    So I am not sure there is a way of using the function:
    Code:
    SerialCommand::parse()
    Does anyone have a way to use this function or am I looking at this the complete wrong way and I should be using a different function referenced in the loop() function, which I can pass a variable value too?

    Thanks for your help! :)
     
  2. Sumner

    Sumner TrainBoard Member

    2,835
    5,969
    63
    This might or might not be of help because I don't have the coding knowledge to help you directly but Dave has the sketch he is using for his throttles on his site here...

    http://www.trainelectronics.com/DCC_Arduino/DCC++/Throttle/index.htm

    Possibly looking at it might give you what you want. He uses a pot on one and a decoder on the other and isn't hooked directly to the Uno but sends via the serial port,

    Sumner
     
  3. Quax

    Quax TrainBoard Member

    27
    5
    8
    Hi!
    The parser function expects a string variable as input (a reference to a sequence/array of chars finished with "\0") an then analyzes this string to perform the desired action by calling other functions. You are passing an int variable to the parse() function which won't work. (The error message itself refers to the "+" operator which is not applicable to string concatenation).

    I guess that your intention is to construct a string variable which is then passed to the parser to be interpreted there to perform the desired speed change. I think that this is possible, but it may be easier to directly address the setThrottle(char *s) function and bypass the parser.

    However, if you don't want to implement a number of changes in DCC++, you should consider David Bodnar's wired / wireless throttle designs.
     
    Last edited: Aug 23, 2020
  4. Fred001

    Fred001 New Member

    3
    0
    1
    Thats exactly what I though, but when I try to use a String it doesn't look like the parse() fuction accepts a string:
    Code:
    String x = "t 1 1 20 1";
    SerialCommand::parse(x);
    I get an error:
    Code:
    no matching function for call to 'SerialCommand::parse(String&)'

    In regards to setThrottle(char *s) how about do I got implementing this in DCCpp_Uno.ino sketch? I assume I need to declare setThrottle at the start?

    In the meantime I will have a closer look at Dave's code, hadn't identified how he actually sets the throttle speed.
     
  5. Fred001

    Fred001 New Member

    3
    0
    1
    Hi, just had an opportunity to look at David's code, looks like he just uses serial.print() to send the throttle data, but that only prints on the serial monitor...

    Also looked at the option to use:
    Code:
    RegisterList::setThrottle("1 1 20 1");
    But I am getting an error which I can't seam to brush off. Any ideas how this can be used?
    Code:
    cannot call member function 'void RegisterList::setThrottle(char*) volatile' without object
    Although I am wondering if I will have the exact same issue in converting a int (speed) to a string (throttle order) and back to an int for passing over. How is this conversion done? I have seen forums using iostream and string. is this the best option?

    Thanks for your help :)
     
  6. FlightRisk

    FlightRisk TrainBoard Member

    548
    237
    14
    That is the latest version of DCC++ Classic, but just making sure that you know that DCC++ Development is advancing as DCC++ EX. In our repository there is BaseStation-Classic and Base-Station-EX (which will be merged into CommandStation-EX and is the future of DCC++). You can find more on the website: https://www.dcc-ex.com. Even if you continue to use DCC++ Classic, you should get it from our site or installer since Gregg's code hasn't been touched in several years and we did fix ACK detection and a few things in that code, but can't fix a few leftovers that would have required a complete rewrite. Therefore, we just created a new version ;)

    Without really spending time thinking this through to completion, you can read sensors using DCC++ and use that to sent a throttle command or you could write your own code in the main loop to to read an analog pin. I need to see what effect, if any, that would have on the program. You can sent the "<t> command to the parser or directly call setThrottle, but you can't do it from where you are trying to do it. I'll look at the code tonight or you can post a question in the Discord channel where some of the other folks can answer you probably fairly fast: https://discord.gg/y2sB4Fp
     
  7. FlightRisk

    FlightRisk TrainBoard Member

    548
    237
    14
    You could try to do analogRead() in the main loop in the .ino file, then call this with the values you need substituted in. This will interfere if you are using something like JMRI which won't know you changed the throttle and you need to know the register assigned to the loco:

    const char* s = "1 2 60 1"; // <REG CAB SPEED DIRECTION>
    mainRegs.setThrottle(s);
     

Share This Page