DCC++ Hardware - Throttles

KE4NYV Jan 25, 2016

  1. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    Scott Eric Catalano likes this.
  2. Steve S

    Steve S TrainBoard Member

    95
    22
    8
    To Dave Bodnar, how do you charge the cell battery? Do you have to remove it, or is there a charging port somewhere?

    Hammond Mfg had a 3D file of their enclosure, so I whipped this up in Blender to give an idea what it would look like.

    [​IMG]

    Steve S
     
    Scott Eric Catalano and sboyer2 like this.
  3. David Bodnar

    David Bodnar TrainBoard Member

    264
    481
    13
    That looks nice, Steve - well done!

    As to charging, I have not yet added a charging port to the Nextion version of the throttle but it will work the same as on the other throttle. There will be a JST connector that goes through the edge of the case that will connect directly to the battery.

    dave
    [​IMG]
     
    Scott Eric Catalano likes this.
  4. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Last edited: Sep 2, 2016
    Scott Eric Catalano likes this.
  5. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    I have some ESP8266 modules, and I am still waiting for the Arduino shields for them to arrive from Thailand. I have never used them, so I will be interested to hear how you use them. I got them purely for educational reasons, and I have been disappointed with the lack of "complete" documentation for them.

    not sure if it will fit your application, but I have heard good things about the Raspberry Pi. I have not used any, but I hear they are quite versatile. I have seen magazine articles of a Pi being built into a case like a tablet, with a touchscreen TFT.

    ~Travis
     
    Scott Eric Catalano likes this.
  6. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Travis,

    Well I'm the resident ESP8266 man on here. It is a very capable chip, and much faster than the 8 bit Arduino's.
    It is also very cheap ! If you don't need a stack of GPIO for your application, then I recommend it over the Arduino's.
    You can leave the WiFi turned off and just use the Mcu what's not to like?

    Steve.
     
    Scott Eric Catalano likes this.
  7. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    I have 4 of these:
    http://www.ebay.com/itm/221989321181

    I have heard those ones are pretty basic though.

    ~Travis
     
    Scott Eric Catalano likes this.
  8. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Basic, yes but you can do a lot with them, say a basic wifi server interface for Base Station for instance.
    Give me a shout when you'd like to do some projects with them.

    Back to my other issue.

    If I run this on an Uno. Output is as expected.
    Code:
    uint32_t test = 0b01101011001101001101001001101011;
    
    void setup() {
      Serial.begin(115200);
    
      for (int j = 0; j < 32; j++) {
        test = test ^ (1 << j);
        Serial.println(test, BIN);
      }
    }

    Steve.

    Actually NO. When the above gets to bit 16

    This happens

    1101011001101001010110110010100
    10010100110010110010110110010100

    Bits 16 to 32 all get inverted at the same time.
     
    Last edited: Sep 2, 2016
    Scott Eric Catalano likes this.
  9. Travis Farmer

    Travis Farmer TrainBoard Member

    352
    320
    14
    that is a 33-bit binary... looks like you are overflowing your 32-bit unsigned long. I noticed the same when I ran it on my MEGA2560. I am wondering now if the Arduino is the right platform for your project, as I don't think it supports higher than unsigned long.

    ~Travis
     
    Scott Eric Catalano likes this.
  10. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    All,

    There may be a workaround for the above
    Oops I cant count,

    More testing, as we actually only use 29bits. I've run it on ESP and it works correctly. ESP will be the target platform.

    Thanks Travis.

    S.
     
    Scott Eric Catalano likes this.
  11. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Nope,

    Same result, Arduino has let me down. Maybe someone could fix this as it's a very slick solution.

    I'm going to port the whole sketch to ESP.
    Inadvertently, this demo has created a little game that will test the whole concept and provide a little fun at the same time.

    The display is looping through 5 data sets and lighting buttons every 2 seconds. I've been playing a kind of whack-a-mole as I
    try to light all the buttons, then extinguish them all again. This proves the sketch is working at both ends, and tests the hardware input
    as you go. I'll be back soon with results and the working code if all goes well with the ESP.

    S.
     
    Scott Eric Catalano likes this.
  12. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    All,

    This little nugget "If you are using an unsigned long (32 bit) variable foo, and have to change a bit, use the macro LONGBIT which creates un unsigned long mask. Otherwise, using the BIT() macro, the compiler will truncate the value to 16-bits.[/]"

    from here http://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?page=all
    might be pointing to the problem.

    However it's all beyond my understanding at the moment, what an earth is "macro LONGBIT" ???

    S.
     
    Last edited: Sep 2, 2016
    Scott Eric Catalano likes this.
  13. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Dave,

    I noted you're running the new throttle at 3+volts. Have you had any issues especially with serial, as I'm pretty sure the spec says the display is a 5v device.
    Under power can cause some serious issues.

    From https://www.itead.cc/wiki/NX4024T032

    There maybe some buck converter circuitry onboard and as your battery can supply high current,
    you're just getting away with it.

    CaptureNex.JPG

    Steve.
     
    Last edited: Sep 2, 2016
    Scott Eric Catalano likes this.
  14. David Bodnar

    David Bodnar TrainBoard Member

    264
    481
    13
    Steve - I have used it with 3.7 volts (single LiIon cell) and with 5 volts and, other than a slightly dimmer backlight, both work well - I have not done extensive tests but have seen zero issues to date.

    I wanted to keep the case as small as possible so a single cell was best - the throttle draws only 110 ma giving a 6+ hour run time on the cell I am using - I also tried a small 3.7 to 5 volt converter and it worked fine but the current draw doubled.

    dave
     
    Scott Eric Catalano likes this.
  15. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    OK thanks,

    Have you had chance to get to grips with that sketch I posted ?
    The more I work on it, I've begun to realise I may have stumbled on something quite significant here.

    Bit bashing can save a lot of time and effort coding designs such as ours, especially moving data to the display and dealing with return input.
    I'll be reworking quite a bit of my code now I've learnt a thing or two in the last few days.

    Steve.
     
    Scott Eric Catalano likes this.
  16. Atani

    Atani TrainBoard Member

    1,474
    1,781
    37
    Why not use bitset/bitget rather than maintain your own or/xor/and/shift/etc...
     
    Scott Eric Catalano likes this.
  17. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    Hi Mike,

    Just to simplify things really. There is no Arduino bitflip (XOR) that I know of.
    So instead of having to check and change accordingly, XOR does what I need in one operation.
    As you will see from the code I'll be posting shortly.
    All we need to know is that a key got hit on the display, doesn't matter what it's state was.
    XOR flips the state in memory and all is good. Next refresh sets all the key states as they are in memory so there's little room for error,
    save for a missed bit here and there. Not critical for our function buttons.

    I've surpassed even my best expectations as to how simple and effective the working code is.

    Steve.
     
    Atani and Scott Eric Catalano like this.
  18. UK Steve

    UK Steve TrainBoard Member

    453
    683
    12
    All,

    I ported to ESP8266, and can report the sketch works beautifully.
    I hope someone can fix the problem for Arduino, I have little interest in doing it myself.

    Code:
    #include <SoftwareSerial.h>
    
    SoftwareSerial NexSerial(4, 5);
    
    const char ter [3] = {0xff, 0xff, 0xff};//Terminating characters
    int f;
    byte x;
    long lastMillis = 0;
    
    int loco [5] = {
      1024,
      17,
      2820,
      376,
      2016
    };
    
    uint32_t fnbtns [5] = {
      0b0001000100010110010001111110011,
      0b0010001101000100011101000110010,
      0b0000101100100010100101101001010,
      0b0011001110010100001001100011000,
      0b0000101101001001100010001001010
      };
    
    uint32_t test = 0b1101011001101001101001001101011;
    
    void setup() {
      Serial.begin(115200);
      NexSerial.begin(115200);//Make sure your display is set to this baud, or amend if you need it slower.
    
      for (byte j = 0; j < 32; j++) {//Tests the MCU to make sure the XOR function works properly.
        test = test ^ (1 << j);
        Serial.println(test, BIN);
      }
    }
    
    void setFnButtons() {//Sends 29 strings to the Nextion to set the Funtion keys accordingly.
      for (int i = 0; i < 29; i ++) {
        int y = (fnbtns[f] >> i) & 1;// i = 0..28.  stores nth(i) bit of fnbtns[] in y.  y becomes 0 or 1.
    
        NexSerial.print("bt");//No library needed here !!!
        NexSerial.print(i);
        NexSerial.print(".val=");
        NexSerial.print(y);
        NexSerial.write(ter, 3);
      }
    }
    
    void setFnBit() {
      fnbtns [f] = fnbtns [f] ^ (1 << x);
      Serial.println(x);
      if (x < 5) {
        sendFn0_4();
      } else if (x < 9) {
        sendFn5_8();
      } else if (x < 13) {
        sendFn9_12();
      } else if (x < 21) {
        sendFn13_20();
      } else {
        sendFn21_28();
      }
    }
    
    void sendFn0_4() {
      byte mask = 31;
      byte fn = fnbtns[f] & mask;
      Serial.print("Binary = ");
      Serial.println(fn, BIN);
      Serial.print("<f");
      Serial.print(loco[f]);
      Serial.print(" ");
      Serial.print(fn + 128);
      Serial.println(">");
      Serial.println();
    }
    
    void sendFn5_8() {
      int mask = 15;
      int fn = fnbtns[f] & mask << 5;
      fn = fn >> 5;
      Serial.print("Binary = ");
      Serial.println(fn, BIN);
      Serial.print("<f");
      Serial.print(loco[f]);
      Serial.print(" ");
      Serial.print(fn + 176);
      Serial.println(">");
      Serial.println();
    }
    
    void sendFn9_12() {
      int mask = 15;
      int fn = fnbtns[f] & mask << 9;
      fn = fn >> 9;
      Serial.print("Binary = ");
      Serial.println(fn, BIN);
      Serial.print("<f");
      Serial.print(loco[f]);
      Serial.print(" ");
      Serial.print(fn + 160);
      Serial.println(">");
      Serial.println();
    }
    
    void sendFn13_20() {
      uint32_t mask = 255;
      uint32_t fn = fnbtns[f] & mask << 13;
      fn = fn >> 13;
      Serial.print("Binary = ");
      Serial.println(fn, BIN);
      Serial.print("<f");
      Serial.print(loco[f]);
      Serial.print(" ");
      Serial.print("222 ");
      Serial.print(fn);
      Serial.println(">");
      Serial.println();
    }
    
    void sendFn21_28() {
      uint32_t mask = 255;
      uint32_t fn = fnbtns[f] & mask << 21;
      fn = fn >> 21;
      Serial.print("Binary = ");
      Serial.println(fn, BIN);
      Serial.print("<f");
      Serial.print(loco[f]);
      Serial.print(" ");
      Serial.print("223 ");
      Serial.print(fn);
      Serial.println(">");
      Serial.println();
      Serial.println();
    }
    
    void loop() {
    
      unsigned long currentMillis = millis();
    
      if (currentMillis - lastMillis > 2000) {
        lastMillis = currentMillis;
        f++;
        if (f == 5) f = 0;
        setFnButtons();
      }
    
      while (NexSerial.available()) {
        int func = NexSerial.parseInt() - 1;
        if (NexSerial.read() == '>') {  //Example format <21>
          x = func;
          setFnBit();
        }
      }
    }
    
    If we take out the Debug, test and print runs, there's some nice simplicity about the whole routine.
    To make it work, all we send is a key number from the display and that is it !
    Off to play whack-a-function with 29 keys:).

    Steve.

    Update. If you'd like to try the sketch without the display.
    Change all NexSerial entries to just Serial.
    Comment out Software serial entries at the top.
    Run and open the serial monitor. Send key numbers 1-29
    In the format <17>.
     
    Last edited: Sep 2, 2016
    Scott Eric Catalano likes this.
  19. David Bodnar

    David Bodnar TrainBoard Member

    264
    481
    13
    Steve, other than looking it over for a time I have not done anything more with it - my objective right now is to get the code for the Nextion throttle in better shape. Great fun!

    dave
     
    Scott Eric Catalano likes this.
  20. Atani

    Atani TrainBoard Member

    1,474
    1,781
    37
    replace the "1" with "1UL" in your bit shifts and it should work. The default size for a number is a 16bit signed integer. When you get to the 15th shift you end up with something like: 0xFFFF8000 when you would have expected 0x00008000 instead. Thanks Arduino C library for being "helpful"....
     
    Scott Eric Catalano likes this.

Share This Page