Build Log for Proof-of-Concept Train Motion Analyzer

This all began about two years ago. I owned a Lionel train I bought off ebay and one day I had an idea that sounded really fun:

  1. Create a self-driving train on a simple closed track that attempts to circle arbitrary track as fast as possible (i.e. will slow down before curves).
  2. Extend the design to make the train remote-controllable while at the same time ensuring the driver never overspeeds.


I’ve been fascinated with O-gauge trains since a kid – a relative had a train set in the basement which I thought was really cool because the trains, the track and whole setup were big! I bought a set years later. The thing that kept bothering me was that I had to be really careful around bends because the O-27, that is 27″ outside round track diameter, is a really quick curve for O-scale trains and that’s inviting trouble. By the way, some engines and cars won’t work on O-27 – you need the larger radius curves and take up way too much space unless you have a very large room to spare.

So I thought maybe if I could use something like an Arduino coupled to an accelerometer a means to measure when the train hit a curve could be determined, then a record of the entire circuit could be made and used for future loop speed adjustment. It would start slow and speed up with each circuit until the acceleration hit some limit at which point it would never go faster.


I needed a proof-of-concept. Attaching three small breadboards and an Arduino to an MDF board I had the base of my system. The rest went like this:

  • Three axis accelerometer installed in inside front of train engine (MMA7260Q), presently retired at Sparkfun:
  • Distance detect using photo interrupter on the wheel crank
  • 32MB hacked SD card connected to SPI interface on Arduino. A switch permits plugging card into card reader to read data onto PC. Since the Arduino has limit data storage, the card allowed storage of accelerometer and distance data as the train went around the track.
  • 8×8 green LED matrix used to show the accelerometer data in two axes in realtime. To save on Arduino pins I used a 74LS138 demux and 74LS164 shift register.
  • A bunch of Arduino code integrating all of these components together.

Check out the Arduino code for this breadboarded system and the data it generated.

After verifying that it worked by tilting the board (actually, the train engine) and seeing the dot move across the LED matrix correctly, I taped the whole mess to the flatcar with a battery and got the train running.

The first problem was that the motion was excessive (pegged the LED display). I added trim pots as inputs to the Arduino to fine tune the offset and zoom (range of motion), which helped in getting full-scale outputs on the LEDs properly centered. This gave me a pretty good idea of what the accelerometer was seeing.

But a problem was apparent with every run: The dot that I was expecting to nicely move sideways when the train went around a corner was instead a blurry smear on the LED matrix with no obvious tendencies to move sideways.

I added a software filter to the accelerometer data (each of the two relevant axes got a 20 bin bucket to smooth out the data). Unfortunately this didn’t help.

After each of a few runs I pulled off the data file and analyzed it using Excel. Even after doing some filtering using the AVERAGE function on the data, it is not obvious that the accelerometer could distinguish lateral acceleration.

Later I observed that the train engine had this notorious habit of shuffling side to side while running because of its high center of gravity and short wheelbase. This motion was short but strong enough that it swamped the acceleration of the train around corners.
That was the end of the proof-of-concept and the project was shelved for a couple of years.

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>