Introduction: RC Car Tracking

About: Student MCT at HOWEST (Kortrijk, Belgium)

For my end project for Multimedia & Creative Technology at Howest Kortrijk I had to make a project that combined all the previous classes into one. This involved hardware, software and a responsive site. I decided to make this project in memory of my grandad who passed away due to Covid in January. He was one of the founders of the Miniature Racing Club Zwevegem, so my choice was to make a device to track different statistics of RC cars, and dubbed it Race Tracking.

The features of Race Tracking

  • Viewing current acceleration
  • Viewing current temperature
  • Automatic lights inside the hood
  • Overheating alarm
  • Ability to modify or turn on/off lights
  • Looking up previous statistics

Supplies

Server side

  • Raspberry Pi 4
    The main controller. This runs the database, backend and website
  • 2x16 LCD Display
    The main display for the Raspberry Pi. This shows the Pi's IP address to allow you to connect the ESP32 to it

Onboard

  • ESP32-WROOM
    The main controller for the onboard electronics. This will communicate over WiFi with the Pi to transmit all the sensor data
  • MPU6050
    This measures the acceleration of the car
  • Neopixels x2
    LED sticks to light up the car
  • 8 Ohm Miniature Speaker
    To play an alarm when the engine starts overheating
  • Voltage Regulator
    To reduce the power supply from 7.4V to 5V
  • One Wire Temperature Sensor DS18B20
    Measures the temperature in the car
  • Ambient Light Sensor
    Measures the light intensity in the car
  • Plexi glass
    This will be the base for the project to go on
  • Various resistors
    Depending on the hardware bought you need different resistors. Please refer to the datasheets of the components for this.

RC Car

  • 1:10 or larger model on battery power
    I personally used a custom built 1:10 car. This Instructable goes more into detail on how to pick a car.
  • 5200 mAh 50C LiPo Battery
    Since I only own these types of batteries for my cars, I cannot guarantee the project will work on weaker batteries. Be careful with these as charging/discharging them improperly can lead to the battery exploding.

Tools

  • Soldering iron and solder
  • Double sided tape for plexi glass, or plexi glass glue

All in all, this project comes to about €118, assuming you already own a RC car with a strong enough battery.

Step 1: Prototyping

The first step of any project involving electronics is making a test setup on a breadboard first. If you want you could skip this step and go straight ahead to the next one, but I would strongly advise against that. Not only is a breadboard setup useful to see if you didn't make any mistakes in your circuits, it's also a great way to test all your components. For example, when I tested my circuits were fine, but the speaker I had received just straight up didn't work.

Due to limitations of the software used to draw these I could not show it, but the ESP32 gets powered by the battery as well. My model had a VIN pin, which powers the controller on 5V, so just make sure you connect the regulator out pin to the ESP32 VIN pin. If yours doesn't have this, a powerbank is a less elegant solution.

Step 2: Software

To start things off we will make sure we have all the necessary software to complete this project. In summary we will need:

  • Raspberry Pi packages
    • Python
    • Mosquitto
    • Apache
    • MariaDB
    • ...
  • PC
    • IDE for ESP32 (I used the Arduino IDE)
    • SSH client (I used Visual Studio Code)

Now let's get started!

1. Installing the Pi image

At first the list of Raspberry Pi packages might seem daunting. Luckily there is a custom image available here that has all the necessary packages installed. A guide on how to install this can be found here.

Please follow the steps on the image site on how to customise access to the device

2. Setting up interfaces

Now use

sudo raspi-config

Go to interfacing options and enable I2C and 1-wire. Make sure to reboot the Pi with

sudo reboot 0

3. Setting up the Mosquitto broker service

In this step we will add a username and password to our Mosquitto service. This is the service which will function as a medium between the ESP32 and the Raspberry Pi.

Normally everything on the image is set up already as it should be, but the current username and password for this service are 'fluvisol'. If you want to use your own simply use

sudo mosquitto_passwd -c /etc/mosquitto/pwfile username<br>

And change username by the name you want to use. It will then prompt you for a password, use whichever you like.

4. The Arduino and VSCode IDE

For this project I recommend using these 2 IDE's. There are different options out there so if you are used to something else, feel free to use that instead!

Visual Studio Code can be found here

Once it's installed, download the extensions for Python and Remote SSH. The latter will enable you to use VSCode as a SSH client and to use it to edit code directly on the Pi

The Arduino IDE can be found here

