An Overengineered LEGO Christmas Train (V3)

by Basement Engineering in Circuits > Remote Control

2107 Views, 20 Favorites, 0 Comments

An Overengineered LEGO Christmas Train (V3)

TrainAnimated.gif
1703891606857.jpg
History.jpg
InstructablesThumbnail.jpg
Overengineered LEGO Christmas Train

"Merry Christmas" that is the sentence that this project ends with every year, since 2021. But it is about more than just Christmas. It's about nostalgia, revival, LEGO hacking, ESP32 tinkering, learning lessons and somehow turning engineering into an annual tradition along the way. If any of these topics sound interesting to you, you might want to take a closer look. If you are not in the mood for reading today, I have also prepared a YouTube video as well as a bunch of nice, comprehensive images scattered throughout the Instructable.

The Backstory

This project might have actually started all the way back in 2005, when I got a LEGO 4511 train set for Christmas. I loved it, I played with it for hours and hours before putting it back into its storage container, just to repeat the whole process a few weeks later. This went on for years, until I got older. One faithful day was the last time I played with it before it was banished into the storage closet for more than a decade. In 2021, it finally saw the light of day again. While I was looking for something else during Christmas, I rediscovered it and decided to put it underneath the family Christmas tree.

I loved to see the little guy rolling again. It was just great :) .............. However, while I watched it doing rounds around the tree, I got the makers itch in my fingers. You know the feeling, when you see something that works well, but think you could improve it and add more features. Well, that's what caught me in 2021 and got me to take the train off the tracks and completely redesign it.

In the past two years, I already went through two quick iterations of this project, where I threw some additional electronics at the train to make it do things that it originally couldn't. This year, I want to create a well-thought-out third iteration and share my journey, as well as all the little details, with you.

Goals (for this year)

To spice things up, I decided to set a little Christmas party with my friends as the deadline for this project and give me about a week to finish it (you can read how this went in the end). The train is supposed to deliver drinks from the kitchen to the living room and, apart from socializing, fun and games, it will be the main attraction of the party.

Therefore, the goal for this year is to Keep It Simple! (the exclamation mark is directed towards myself, as I tend to overengineer things a little bit). I kept my excitement down and tried to focus on two major features:

  1. Make it move
  2. Make it stop automatically

Furthermore, we have to figure out a way to power it and maybe even make it glow.

With our major goals set, let's get started.

Supplies

Disclaimer

I would not recommend rebuilding this project exactly as I did. It is very much a one of a kind thing, a work in progress and maybe even a little bit overengineered. Newer LEGO trains have a lot of the controls already built in. I think they even have sensors, to make the train stop on its own. I view this train as a little engineering challenge that I use to try out some of my tech, and that I can evolve every year.

I still want to give you an insight into all the things that I did, so you can learn a thing or two and get detailed inspiration for your LEGO train.

So here is what I used and what you would need to build the same thing.

Brick Material

  • a LEGO Train

Mine is LEGO 4511 from 2003, unbelievable that that is exactly 20 years ago. However, you can also get a newer LEGO train. There are some experts that claim "old school 9V is the best", but I really only care about what is available, looks nice and has an appealing price tag.

  • additional LEGO bricks to get creative with the trains look
  • a LEGO Christmas Tree

Electronics

Of course, there is a bunch of electronics

Power Supply:

  • 18650 battery cell
  • battery cell holder
  • 1S 6A battery management system (BMS) module
  • TP4054 lithium-ion charging module
  • power switch
  • 5 V DC-DC step up/boost converter
  • adjustable DC-DC step up/boost converter
  • adjustable DC-DC step down/buck converter

Control Electronics:

  • ESP32 Node MCU with 38 pins
  • touch button module TTP 223
  • 0.5 m strip with WS2812B addressable RGB LEDs
  • DRV8833 dual H-Bridge motor driver module

Other:

  • breadboard 400 pin
  • male and female header pins
  • wires and shrink tubing

Software

  • Arduino IDE
  • My firmware file or source code. You can get the precompiled binary as well as the source code from my GitHub repository.

Other Stuff

  • battery powered LED Christmas lights
  • aluminum foil

Making It Move

Moving_Animated.gif
ProtoTrain.jpg
MotorControl_Circuit.jpg
LegoMotorComparision.jpg

The first endeavor on this journey is to get the train up and running. With LEGO trains, this is very simple once you get past the connection barrier. My motor is a "classic" 9 V motor. There are several different motors that I compiled in an image above. I also added some text below on how to connect the newer motors. Apart from a connector, my particular old school motor features metal wheels and is supposed to run on metal tracks that act as a power supply. To make it go slower or faster, you would usually crank up the voltage on the tracks using an external power supply. However, I want to have my control electronics on the train and use the more affordable all plastic tracks to extend my layout. Therefore, the motor has to be supplied from an onboard power supply. Luckily, LEGO has thought of that and the connector on the back of the motor can be used to supply power to it. I just needed a suitable cable to connect to it. Luckily, the old cables that came with my train crumbled on their own and lost almost all of their insulation. That is why I did not feel bad cutting them apart and soldering pin headers to them.

