So, my 1st week of internship is done. Now 25 more to go!
Anyway, I did a lot this week. Like, I designed the cabling for an electrical panel, made flowcharts showing all the programming stuff, studied app development and microcontrollers, and even helped a bit with the accounting. I’m super tired but incredibly fulfilled.
Kinda wished I met the IT guy by now. I’m supposed to meet him and he’ll be helping me with all of this but I still haven’t seen him. So I’ve just been teaching myself and learning on the job. Like, this is literally a full-blown job I’m doing. I just have the title “intern”.
I still have a lot of work to do though. Gotta figure out how to do RS-485 stuff, and now Raspberry Pi. I also need to study more on programming and I still haven’t done the piping and sensors installation. So yeah, work in progress.
Since the prototype turned out to be a success, it is time to work on a more professional solution: a custom PCB. Of course I don't just slap an Arduino and a MAX485 IC on a board and call it a day. I use this opportunity to add some nifty features to the custom board. You know, just to impress my dad.
The train my dad is controlling has on board sound. But just as in real life, it's not only the train that makes sound. By adding a MP3 player to the board, we can play random sounds over a train station speaker.
For this project I use a DFPlayer Mini. A $1.50 MP3 player with integrated (mono) amplifier. It uses Micro SD cards to store the sound clips and can be controlled over a UART serial interface (together with many other control options).
I have a soft spot for tiny displays, so whenever a built a project like this, I find a way to integrate a display. The display is just as cheap as the DFPlayer Mini, so I think I can justify the costs.
Now, of course sound and display won't be enough to make it a stand-alone controller. So here's the full feature list:
Arduino Nano Socket
DFPlayer Mini Socket with an external connector for a speaker.
The MAX485 IC to allow the board to talk to the Roco MultiMAUS.
A 0.96" I2C OLED display.
Three SMD LED's that can be used as visual feedback (convenient during debugging).
Three hardware debounced push buttons.
A RJ12 connector to connect the Roco system.
Various JST connectors for additional GPIO ports.
A LM7805 voltage regulator to supply power to all the components.
And with that list in mind, the next step is to draw the schematics for this project.
Download the PDF of the schematics here.
After finishing the schematics, it's time to work on the PCB design. Granted, KiCad hs it's quirks, but in the end you'll be able to design some pretty sexy PCB's.
Along the way, the 3D-render function of KiCad gives you a nice feeling about the end product. I think I am on the right track here ...
After I finished up the design, I send my order to one of the Chinese manufacturers, and within a few days this stack of beauties arrived on my doorstep.
Some solder, some heat and a few bottles of midnight oil later, the first populated board turned out better than expected. I must day I'm really a fan of SMD soldering.
If I would make a second version of this board, I'd integrate the ATMega328 and remove the need for the header pins between the display and the DFPlayer. You know, just to make it look even nicer.
Of course I did goof up at some points:
I used the wrong footprint for the JST connectors. I own boxes of 2.54mm spaced JST connectors, but used the 2mm footprint. Not a big deal: we just solder the wires directly to the board (or order some 2mm connectors if needed).
I added a jumper to disconnect the Arduino from the board's power to allow me to connect it to my computer while it's on the board. Unfortunately I forgot to add a jumper of switch to disconnect the serial lines from the MAX485 IC. This prevents me from programming the Arduino while it's on the board.
I added hardware debounced buttons to the board, but those buttons need to be connected to external buttons. It would be much nicer if I added a connector for this as well. Right now I need to solder some wires to the button pads.
Luckily, none of those points are show stoppers. But if I ever need to order a second batch of this board. It might be worthwhile to make the nessecery modifications.
Next step: work on some code!
Want to build this controller yourself? Download the Gerber files here. Or get the full KiCad project here. Keep in mind that it comes wihtout ANY form of support. :)
As my regular readers know, my dad is an avid Model Train hobbist. And altough my interest is more on the digital side of electronics, every now and then our hobbies meet. After my recent Arduino powered analog clock project, I once again will work on a project for my dad: Let's make his trains Arduino powered!
In the past years, my dad's train artworks were featured during the OnTrax Train Expo in the dutch Railway museum. The photo above (which show my dad and my oldest son Enzo) is made during the most recent expo and features the train controller I built last year. During the next Expo, my dad will show his new creation with a shuttle train.
Like most of his tracks (with exception of the track in the previous picture) the shuttle train will be controlled using a Roco MultiMAUS and although this allows for very easy control, this would mean he needs to continuously operate the train during the expo weekends. Of course there are many automated solutions to solve this. Unfortunately most of them are pretty expensive, complicated and would require my dad to connect a full blown computer to the track.
As an enthaustic microcontroller fanboy, I'm sure I can come up with a simpler solution that allows him to automate his shuttle train.
The MultiMAUS is connected to the track via a digital amplifier. The digital amplifier and and MultiMAUS use the RS485 protocol to communicate which can be connected to an Arduino with the help of a MAX485 IC. To make life a little easier in the prototyping phase, I bought a Waveshare 485 breakout board.
To check if I was on the right track (pun intended), I hooked up my Rigol DS1054Z oscilloscope to see if I indeed receive some data ...
And after some fiddling around and swapping the A & B channels on the bottom of the MAX485 breakout board, I the bits started to appear on my oscilloscope. Great!
Of course, I wasn't the first person to start this adventure. As a matter of fact, I couldn't have done it without the help of Philip Gahtow who wrote the awesome XpressNet library. This library also included the image above which shows the wiring needed for this project.
Since I'll be using an Arduino Nano which only has one Serial port, there was one caveat: I couldn't flash the Arduino while it was connected to the RS485 bus. But with that in mind, wiring everything up was pretty straight forward.
Of course, the system also needs a way to detect if the train approaches the end of the track. And although there are many (complicated) ways to achieve this, I will go for the easiest solution possible: adding a magnet below the train, and putting two reed contacts between the tracks. For now (since we are prototyping) I just manually control the end stops by connecting the yellow wire to one of the two assigned end stop pins of the Arduino.
And with the electronics all wired up, it's time to start working on some proof of concept code. I must admit it's a pretty unique place to do some coding: right between the tracks.
Let's see if we can start the trains.
First, we need to set up the basics:
// Include the XpressNet Library #include <XpressNet.h> // Define the address we will be using for our virtual MuliMAUS. #define XNetAddress 31 // Define which pin we use to enable the transmission to the digital amplifier. #define XNetSRPin 3 // Define the ID of the train we will be talking to. #define TRAIN_ID 89 // Create an instance of the XpressNet class. XpressNetClass XpressNet;
Next, we need to configure the XpressNet object, and finally we can give the train the command to start driving. In this prototyping phase, let's keep it simple, and put it all in the setup() routine, so this command will be only be given once.
void setup() { // Initialize the XpressNet controller, using the defined values. XpressNet.start(XNetAddress, XNetSRPin); // Queue the command to start the train. XpressNet.setLocoDrive(0x00, TRAIN_ID, 0x13, 32); // Speed: 32 }
Note that It said the command is queued. It won't be send to the train directly, since the XpressNet library will wait for data from the digital amplifier first. This is something that took me a while to find out, but luckily, the solution is very simple. We need to call XpressNet.receive(). in the main run loop:
void loop() { // Check if there is anynew data available, and then send all queued messages. XpressNet.receive(); }
And low and behold, after uploading the code and connecting the MAX485 unit to the digital amplifier, the train starts moving!
A few caveats I ran into:
The acceleration and deceleration of the train is something that is programmed into the train. It is not something you can control on the fly. We need to take this into account when we place the reed contact end stops.
The speed is a one byte value (0-255). Everything below 128 is forward driving, 128 and up is backwards driving.
As said: we need to listen for new data before our commands are send.
And with that in mind, we can start working on the read deal.
Of course my dad likes to give me a nice challenge. So not only are we going to control the train's movement. We are going to add the following as well:
An OLED display to see the current state of the train and the time of the next automated departure.
We are going to control the on board train sounds (literally: bells and whistles).
We will add an integrated MP3 player to add train station sounds that are played at random intervals.
Everything is going to be configurable using a few integrated buttons to allow my dad to change the intervals without the need of a computer.
Of course, I can't just hand over a breadboard contraption, so in the next post we are going to work on a custom designed PCB that houses all the necessary electronics. Read it here!
The Train Automator: Part 3 - Writing the Software
After finishing the electronics it is time to work on the software. Since the train automator runs on an Arduino Nano, it's time to fire up Visual Studio Code and start typing some C++.
I've mentioned it a few times before: Platform.io is the perfect integrated development environment if you want to work with microcontrollers. The "new" VSCode extension makes it even better, since VSCode is my code editor of choice.
The setup for the embedded software is based around some Manager classes and Controller classes. If you are a regular reader of my blog, you know I used those term only to make my code look more professional. Why? because I have no idea what i'm doing.
Anyway, here's the beakdown of the software:
DisplayController: Responsible for displaying all the nessecery information on the screen. This class creates the user interface.
RandomTimeTask: A class responsible for executing tasks at random time intervals.
SettingsManager: Responsible for the setting settings interface, as well as storing and retrieveing the various settings stored in the EEPROM.
SoundPlayer: Responsible for playing the sound clips via de DFPlayer Mini (MP3 player).
TrainController: Handeling the communication with the train (via the Roco MultiMAUS system).
main.ino: The glue between all the classes mentioned above.
The interface allows you to toggle the three random timers (Auto drive, Train Sound, Station Sound) using the on board buttons. The display will show the countdown towards the the moment the action will be initiated.
The randomly picked delays are within a preconfigured range. By using the random intervals, my dad's train module will get a more natural feel. Because lets face it: when does a train ever drive on the exact schedule!?
The randomly scheduled tasks (RandomTimeTask) are based on the Task library by Makuna. The possibility to build your own Task subclass was a perfect fit for this project.
Aside from the default timer interface, you can enter the setting screen by holding one of the three buttons. This will allow you to configures things like Train ID, Train Speed, Volume, Auto Drive Minimum Delay, Auto Drive Maximum Delay, Train Sound Minimum Delay, Train Sound Maximum Delay, Station Sound Minimum Delay and Station Sound Maximum Delay.
All these settings are stored in the Arduino's EEPROM, so they are non volatile (meaning they remain stored even when the Arduino is powered down).
Building these settings screens was extremely easy using the u8g2 graphics library. It already included all the nessecery input tools and is extremely powerful if you want to built user interfaces on small displays like the used 0.96" OLED.
Here's a small impression of the interface I built for this project:
Of course I couldn't have built this project without the hard work of Philip Gahtow who wrote the awesome XpressNet library. So a big thanks to Philip!
And with both the electronics as well as the software finished, it's time to incorporate the Digital Train Controller into my dad's train module. Stay tuned! :)
PS. Interested in the full sourcecode and Platform IO project? Check out the GitHub Repository here. Keep in mind that it comes without ANY form of support. :)
Looking for a reliable and high-performance rs485 transceiver for your industrial or embedded communication project? Campus Component brings you expert-level solutions designed to ensure stable, long-distance data transmission with minimal signal interference. Whether you are working on automation systems, smart metering, PLC networks, or microcontroller-based applications, our carefully selected components deliver durability and precision you can trust. At Campus Component, we understand how critical communication stability is for your operations, which is why we provide tested and dependable products tailored to your needs. Our team is committed to helping engineers, developers, and businesses find the right RS485 interface solution without confusion or delays. Choose Campus Component for genuine products, technical guidance, and competitive pricing. Upgrade your communication systems today with a trusted rs485 transceiver from Campus Component and experience seamless connectivity that drives your projects forward. Contact us now to get the best deals and expert support.
Membaca Banyak Modul PZEM-016 dan PZEM-017 dengan RS485
Tulisan ini sebenarnya adalah latepost lagi dari yang seharusnya saya tulis di pertengahan Agustus, tapi baru sempat saya tulis sekarang.
Pada tulisan sebelumnya kita cerita tentang membaca data dari Pzem dengan protokol RS485. Kali ini, kita akan bahas membaca banyak modul Pzem dengan protokol komunikasi RS485 dengan satu mikrokontroller ESP Wemos D1 Mini.
Secara umum, port RS485 yang biasa…
India’s most affordable RS-485 to Ethernet Converter by HashStudioz is designed to bridge legacy Modbus RTU devices with modern Ethernet (Modbus TCP) networks. With a compact, industrial-grade design and reliable performance, it’s an ideal solution for industrial automation and IIoT deployments.