To use this on your ESP32, you have to follow the steps in this guide. I personally used the DoIt ESP32 DEVKIT board.

5. Installing libraries

We will need some libraries on our ESP32 to be able to make everything work. To do this, in the IDE go to Tools > Manage Libraries, then search for and install the following packages:

  • Wire
  • Wifi
  • PubSubclient
  • DS18B20
  • Adafruit_NeoPixel

Once this is done we're all set to start with the next step!

Step 3: Database

Of course, as with every project that logs data, we will need a database. On my Github repository you can find a SQL file under Code/Database-export. If you run this file, it will create a database with the structure as found above, as well as add all the devices and actions used in this project. Now I will give a quick rundown of what exactly is stored in the database.

1. Devices

This table holds all the information about the devices used. The different columns are:

  • iddevices: The unique ID of every device
  • abbreviation: A shorthand for every device which is easier to recognise without having the table
  • code: The manufacturer's code of the device, useful in case you need to buy a new one
  • Manufacturer
  • Description: What the device does
  • Type: Whether the device does output or input
  • Cost
  • Unit: The measurement unit of the device

2. Actions

This table holds all the different actions that can be done. We have:

  • 1: Read values
  • 2: Save values
  • 3: Turn on
  • 4: Send instruction
  • 5: Set default

3. History

Here we combine both tables to log which device did which action at what time.

Step 4: Backend on the Pi

This step will be pretty straightforward since all the code is available on my github, and all the packages have already been installed on the image. However, I will give a quick rundown of the MQTT.py file because it might look a little confusing. The other files should speak for themselves, however I will in the future add an explanation of everything to my github.

Also do note that if you changed passwords at any point, you need to edit those. Mainly in config.py, the top of MQTT.py and all the way at the bottom in app.py for the shutdown function.

If you don't care much about code, feel free to skip this step as everything should be working.

MQTT.py

This is the file that holds our Wireless class, and is used primarily for communicating with the ESP32.

First, we set the default values. Our Pi has a fallback IP of 192.168.168.168, so that's a good address to set as default. The user and password are defined when we set up the MQTT broker, so if you changed these please use your own. The topic is the messages we want to listen to, which is anything of the form sensors/<something>.

In the initial declaration we also define 2 dictionaries, which will be used later

address = '192.168.168.168'
user = 'fluvisol'
password = 'fluvisol'
topic = 'sensors/+'

def decode(a):
string_a = a.decode(encoding='utf-8')
return string_a

class Wireless:
def __init__(self, address = address, user = user, password = password, topic = topic):
self.address = address
self.user = user
self.password = password
self.topic = topic
# Dict with values from sensors. Easy to add more if desired, more efficient than earlier version of just declaring variables
self.vals = {
"accx" : 0,
"accy" : 0,
"accz" : 0,
"acc" : 0,
"temp" : 0,
"ldr" : 0,
}
self.outvals = {
"actuators/override": 0,
"actuators/lights": 0,
"actuators/sounds": 400,
"actuators/intensity": 50
}

Now we define a bunch of functions that will make everything run smoothly.

  • on_connect_in runs whenever our script connects to the broker service. It will then immediately subscribe to the topic it was initialised with, in our case 'senors/+', and call on the on_message function if a message with that topic arrives
  • on_message runs when one of those messages arrives. here we split the message up in topic and value, the latter of which needs to be decoded as the ESP32 uses a different encoding system. Then we doublecheck if it is indeed a sensors message. If it is not a timing message, we change the values in the dictionary to the new ones. If it is, we know that all the acceleration values have been sent, so we update the added up acceleration
  • publish will run constantly and send all our output messages to the ESP32 every second
  • setup runs once. Here we define the name of the client. Then we set our username and password, the on_connect and on_message functions. When all that is set up, we connect to the broker service and finally start a loop on the publish function. If everything was done right, the Pi will now send instructions every second, and listen for data to be sent to it.
def on_connect_in(self, client, userdata, flags, rc):
print(f'Connected with result code {str(rc)}')
client.subscribe(self.topic)
def on_message(self, client, userdata, msg):
"""The callback for when a PUBLISH message is received from the server."""
sorting = msg.topic
value = decode(msg.payload)
if sorting[:8] == "sensors/" and sorting != "sensors/timing":
t = sorting[8:]
self.vals[t] = float(value)
if sorting == "sensors/timing":
self.vals["acc"] = round(math.sqrt(((self.vals["accx"] / 8192.0) ** 2 + (self.vals["accy"] / 8192.0) ** 2 + (self.vals["accz"] / 8192.0) ** 2)),2)

def publish(self, client):
while True:
time.sleep(1)
for i in self.outvals.keys():
topic = i
msg = self.outvals[i]
client.publish(topic, msg)

def setup(self):
mqtt_client = mqtt.Client("pi_in")
mqtt_client.username_pw_set(self.user, self.password)
mqtt_client.on_connect = self.on_connect_in
mqtt_client.on_message = self.on_message
mqtt_client.connect(self.address, 1883)
mqtt_client.loop_start()
self.publish(mqtt_client)

Step 5: Backend on the ESP32

Now that we have our Pi all set up for communication and data processing, we just need to set up our ESP32 to actually provide the data. Again, the code for this can be found on my github under Code/ESP32. Simply upload the code to your ESP32 through the Arduino IDE and it should work. Be sure to hold the boot button on the ESP when the IDE says connecting, or it will not let you write to it.

This code has nothing particularly hard I think, though feel free to ask questions. I will also try to get an explanation up on github about this code.

Do note that because of using the millis() function, this script can only run for 5 days before that value will overflow. I don't think any battery could keep this running for 5 full days, but it's worth mentioning.

Step 6: Frontend

Again, this is quite simple. Everything is already set up on the Pi, even the files should be present.

If it's not working however, simply copy the files in the frontend folder from the github repository and put them in /var/www/html

Then use

sudo nano /etc/apache2/conf/httpd.conf

And make sure Documentroot is /var/www/html. Also change Directory to this path. (Only if it didn't work initially! Currently the image is set up to use a different folder so if you change this without pasting the files, it will not work anymore)

The website is fully responsive and works on both mobile and desktop.

Step 7: Preparing the Housing

Now we need to get everything ready for the soldering part. Luckily for this project there is not a lot of precision cutting involved. We have to cut the plexiglass to be a bit smaller than the battery, which in my case meant I needed to cut it to 12x4 cm. If you make it the same size, it can be difficult to wire everything as some batteries have connectors on the top rather than at the ends.

To cut your plexi properly, please refer to this guide

Also make sure that all your components fit on the glass. The LCD doesn't need to be there, but everything else should fit on comfortably and with enough space to wire everything

Step 8: Soldering

Now comes the tricky part. There is not much that I can say here sadly other than be careful and think ahead. Unlike a lot of projects, this one requires a lot of precision due to the small amount of space available.

With both the MPU and ESP32 it is easier to just use connecting wires and pins as shown in the picture above. For the ESP this allows for changing pin numbers if needed and for easier maintenance, and for the MPU it's mostly for maintenance purposes.

Make sure the ESP is in a corner, as that will allow you to simply connect the two NeoPixels directly and they should fit right next to it. Also pay attention to the micro USB on the ESP, you want this to be accessible to edit code

Every component except the light and temperature sensors can be stuck to the plexi with double sided tape, just make sure you use the tape normally used on RC cars as this is extremely strong, otherwise your components might come loose while driving. If you have no such tape available, I would recommend using plexiglass glue. This is however more permanent and makes it harder to replace faulty components later down the line.

For those other two, you want the light sensor to stick out through a little hole in the hood, or it will pick up the light from the LEDs and always give high intensity while they're on. The temperature sensor would ideally be stuck to the engine. However this isn't practical, so I just have it loose in the air.

You can connect the VIN pin of the ESP and the 5V pin of one NeoPixel, and then connect those both to the regulator. Same goes for all the ground pins of every component, they can all go in one bunch and connect to the regulator.

Important! Make sure none of the wires are touching the axis of the car, as in the best case scenario this would disconnect your components when driving, and in the worst case it could break your car.

Step 9: Connecting It All

Now all that's left to do is giving our project a place in the car. Most models have a piece of plastic that holds the battery in place. You can use the same tape/glue as in the previous step to simply stick it to that piece, and now you have an easily removable project. Make sure to always put the wires towards the outside of the car, even if it seems counterintuitive. This is to prevent accidents with wires getting caught in the main axis.

For the power supply you simply need to solder two connectors onto the regulator, one male and one female. That way you can plug the project in between the battery and the engine with the least amount of trouble, and on top of that the car can still drive without all these components on it!

As for the Raspberry Pi and LCD, you can make your own little housing with any material you want. I built this project to be used at our RC club, where the Pi will just go with the other networking equipment, so I didn't give the housing much thought.