I'm going to use a microcontroller to control the train. To enable it to control the motors, we need a motor driver that can deliver up to 1 A. Luckily, I have my trusty old DRV8833 H-bridge motor driver module at hand. The hardware setup can be seen in the image above, along with a circuit diagram. In this test setup, I added a hefty power bank that outputs 5 V, which is enough to power the motor, although it is not going to reach it is only going to reach its maximum speed. With our train firmware, the microcontroller outputs the right signals through the two wires to make the motor move forward and backward. The signals are pulse width modulated (PWM) to drive the motor at a variable speed.

Movement: ✔️

--------------------

Jan's pro tip:

Apparently my motor can already be considered as antique. There have been two newer generations of train motors, that can be seen in the overview graphic above. They have different connectors with more pins than the old motors, but there are always two wires that go straight to the motor. Those are labeled C1 and C2 or M1 and M2 in the pinout diagram. If you hook them up to the motor driver's output wires, you are good to go.

Making It Stop

Stopping_Animated.gif
StoppingComponents.jpg
Stopping_SensorMount.jpg

Making the train stop on its own is surprisingly simple. We just need two components. One is a TTP223 Touch button module. This thing is amazing, and I use it in a variety of projects. It works by measuring capacity changes, that can be caused by a finger touching it. However, there are other things, that can cause a capacity change that is detected by the sensor. This is where component number two comes into play: A LEGO brick covered in aluminum foil.

I simply place the brick on the track and the sensor underneath the train. This way I get a signal, whenever the train drives over it. With multiple bricks on the track at fixed distances, I could even count the number of signals to register the train's position and estimate its speed. As of now, I just have two bricks. One is located at the start of the track and one, at the end. When the train reaches the desired stopping location, the sensor detects the brick and my software simply stops the motor.

Simple, cheap and mostly reliable.

Stopping: ✔️

--------------------

Jan's pro tip:

One thing to consider is that the touch module calibrates every time the power is turned on. It sets a threshold value for when nothing is supposed to be detected. So make sure that there is no aluminum brick underneath the sensor when you turn it on.

Controlling It

Controls_Animated.gif
Communication.jpg
ControlSetup.jpg

We could just add a button to start the train, but where is the fun in that? The ESP32 comes equipped with shiny wireless capabilities and can communicate with other devices via Wi-Fi and Bluetooth. Let's make use of these features and add remote control. In my opinion, Bluetooth is the easiest to set up and use for that, because it offers a simple coupling and connection mechanism, and it allows us to use the Bluetooth UART service to send text from and to a remote terminal app, just like the good old Serial Monitor in the Arduino IDE does. To open the connection on my phone, I use the "Serial Blueetooth Terminal" app.

That is all the tech we need to talk to the train and tell it what it is supposed to do. However, our train has no clue what we are talking about, so we have to teach it a language and program a communication protocol. The simplest protocol would be to simply send the desired speed as a number from -100 to +100. The communication protocol, that I baked into the code is a little bit more advanced, as I stole it from a previous submarine related project. It encapsulates the desired speed in a JSON message that looks like this: { "channels":[1,<speed>] }

Of course, I don't want to send these messages by hand every single time. Most Bluetooth terminal apps offer the option to hide a pre-written message behind a button. Using this feature, we can create multiple buttons to send different speeds to the train.

Why do I use such a complicated protocol? Because it will allow me to add more controllable features in the future. I could, for example, add a channel to remotely control the lights.

Remote Control: ✔️

--------------------

Jan's pro tip:

Be sure to grab an ESP32 module that supports classic Bluetooth. There are newer chips, like the ESP32-3C, that exclusively support Bluetooth Low Energy (BLE), which is a very different protocol. While there is also a BLE UART service, it is not well-supported by the Arduino ecosystem or the Serial Terminal apps. I had to find that out the hard way, so you don't have to.

By the way, my protocol also sends messages back to the phone with information about the current states of the outputs. We might make use of that in the next iteration.

Making It Glow

Lights_Animated2.gif
1703891606799.jpg
1703695977131.jpg
1703695977155.jpg
1703695977109.jpg
1703695977200.jpg
1703695977178.jpg

LEDs, gotta love them. I'm especially in love with all the little battery powered light strings that are available for a couple of euros at almost every store during Christmastime. Unfortunately, we do not have the space to fit an additional battery pack on my train. Therefore, we are going to want to power the LEDs from our main battery, that also powers everything else. The strips normally use 2 AAA batteries, but we are simply going to emulate the batteries using a DC-DC voltage converter. More on that in the power supply section of this Instructable.

