Close
0%
0%

Not Just Another Coffee Table

Custom coffee table with a DCC train track, automation, LEDs and a web interface

Similar projects worth following
Model trains are fun and cool but they can take up a lot of space. This project is about compressing that fun into a fully functional piece of furniture that keeps the partner happy but lets the kids play and gives us a chance to express our hacking desires.

The key design criteria for the coffee table are;

Functional living room table - no mess and nice to look at
Additional practicality features - USB charging ports for devices, storage for living room "stuff"
Fun layout and interesting design
Interactive train and lighting control - easy to use, kid friendly
Automation for added flair

With these criteria in mind, we're documenting on Hackaday as a way to show off what we've achieved, what's failed and all the lessons learned along the way.

The project details will expand as we progress, however, for now these diagrams outlay the main project design as it currently stands;

  • 1 × Raspberry Pi "Brains" of the operation
  • 1 × Teensy 3.2/LC Teensy used to handle effects
  • 1 × Sprog DCC Controller DCC controller for handling DCC interface for controlling the trains
  • 1 × LED Lighting Various LED lighting options

  • Raspberry Pi - Sprog - DCC Train Control

    Jack Wells19 hours ago 0 comments

    The model train world has moved far forward from the old-school days of analogue current motor control. It's now possible to have multiple trains on a track with sound effects, lights, and motors, and control these trains with ease. DCC (Digital Command Control) is the cool new way to do this. It's a command protocol on the rail lines that allows for addressing  and commanding of individual trains on a shared "network" of rail line. DCC  can be thought of as quite similar to an i2c or rs482 communications bus but also supplying power at the same time as data. We're planning to use, likely 3, N-scale locomotives for our train layout that all have DCC decoders built into them. To interface to the DCC decoders on the trains we're using the Sprog 3 Command Station.

    Sprog 3

    The Sprog 3 is a simple USB based DCC controller that allows for both programming and running of devices on a DCC rail network. It's a really small packaged device and it works on a simple serial command interface. Traditionally it's connected to a PC or Raspberry Pi running JMRI which is a super powerful program that handles reprogramming of devices, track layouts and automation and a tonne of other stuff; it's actually over powered for what we're looking to do and I'm excited for the opportunity to create my own interface for working with the Sprog. To be fair, another reason we're using this controller is it was repurposed from a previous project so essentially for this project it was free.


    DCC Command Protocol 

    So when it came to working with the Sprog I had a little bit of a harder time than expected. The documentation for the Sprog is reasonable. It has a command list for "rolling roads" and other testing features but these setups tend to be for reprogramming purposes. When it comes to actually running a full working track layout you need the sprog in it's command mode instead. 

    I needed a way to get a better look at what the command structure should be for the Sprog. I struggled to find anything under "Dcc command list" on google due to an open source "Dcc controller" project that actually led me astray. In frustration I tried a different tactic; I setup JMRI and after a lot of jigger-pokery I managed to get it up and running with my lovely little DCC decoder tester.

    The decoder tester is basically a deconstructed train on a pcb. It has lights, a motor and speaker and with a decoder plugged in it reacts exactly like a train. Using JMRI (which reaffirmed my opinion that it's overly complex) I was able to monitor the packets that JMRI was sending to the Sprog based on my inputs to the JMRI "throttle" control. This made it clear that the Sprog works on a packet format similar to;

    < O -Train Address- -Data 1- -Data2- -CheckSum- >

    Now I could have simply gone through the process of testing every button press and speed value, creating a look up table of commands and using that to jerry-rig the control I wanted, but obviously it was much better to understand the packet and decode it to allow me to create commands on the fly. I did a couple of easy checks to start out; Speed, Forward, Backward, Stop slow and hard emergency stop. Interestingly these commands were all encoded in one packet. I thought that possibly there would be a separate command for direction and then speed but this didn't turn out to be the case.  

    Clearly I needed some documentation to move forward. I contacted the owner of the Sprog site and he replied pointing out that the sprog accepts "standard NMRA DCC commands". That led me down the rabbit hole of eventually finding the NMRA spec sheet for DCC commands. Reading through the document we can see that the DCC commands are based on a packet layout as discovered and use the individual bits in a byte to differentiate the different commands and control. Another point made to me in the email was that JMRI repeatedly sends the same commands over and over again. This makes sense...

    Read more »

  • Hardware - LEDs & LDRs - Automation Part 1

    Jack Wells6 days ago 0 comments

    Part of the fun of this build is to put small subtle details into it that add a layer of complexity to create a more "life-like" feel to the miniature layout. With this in mind we've taken our LED lighting for the housing, street lighting, etc and paired them with an LDR - light dependent resistor, or photoresistor. An LDR can be used to measure the level of light around the sensor. For our application this means we can use an LDR to measure the ambient light level in the layout and use that data to turn on LEDs as if the world is reacting to the light around the table.  This paired with our dimming LEDs creates a nice result (code block at the end of the post);

    By pairing multiple LDRs with block groups of LEDs then I'm hoping we can create localised areas that will react to objects placed on the top of the table that reduce the light in a certain area and the local LEDs turn on in response.  Combining this with my house and street light setup we can see a nice little result;

    /*
     Turns on LEDs based on LDR feedback
     Uses analogue write to handle dimming of LEDs
     */
     
    int Redled = 6;
    int Yelled = 5;
    int Grnled = 3;
    
    boolean RedState, YelState, GrnState = false;
    
    int RedRate = 1;
    int YelRate = 10;
    int GrnRate = 60;
    
    // the setup routine runs once when you press reset:
    void setup() {                
      // initialize the digital pin as an output.
      pinMode(Redled, OUTPUT);     
      pinMode(Yelled, OUTPUT);     
      pinMode(Grnled, OUTPUT);     
      pinMode(A5,INPUT);
      Serial.begin(115200);
    }
    
    // the loop routine runs over and over again forever:
    void loop() {
      Serial.print("LDR Value;"); Serial.println(analogRead(A5));
    
      static boolean LightState = true;
      boolean newLightState = LightState;
      
      if(analogRead(A5) < 600)
       newLightState = true;
      else
       newLightState = false;
       
    if(LightState != newLightState)
    { 
      LightState = newLightState; 
      
      if(newLightState == true)
      {
      //Brigthen all leds
      for (int i = 0; i < 255; i++)
      {
        analogWrite(Redled, i);
        analogWrite(Yelled, i);
        analogWrite(Grnled, i);
        delay(10);//reset timer
       
      }
      }else
      {
       
      //Dim all leds
        for (int i = 0; i < 256; i++)
      {
        analogWrite(Redled, 255-i);
        analogWrite(Yelled, 255-i);
        analogWrite(Grnled, 255-i);
        delay(10);//reset timer
      } 
      }
    }
    }

  • Hack a glass table top

    Steve Wells6 days ago 0 comments

    I bought a £29.99 glass table just for the glass although it had 4 of these metal adaptors glued in place. It was the correct size for the table project and it was tempered and bevelled glass (thought it'd be worth the risk). After a bit of research on the internet, I realised I had to apply enough heat to the adaptor to melt the glue used to attach the adaptor without risking too much heat to the glass.  

    I used a soldering iron and ground down a steel bolt so it would replace the tip and could be also screwed into the metal adaptors and rest there while heating up. While it was heating I clamped some mole grips to the metal and applied a constant downward pressure to it until the glue got to its its melting / softening point (500 degrees?)and it comes away. So no heating of the glass and just enough heat to get it off.

    Worked great and we now have a clean piece of bevelled tempered  glass for the project. 

     While it was heating I clamped some mole grips to the metal and applied a constant downward pressure to it.

    It took about 40 mins before any signs of softening.

    The bubbles began appearing on the edge and spread across the adaptor.

    Just drops off when soft enough without any damage to the glass, just another three to go!

  • Hardware - LEDs - A digital boy in an imperfect world.

    Jack Wells6 days ago 0 comments

    I've had a lot of fun playing with the LEDs. As of this moment each LED is connected to a pin on the Teensy. In the future, as the number of LEDs grows, I'll need to use a buffer chip of sorts to prevent running out of pins or over current draw from the Teensy. For the code I've created wrapper modules to make controlling the LEDs easy with the Teensy and they should be upgradable when I change control method. 

    Before writing this log entry I had the LEDs switching on and off as shown in my previous entry. This shows that the logic control for the LEDs is working and we have that instantaneous control. How this is achieved from mouse click to LED "on" is detailed below;

    The Imperfect World

    LEDs are a perfect example of a digital device. They are generally on or off without any variation of power in the middle; as soon as you apply a voltage above a threshold you get full brightness depending on the allowed current usage. This is great for fast paced, reactive interfaces; nothing catches your attention like a blinking LED. However in the real world of lighting, particularly older homes and street lights, this on-off flip to full brightness isn't achieved  instantaneously. It takes time for normal bulbs to warm up and produce their full brightness, perhaps this isn't ideal in the real world but aesthetically it's comforting and more natural than instant "LIGHT!". With this in mind can our LEDs replicate this imperfect "warm up"?

    Trick of the eyes

    Again, unlike the analogue world of bulbs where we can use a variable resistor (dimmer) to vary  our brightness, the digital world of LEDs requires a more complex solution to allow for "dimming". As stated an LED is either on or off, this is fact, but our eyes are easily deceived. Blink an LED above 60 blinks a second and what should be on-off-on-off appears to our eyes as constantly on; this neat little trick can be seen here:

    (red flashing 1/s, yellow 10/s and green 60/s - not as easy to see as the yellow is brighter)

    The code to achieve this effect is really simple. We're just turning the LED on and off and on again 60 times a second.

    /*
    Based on "Blink" example.
    
    Runs 3 LEDs blinking at different rates dependent on timers. 
    
    The "on" and "off" period are the same amount of time.
     */
     
    int Redled = 6;
    int Yelled = 5;
    int Grnled = 3;
    
    boolean RedState, YelState, GrnState = false;
    
    int RedRate = 1;
    int YelRate = 10;
    int GrnRate = 60;
    
    // the setup routine runs once when you press reset:
    void setup() {                
      // initialize the digital pin as an output.
      pinMode(Redled, OUTPUT);     
      pinMode(Yelled, OUTPUT);     
      pinMode(Grnled, OUTPUT);     
      Serial.begin(115200);
    }
    
    // the loop routine runs over and over again forever:
    void loop() {
    
      static unsigned long RedTimer = millis();
      static unsigned long GrnTimer = millis();
      static unsigned long YelTimer = millis();
    
      //Timer for red led
      if(millis() - RedTimer > 1000/(RedRate*2))
      {
        RedState = !RedState; //Flip value of RedState
        digitalWrite(Redled, RedState); //Write to pin
        RedTimer = millis(); //reset timer
      }
      
      //Timer for Yellow led
      if(millis() - YelTimer > 1000/(YelRate*2))
      {
        YelState = !YelState; //Flip value of YelState
        digitalWrite(Yelled, YelState); //Write to pin
        YelTimer = millis(); //reset timer
      }
      
      //Timer for Green led
      if(millis() - GrnTimer > 1000/(GrnRate*2)) //need to double the rate as this covers "on" and "off" cycle
      {
        GrnState = !GrnState; //Flip value of RedState
        digitalWrite(Grnled, GrnState); //Write to pin
        GrnTimer = millis(); //reset timer
      }
    }

    Dimming by PWM

    So blinking really fast allows us to trick the eyes into seeing a constantly "on" LED but we still don't have control over the brightness. The answer lies in "PWM" - Pulse Width Modulation. We're basically taking the "blinking-really-fast" trick and adding another layer on top. Previously when we were blinking the LED we had the same amount of "on" and "off" time. This is known as a 50% duty cycle where the pin spends the same number...

    Read more »

  • Hardware - LED Testing - Little blinkies are fun!

    Jack Wells10/09/2018 at 14:33 0 comments

    Putting LEDs inside something instantly increases its cool factor by 50%. What started as a miniature house that would forever sit lifeless on the layout is now more alive simply by adding some LEDs to liven up the place. The cool thing about these miniature N-Scale (which is tiny by the way!) buildings is that they've been built with acetate clear windows and internal floors. That means when I put 2 LEDs into the house then I can individually light up the top floor and the bottom separately. It's a nice touch and you can see the effect in the video below.




  • Python Anywhere - Django - Git - Online Test Site

    Jack Wells10/09/2018 at 10:39 0 comments

    Whilst working on any project it's always beneficial to get outside feedback. I'm working with my Dad on this one so we've talked a lot back and forth over the phone but sometimes it's just easier to "show" what I mean rather than tell. With this in mind I set about using the previous Django Girls Tutorial to "Deploy" my site online and create a mock up that could be viewed and interacted with without the risk of opening up my Raspberry Pi to the world wide web.  

    Hosting a Django site online is essentially done by using Git to store the working files online and then passing those files to a second web server that will host the site. Python Anywhere was recommended by the tutorial and was simple enough to get setup. It runs very similar to a shell interface like working with the raspberry pi but inside your browser;

    You can find the mock up of my site here. Whilst on the site if you open up the browser development tools then you can monitor the console for the debug statements coming from my java script. This lets us view how the html buttons are parsed by the javascript and what is being sent via "POST" to Django.

    A final little piece I added to the site was to create a basic user for the Django admin panel. This user has the ability to add and edit the database entries for the "Trains" and "Lights" tables. If you want to play around with it then you can go to - http://jackflynn.pythonanywhere.com/admin/ - and then use the following log in details;

    User - TestUser

    Password - coffeetable1

    Once logged in you can then change the entries in the tables or add new entries. The main page will update on a refresh and you can see for yourself how Django actively generates the html based on the database. 

  • Raspberry Pi - Bash - A hard job & a lazy man

    Jack Wells10/03/2018 at 13:28 0 comments

    After detailing the code flow for the Raspberry Pi and getting some initial scripts working with Redis and my Teensy, I realised that I was having to launch 3 different objects manually in order to get everything working. I had to run Django via the manage.py to get the site up, then open another terminal and run Redis for passing data between my scripts and finally to get the Teensy communication working I had to run the "ArduinoEffectsManager" script. An added step was also that I had to launch my virtual environment before running my python scripts. 

    While debugging this was really useful as I could track the printed outputs from my scripts but for a quick demo it wasn't ideal. There's a quote that goes around; "Whenever there is a hard job to be done I assign it to a lazy man; he is sure to find an easy way of doing it.". I decided to be lazy and find a nicer way to get everything running as eventually I would need everything running without my input anyway and it had me learn a bit more about running tasks on linux. 

    Read more »

  • Raspberry Pi - Development - Project Code Flow

    Jack Wells10/03/2018 at 09:16 0 comments

    Development on the Raspberry Pi is all setup and running smoothly. To better understand what the Pi is doing I've created a rough flow diagram for how it's going to work.

    Starting at the

    Read more »

  • Raspberry Pi - Development - IDE; Speed, Security, Complexity and Price.

    Jack Wells10/02/2018 at 09:44 0 comments

    Fast, Easy, Secure, Cheap. We'd like all 4 but in all engineering disciplines we quickly learn that with the real world there comes trade offs. I wanted an nice IDE interface for developing code on the raspberry pi while it was running in a headless configuration; no screen attached. Looking online there were a number of IDE options that ranged from eclipse; running on my PC with it's various complex setup methods and paid-for plugins, to VIM; an old school text editor that could be run directly on the Pi via a terminal interface. I wasn't a fan of either of these options. 

    I wanted something that would let me edit files in a clean windows environment that didn't take 2 hours to setup and could come crashing down at any moment. I was willing to compromise on security in return for a free solution as my Pi won't be exposed to the outside world.

    Luckily I came across...

    Read more »

  • Web-server - Pi - Where to start?

    Jack Wells10/01/2018 at 15:06 0 comments

    The criteria for the web-server is to not only have full control of the layout and effects but also to provide that control in a clean and friendly manner. There is an epiclly complex package already available for a raspberry pi compatible DCC control called JMRI. Like this project, JMRI is used to interface to off-the-shelf DCC controllers and can work as a standalone interface, web-server or communicate with smartphone apps. My hat goes off to the guys at JMRI as it truly is an excellent bit of software for the hardcore DCC fans. However, for our application I wanted something more friendly for the kids and I was looking for a chance to learn more about the raspberry pi and web development in general. 

    Python and Django

    So where to begin with the raspberry pi? Well first off I knew I wanted to work in python. Python is an excellent programming language for beginners and is heavily favored in the raspberry pi community. This means there's plenty of support out there and reduces the need to "re-invent the wheel". With that in mind there are plenty of options for getting a pi to display a web page. For this I've used Django;

    Read more »

View all 13 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates