undefinedbehavior-website/content/blog/scroip.md
2023-10-24 14:19:59 +02:00

78 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Title: Slot Car Racing over IP (SCRoIP)
Date: 2022-08-28 16:05
Author: Error
Slug: scroip
Summary: A remote control for a slot car racing tracks; Unnecessarily complicated and inefficient; Ladies, Gentlemen and everyone else, start your engines.
License: CC-BY-NC
https://creativecommons.org/licenses/by-nc/4.0/
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 too straight forward - the controlling mechanism itself should add its challenges.
So I came up with the idea to control it with the network traffic itself.
The more traffic is sent to the remote control, the faster the car is supposed to go.[°Use more bandwidth!!!]
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}/blog/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 is used to power the car's engine.
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]
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}/blog/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.
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](https://git.undefinedbehavior.de/undef/SCRoIP "Slot Car Racing over IP - SCRoIP - undefined git server").
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}/blog/scroip/demo.webm" type="video/webm">
<p>
The video could not be loaded.
You can try to download it directly <a href="/blog/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")