Let's decorate our little LEGO Christmas tree, by wrapping two of the strips around it. We can simply cut off the battery packs to solder simple header pins onto the ends to hook them up to a different power supply. Another nice addition is an illuminated snow cover on the main train carriage. For this, we can just hot glue a white string light onto a piece of wood. The snow cover will be a simple paper tissue securely mounted to the wooden base with packing tape. See the attached pictures, in case you get confused by my descriptions.

Apart from the string lights, we also want a headlight, and while we are at it, why not add a bunch of LEDs to illuminate the drinks. Addressable RGB LED lights are perfect for that job. One whole strip of 18 LEDs can be embedded into the drink carrying train carriage. It extends to two individually soldered LEDs in the locomotive through a cable. One is glued to the back of a 1x2 LEGO brick, with a hole into, to form the headlight. Another one is simply located in the locomotive's cabin to create a cabin light.

Using some code magic, embedded in the firmware file, we can control those RGB LEDs individually and make them light up in different colors and at different brightness levels. The only one turned on at full brightness is the headlight. All the other RGB LEDs are set to be noticeably dimmer. I also programmed a little animation to make the LEDs on the drink carriage "breathe" when the train is just parking. They turn to a solid, warm white color as soon as the motors are started.

In the future we could do more advanced things with the programmable lights, but for now, they just look nice.

Christmas Lights: ✔️

Powering It

PowerSupplyBattery.jpg
PowerSupplyVoltage.jpg
Schematic_PowerSupply.PNG

The power supply will be a little bit more complex and sketchy than I would like it to be. The easiest thing would have been to use a power bank. However, all the power banks I had available were either too big to fit into the train cart or could not supply enough current for the motors and the control electronics at the same time.

For that reason, I designed a custom power supply, that looks super sketchy and can be seen in the images above. Let's take a look at what it does.

First things first: we need multiple different voltages to power the trains components. The controller board and the addressable RGB LEDs take 5 V. The motor can also run on 5 V, but it reaches its full speed at 9 V. That might be more than the train needs, but we do at least want to have the option to go full speed. The little string lights on the other hand take a lower voltage of around 3 V (2 AA batteries).

On the supplier side, we have the power source. As I wanted to keep it simple and small, I decided to go for a single 18650 lithium-ion battery cell. I choose a Samsung 25R cell, which is capable of supplying up to 20 A. This should be more than enough to reliably power the whole train, right? Well, that is a little bit of a foreshadowing of the issues we will discuss in a later step. Apart from the battery, the backside of our power supply contains a battery management module. This protects the battery from fiery circumstances, like short circuits or overcurrent. It also protects it from over-discharging. Next to it is a little charging board that allows me to charge the train using a USB cable.

On the other side we have the voltage conversion section. As mentioned above, we need a bunch of different voltages. Our battery can also deliver a bunch of different voltages, unfortunately not necessarily when we want them. Depending on its state of charge, it outputs anywhere from 2.8 to 4.2 V. Our controller does not really like this behavior and wants a constant 5 V, just like most other digital components. For that reason, we need multiple voltage converters, that generate the required voltages. Two of them are so-called step-up or boost converters, that increase a lower input voltage to 5 V and 9 V respectively. The third converter is of step-down or buck type and reduces the voltage to 2.8 V for the string lights.

With this, we can say:

Power Supply: ✔️

--------------------

Jan's pro tip:

One word of caution: motors don't mix well with digital components on a shared power supply. They consume a lot of current when they start up, and they produce noise and voltage spikes. It gets especially bad, when they abruptly stop or change direction, which causes the motor to induce a voltage back into the circuit. To mitigate the impact of these disturbances, I added capacitors close to the components. The motor control code in the firmware also slowly ramps the outputs up or down to prevent sudden changes in speed or direction and the accompanying induced voltages.

Putting It All Together

Spine_Animated.gif
TrainOverview.jpg
InsideTheCart.png
1703758896352.jpg
IMG_20231218_223154.jpg
1703758896374.jpg

Now that all of our components are ready, we need to put them into a nice package. In this case, the longest cart of the LEGO train. As we are planning on building onto this project in the future, we want to keep it modular and be able to plug additional components into the circuit in the future. Modularity is nice, but it often comes at the cost of requiring more space, and we don't have a lot of that on our train.

Let us first consider modularity across the train. The locomotive contains two RGB LED's as well as the motor and has some space left, so it should also contain the motor driver. The second carriage is supposed to carry the drinks and illuminate them using some more RGB LED's and the very last cart will contain all the remaining electronics, as it offers the most space. To connect the different carts at the two connection points, we will use pin headers. Male pins will be coming from the front and plug into female sockets in the car behind. Each cart is equipped with a 4 Pin connector for the motor driver and a 3 Pin Connector for the RGB LEDs.

All the wires run towards the back, but how do we connect the internal components inside the electronics cart while keeping it modular? Well, one of the internal modules has already been put together in a previous step, the power supply. It features the battery on one side and the voltage conversion modules on the other. All of those components are soldered and hot glued together. Out of the module comes a 6 pin connector. An overview of all connector pinouts used on the train is attached as a PDF.

This connector plugs into the controller module. This thing part is interesting. We do not want to permanently solder any wires to the control board because we would like to be able to plug in new components in the future. A solution that allows for reconfiguring circuits is a breadboard. However, a breadboard is simply too large for our train. To solve the issue, we can cut a small 400 pin breadboard in half and glue the two halves together. Now comes the even sketchier part, we plug a few header pins into the breadboard and soldered those to the ESP32 board in a 90 degree angle. You can see this creation in the picture above. We then create the necessary connections on the breadboard using jumper wires and plug the remaining components into the breadboard. You can see the result in the picture above. The attached schematic shows all connections in detail.

That's it, with this we can just barely fit all of it into the electronics cart.

Packaging It: ✔️

--------------------

Jan's pro tip:

Simple pin header connections have two major downsides: They can be plugged in the wrong way, possibly destroying the electronic components, and they can accidentally be ripped out. A better solution are JST connectors.

Embracing Failure

Issues_Animated2.gif
Improvements.jpg

Let's be honest, no DIY project is perfect. This little train creation is no exception. Last year's iteration had some downsides, and this year it is no different. I want to discuss two major weak points and how to fix them.

Too Little Power (mechanically speaking)

The single train motor, that I used, was made to power a small LEGO train with two carriages. I'm assuming that no one ever planned for it to carry 3 carriages, the weight of multiple shot glasses and our electronics combined. The motor is also 20 years old, and the rubber O-Rings on the wheels that are supposed to give the motor grip have seen better days.

During my tours from the kitchen to the living room, the train got stuck in curves on a regular basis. I improved the track and moved the curved pieces apart to ease the train in its endeavor of delivering drinks, but it still got stuck from time to time and required a little push. The motor is also constantly going at full power and probably slipping most of the time when starting up.

The solution for next year is simple: More motors.

Too Little Power (electrically speaking)

I mentioned before that motors can give you a hard time, when designing an electronic circuit. When they are starting, they consume a substantial amount of current. This current consumption, in turn, reduces the battery voltage. If the voltage converters can not pick up fast enough, this also reduces the voltage on the microcontroller. A voltage drop can cause the controller to reset.

And unfortunately that is what my train experiences on a regular basis. Especially if the battery is not fully charged.

It's a big issue, but the solution is once again to add more. In this case, more batteries. We could go with multiple in parallel, reducing the voltage drop caused by the motors. But instead, I am planning to put multiple batteries in a row to increase the supply voltage. Two in a row means 5.6 to 8.4 V straight from the battery. According to some online research, if you have the luxury of choosing the source voltage, it is generally better and more stable to use a higher input voltage and step down converters for everything that requires a lower voltage. With this higher voltage, I can also feed it straight to the motors, without the need for an additional converter.


As you can see, with such a project, you never run out of work. But it is worth it in the end, because brains are pretty darn good at forgetting the bad parts of a project and remembering the fun result.

Enjoying and Dreaming

TrainAnimated.gif
1703891606778.jpg
1703891606876.jpg
IMG_4000.JPG
IMG_4014.JPG
IMG_4017.JPG

Speaking of results, let's take a look into my living room and see some pictures of this train in action. I think it looks great, and it sparks joy, whenever I see it running around my Christmas tree. We have also reached our goals of making it move and stop on its own, albeit with some issues. Thank you for joining me on this project journey.

Regarding the deadline I set in the beginning, I did technically finish it for the Christmas party, but it was only a very simple prototype. I then spent a few more weeks, to further improve the train, but that is covered in the YouTube video.

As you can probably already guess, this project is not finished yet. For next year, we are going to add more features. Mainly the following:

  • Fix the issues mentioned inst Step 7 and give it more power
  • Add actual speed control using encoders and a PID motor control loop
  • Add an NFC based location system

We will see how much time I have next year.

If this Instructable gave you anything, even just nostalgic memories of playing with LEGO, consider to leave a like. I am also entering it in the "Anything Goes Contest", as it is definitely an anything, so I think it is suitable. Wish me luck and maybe give me a vote. If you also want to be in for next year's iteration, give me a follow on YouTube or on here.

Thanks for reading and happy holidays, or just have a great day if you are reading that at a later point in time:).