88 lines
5.1 KiB
Markdown
88 lines
5.1 KiB
Markdown
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 stubling 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 sriaght forward - the controling 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.
|
||
|
||
![Simplified circuit diagram for a slot car racing system]({static}/posts/scroip/carrera.svg "Simplified circuit diagram of a slot car racing system")
|
||
|
||
The underlying mechanism is fairly simple. The power supply provides about 14.8 V DC voltage, which a 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.]
|
||
|
||
![SCRoIP controller circuit diagram]({static}/posts/scroip/scroip.svg "SCRoIP controller circuit diagram")
|
||
|
||
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 ammount 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](https://git.undefinedbehavior.de/undef/SCRoIP "Slot Car Racing over IP - SCRoIP - undefined git server").
|
||
|
||
## 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:
|
||
|
||
<video controls preload="metadata">
|
||
<source src="{static}/posts/scroip/demo.webm" type="video/webm">
|
||
<p>
|
||
The video could not be loaded.
|
||
You can try to download it directly <a href="/posts/scroip/demo.webm">here</a> instead.
|
||
</p>
|
||
</video>
|
||
|
||
[^1]: [https://de.wikipedia.org/wiki/Autorennbahn#Fahrzeugsteuerung](https://de.wikipedia.org/wiki/Autorennbahn#Fahrzeugsteuerung "Autorennbahn – Wikipedia")
|