Resources
Highlights
Introduction
Old android phones are surprisingly capable: sensors, camera, mobile networking, and decent processing power; they are basically Raspberry PIs on steroids with the only downside of having to build a Java/Kotlin android app to program them. When i found out that you can even use them to send serial-over-USB messages to microcontrollers, i immediately got the idea of using one to control a RC car.
Networking

Network diagram
Knowing that:
- With my computer i can read inputs from any video-game controller
- Android phones can talk with microcontrollers Then, if i find a way to make the phone and the computer communicate, i can control anything wired to the microcontroller from everywhere in the world, using a simple video-game controller.
To achieve that, i considered a few options:
- Can’t host anything on the phone - With 4G/5G you are behind CGNAT
- Can’t host anything on the computer - What if the computer is connected to a 4G/5G hotspot or to a network i cannot control?
- Using a third party relay server is out of the question since it only adds more latency
- Tailscale (or similar, e.g., NordVPN Meshnet) is a perfect solution since it creates a VPN between the phone and the computer - Direct communication, no added latency
Circuit
The main board is an Arduino Uno R3
, which i wired to:
- A
L298N
motor driver (old design, if buying new go for MOSFET-based drivers which have lower voltage drop) - A horn (active buzzer)
- Blue underglow leds (resembling neons)
- Voltage dividers to monitor the voltage of the batteries (arduino’s analog pins only support up to 5 volts)
Circuit diagram
Why are there two batteries, one for the electronics and one for the motors? Because:
- I had two
- If i don’t power the electronics with one of the two batteries then they take the power from the phone’s battery (which is already not impressive) via the USB cable used for data transfer
- I don’t think it’s good practice to power the electronics with the same battery used by “heavy” components such as DC motors (the electronics require stable voltage and low current, the motors instead can create large instantaneous current draws, potentially creating voltage drops on the supply rail)

Original car

Modified car (external view)

Modified car (internal view)
Android app
It measures:
- Location (GPS coordinates)
- Heading (degrees)
- Temperature of CPU, GPU, modem and camera
- Battery percentage
- Signal strength

For the video feed, the phone records a 320x240 @ 30fps
stream and compresses it on-device using hardware H264 encoding. H264 NAL units are sent to the computer via a UDP socket. Resolution can be much higher depending on the network bandwidth and hardware capabilities. You can switch from front to back camera and vice-versa in real time (note: see the limitations section below).
Controller GUI
The computer runs a multi-process python back-end. The GUI is organized in tiles, each one rendered by a different process implementing a specific feature:
- The main process reads the controller inputs using
PyGame
, renders the temperature readings an orchestrates all the other processes - A process implements the TCP socket for receiving the metrics
- An
electron
app executing https://gamepad.e7d.io/ is used to display the controller in a borderless window - Another
electron
app renders the received locations on a map. The map is implemented as an HTML file which is built (and updated) usingfolium
andOpenStreetMap
- Another process renders the bandwith chart using
matplotlib
for the graphics andpsutil
for the network counters - Finally, a process renders the stream using
ffmpeg
andPyAV
to receive and decode H264 NALs, andQT5
for displaying the frames with along with the metrics overlay

See it in action
Limitations
Latency is the main limitation of this architecture. You pay the price of being able to control the car from anywhere in the world with a higher latency (50~100 ms) compared to radio control. The main contributor to latency is network latency between the phone and the controller: even with a 5G-capable phone and a controller geographically close to the phone, this kind of latency will never get lower than a few tens of milliseconds, which is enough to comfortably control the car in most situations but not enough for extremely low latency applications such as high speed FPV control
Video stabilization is another limitation of the current architecture. This issue can either be solved in software (requires a buffer of at least a few frames, i.e., more latency) or in hardware (outside the scope of this project). Overall it’s not that big of a deal imo
Software i aint no android dev - you can switch cameras but only twice, then it stops working. There probably are other bugs there (and also in the python code, which is not great by any means). Anyway, for a prototype it’s more than enough