5.1 KiB
Title: Slot Car Racing over IP (SCRoIP) Date: 2022-08-28 16:05 Author: Error Slug: scroip Summary: I built a remote control for a slot car racing track to play with it over the LAN. It's unnecessary complicated and inefficient, but at least it supports IPv6. Ladies, Gentlemen and everyone else, start your engines. License: CC-BY-NC https://creativecommons.org/licenses/by-nc/4.0/
The Idea
When I was a child, I used to play a lot with my slot car racing track. After stumbling upon it again recently, I started wondering if I could build something to control it over the network. Not that I needed a remote control for it, but it seemed like a fun project. However, simply creating an API that offers precise control over the device seemed way to straight forward - the controlling mechanism itself should add its challenges. So I came up with the idea to control it with the traffic itself. The more traffic is sent to the remote control, the faster the car is supposed to go.[°Use more bandwidth!!!]
Reversing
In order to build the remote control, the first step was to figure out how the slot car racing system works. So I disassembled it and took a look at its wiring.
The underlying mechanism is fairly simple. The power supply provides about 14.8 V DC voltage, which is used to power the car's motor. The speed of the car is controlled by a variable resistor within the controller, which allows to control the voltage the car receives. Pushing the controller further down lowers the resistance, which raises the voltage available to the car and makes is go faster. A third wire is used to brake the car when the controller is in its neutral position by utilizing the current generated by the motor when the car is rolling out. A look at wikipedia confirms this analysis. 1
Building a digital Controller
Now that I understood the mechanism, the next step was to create a digital version of it, so that I could control the slot car racing track with a Raspberry Pi. My first idea was to simply use a digital potentiometer. However, searching for a suitable digipot, I quickly realized that there were no options with the desired dimensions of about 30 Ω available. Therefore I built it myself using a few resistors, solid state relais and multiplexers.[°I'm sure there are simpler solutions for this, but, well, it worked for me.]
For the sake of simplicity,[°or maybe out of laziness, who knows? :)] I did not add the braking mechanism from the analog controller to my digital version.
Implementing the Server
With the hardware fully assembled and soldered, it was time to have a look at the software.
Python offers an easy way of implementing TCP servers.[°This project will use TCP. Even though the payload is immediately discarded, reliability is of the utmost importance and packet loss will not be accepted!!!]
By default, it only supports IPv4, but IPv6 support can be added by setting address_family
to AF_INET6
.
if not legacy:
self.address_family = AF_INET6
super(SCRoIPServer, self).__init__((address, port), SCRoIPRequestHandler)
The server's logic itself is implemented in the method handle()
of the class SCRoIPRequestHandler
. While there is an active connection, it reads from the socket and sums up the amount of data that was received.
Once every 100 ms, it then calculates the average throughput for that time period and sets the raspi's GPIO pins accordingly.
while self.data != b'':
try:
self.data = self.request.recv(4096)
self.traffic_counter += len(self.data)
except TimeoutError:
pass
time = clock_gettime_ns(CLOCK_REALTIME)
diff = time - self.last
if (diff > 100000000):
self.last = time
traffic: float = self.traffic_counter / diff * 1000000000
print(f"{traffic} Bytes/s")
self.server.set_throttle(traffic)
self.server.apply_throttle()
self.traffic_counter = 0
The full server code can be found here.
Lights out and away we go
Once the server was implemented as well, all that was left to do was to test it. So I deployed the server script to a Raspberry Pi, connected its GPIO pins to the controller and the controller to the slot car racing track. Using netcat, I was now able to accelerate the car with the network traffic I generated: