# How I built an RC car controlled over the Internet which can measure temperature (The Earth Rover) ![](https://i.imgur.com/xeuXdaZ.png) **by Adam Leo.** This tutorial will go through my process of building an RC car connected to WiFi and controlled via an Android application connected to the internet. That is, the RC car and the Android application does not need to be on the same network. Therefore making it possible to control the car from anywhere in the world. Furthermore, the RC car also takes the temprature wherever it goes and sends it to the application which in turn displays it in a graph. My personal buliding time for this project was lengthy, but that is including all the research and mistakes. If one were to follow a long with this tutorial and has all the necessery parts, I think it could be done in a few hours. However, this is if you use the Android application I created, if you want to create your own application, then the building time would increase. ## Objective The objective was to create a minitaure Mars Rover, jokingly called the Earth Rover. I choose to do this specfic project due to it being very extendable and scalable for future adaptations and build-ons. Meaning, my tinkering with this project is long from over. But as it stands now, it only measures the temprature. The purpose of the Earth Rover is purely for fun. However, the process of making it was highly educational. And I expect I will learn a great deal more as I contiune my tinkering. ## Material You will need to either own a RC car, or to buy one. This one will be butcherd and turned into a freak, so ideally you shouldn't have any sentimental connection to the RC car you are about to frankenstein. A fairly cheap one should do, as long as it as at least on DC motor for steering and at least one for driving. The one I had lying around, had one DC motor for steering and two for driving. Or if you want to, you can buy your own wheels and DC motors, but this tutorial will not explain how to put those two things together. The good thing about an already existing RC car, is that they usually have a pretty realible mechanics for steering. Some of the material I used could be omitted if the RC car would be created a bit differently. For example the LM2577 and the powerbank could be switched out for an 9V battery instead. Then you would need to buy 9V battery connector. However, those are very cheap and can be bought for under 20 Kr (Approximately 2 euros). By doing this, the final price of the RC car would be significantly lower. You could also choose to use the power supply already existing on the RC car. Usually they have a number of AA batteries connected at the bottom. | Device | Info | Bougth From | Price | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ----- | | Lopy4 | A quadruple bearer MicroPython enabled development board (LoRa, Sigfox, WiFi, Bluetooth). Has many analog input and outputs and is well suited for an IoT project. | https://www.m.nu/pycom/lopy4-with-headers | 559Kr | | Expansion Board 3.1 | Expansion Board for LoPy4 | https://www.m.nu/pycom/expansion-board-31 | 269Kr | | 7805 | 5V Voltage Regulator | https://www.m.nu/ic-transistorer/5v-15a-linear-voltage-regulator-7805-to-220 | 9Kr | | LM2577 | Adjustable step up module to increase voltage | https://www.kjell.com/se/produkter/el-verktyg/arduino/stromforsorjning/velleman-stallbar-step-up-modul-p90727 | 250Kr | | Jumper Wires | Female/Male | https://www.m.nu/breadboarding/breadboarding-premium-female-male-extension-jumper-wires-40-x-6-150mm-1 | 45Kr | | Jumper Wire Bundle | Male/Male | https://www.m.nu/breadboarding/breadboarding-wire-bundle-65pcs | 49Kr | | L298N | DC Motor Driver Board | https://www.m.nu/servo-motorer-robotics/l298-dc-motor-driver-board | 89Kr | | TMP36 | Temperature sensor | https://www.m.nu/sensorer-matinstrument/tmp36-analog-temperature-sensor | 29Kr | | Power Bank | Will be used as a power supply | https://www.proshop.se/Powerbank/Samsung-EB-P1100-power-bank-Powerbank-Silver/2727495 | 238Kr | | Breadboard | For solderless connections | https://www.kjell.com/se/produkter/el-verktyg/elektronik/elektroniklabb/kopplingsdack-400-hal-p36285 | 90Kr | Moreover, one will also need an USB to USB-C cable. The final price is: 1627 Kr (Approximately 155 euros). However, as I mentioned above, one could use a 9V battery instead or the power supply present on the RC car, then the price would be: 1139 kr (Approximately 110 euros). ## Computer setup ### Setting up the Expansion Board and LoPy Firstly, one needs to update the firmware on the Expansion Board. Pycom has an guide on how to do this: https://docs.pycom.io/pytrackpysense/installation/firmware/ When the Expansion Board has been updated, one can insert the the LoPy4 module on the Expansion Board with the reset button pointing towards the USB connector. It should firmly click into place and the pins should now no longer be visible. As described in the pycome documentation. https://docs.pycom.io/gettingstarted/connection/lopy4/ However, one can skip the steps regarding the antenna, as the RC car will be connected to WiFi and not LoRa/Sigfox. When the LoPy has been inserted, it is time to update the firmware on it. Pycome once again has a guide on how to do this (Follow the Expansion Board 3.0 steps): https://docs.pycom.io/gettingstarted/installation/firmwaretool/ When everything has been set up correctly one can choose which IDE they would like to work in, I choose Visual Studio Code, but one could also use Atom. ### Visual Studio Code Set Up with Pymakr To download and install Visual Studio Code, navigate to VS Code: https://code.visualstudio.com/ You will also need NodeJS installed on your PC (The latest LTS Version): https://nodejs.org/en/ The when Visual Studio and NodeJS have been installed, open Visual Studio. Follow the steps in the pycome guide to install Pymakr: https://docs.pycom.io/pymakr/installation/vscode/ ### Setting Up Your Project Directory 1. When the IDE has been installed with the pymakr plugin go ahead and create a folder on your PC, wherever you want, I created mine on the desktop for easy access. 2. In the newly created folder create a new folder called lib 3. Open Visual Studio 4. Press File -> Open Folder and then choose the folder you first created. 5. In Visual Studio, to the left, you will now find a representation of that folder 6. Create two empty files, main.py and boot.py, in the main folder, see Figure 1 (you may get prompted to install the 'Python' extenstion, you may press install). ![](https://i.imgur.com/NwcY5OP.jpg) Figure 1. Showing where to click to create new files. 7. Every other .py files will be located in the lib folder (Meaning boot.py and main.py are the only .py files which will be in the main folder). #### Creating the Config File 1. In Visual Stuido, in the same working directory, create a new file, refer to Figure 1. 2. Name the file pymakr.conf 3. Structure it the following way (you may have to change the address of your COM-address, you can find which COM address you have in the device mananger, see Figure 2): ``` { "address": "COM4", "username": "micro", "password": "python", "sync_folder": "", "open_on_start": true, "safe_boot_on_upload": false, "py_ignore": [ "pymakr.conf", ".vscode", ".gitignore", ".git", "project.pymakr", "env", "venv", ], "fast_upload": false } ``` The project directory has now been implemented correctly. ![](https://i.imgur.com/5fHTtLd.png) Figure 2. Shows how to find which COM address you have. ### MicroPtyhon Libraries The project uses a number of MicroPtyhon Libraries. However, all except one are already present on the flash memory. Meaning, you only need to import one extra .py file to the lib folder (disregarding the files you need to write yourself). This file is called umqtt.simple and is used to communicate via the MQTT protocol. This file can be find in the following git repository: https://github.com/micropython/micropython-lib 1. Download the repository 2. Navigate to micropython-lib -> umqtt.simple -> umqtt 3. Copy the simple.py file 4. Paste the simple.py file in your project directory in the lib folder ## Putting everything together As previously mentioned, this project was done mainly as an educational project. I plan on contiune buildning on it and make it more advanced. However, at the moment even calling it a prototype would be streching it. It is very much still in the development phase. The components sits on top of cardboard fasten with electric tape and wood skewers. The carboard sits on top of the bottom part of plastic RC car, see Figure 3. This gives the car a bombesque look. ![](https://i.imgur.com/rOvykro.jpg) Figure 3. Shows the construction of the car. So if you want to do it the budget version then follow my lead; just take large enough cardboard piece, put the battery where it best fits and tape it stuck (mine is under the cardboard), then put the components on top. Connect it to the deconstructed RC car with some more electric tape. Ideally, one would 3D print a caseing which fits both on the RC car bottom and with all the components, this is something I plan on doing in the future when I get hold of a 3D printer. When it comes to connecting all the components together it is possible to do it multiple ways. That is, my setp up is not the absolute set up and if you have the know-how feel free to set it up differently. One example being that instead of using the voltage regulator one can use the 5V IN/OUT pin on the L298N, see Figure 5. It will work exactly the same, but you need one less component. I opted to use a 7805 Voltage Regulator instead, but both ways are viable. The L298N is centeral piece in the setup. Figure 5 shows what everything on the component are. ![](https://i.imgur.com/RW0NP9D.png) Figure 5. An overview of ht L298N motor driver. [electronicshobbyists.com](https://electronicshobbyists.com/controlling-dc-motors-arduino-arduino-l298n-tutorial/) explains the pin out of the motor driver the following way: >**Motor A:** This terminal block will give the output for the first motor. >**12V Jumper:** Keep this jumper in place if your supply voltage is less >than 12V and the 5V power pin will give you the output of 5V. If the supply >voltage is greater than 12V, then remove this jumper and give the 5V supply >to the 5V power pin so that the L298 Dual H Bridge IC can work properly. *(In this build we can leave the jumper in place)* > >**Power Pins:** Give the supply voltage from 5 to 35V at the 12V pin and ground. If your supply voltage is greater than 12, then make sure to remove and 5V pin will act as Input if the Vs will be greater than 12V. *(We will use the 12V pin as input)* >**Enable Pins:** Remove the jumpers on the Enable A and Enable B if you want to control the speed of DC motors and connect these to PWM pins of Arduino. If you want to control the stepper motor with L298N, then keep the jumper on Enable A and Enable B. Keeping the jumper on these pins means that the these pins will be High. *(here we need to remove the jumpers to control the speed of the car/motors)* >**Logic Pins:** Connect the Logic pins to any digital pins of Arduino. These will help in controlling the rotation and speed of DC motors. >**Motor B:** This terminal block will give the output for the second motor. >**5V linear Regulator:** This will step down the supply voltage to 5V and will give the output at the 5V pin. The output voltage from the battery will be 5V (standard for most power banks and other electrical components using USB cables), but I found 5V to be a bit weak for my motors, therefore I added a step up module, see Figure 6, to give the motors some more juice. You could test if your car runs well on 5V then you won't need the step up module (or the voltage regulator as you will only work with 5V). But if your situations are similar to mine, then your motors will need some more voltage to run smoothly, then you need a step up module to step up the voltage. As a consequence you'll need a voltage regulator to drop the voltage down to 5V (as said before, if you don't have a voltage regulator, you can use the 5V IN/OUT on the L298N to do this). The reason for this is because the lopy can handle at most 5.5V (minimum 3.5V). Thus we need to lower the voltage as to not destroy the lopy. I found 10V to be sufficent for the motor driver. So turn the little golden screw on the step-up module til you have a 10V output on a 5V input, see figure 6. Check this with a voltmeter. ![](https://i.imgur.com/S4R6Sm4.jpg) Figure 6. Illustrates how the step-up module looks like. Now, each indvidual component should be ready to connect! Cut a USB to USB-C cable in half and make it breadboard friendly. Follow the wiring on Figure 7. **MAKE SURE THAT YOUR LOPY4 DOES NOT GET OVER 5.5V, OR YOU WILL FRY IT, DOUBLE CHECK WITH A VOLTOMETER.** ![](https://i.imgur.com/67ixJXu.jpg) Figure 7. Illustrates the how the wires are connected between the different components. I recommend right clicking on the image and choose *open image in new tab* to more easily see the details. As mentioned before, the RC car I butchered had three motors. Two of which control driving forward/backward. These have been connected in a parallel circuit as the L298N only supports control for two motors. If your RC car bottom has two motors, one for driving and steering respectively, then you will not need to do a parallel circuit. If on the other hand, your RC car bottom has four motors, two for driving and steering respectively, then you will need to do two paralell circuits. (The reason for parallel circuit is to keep the voltage the same instead of spliting it in half as would happen with a serie circuit) Also take extra care to plug in the temperature sensor and 7805 voltage regulator correctly. ## Platform The platform I used is called [Maqiatto](https://www.maqiatto.com/). It is an online free MQTT broker, which is very easy to use. Figure 8 illustrates how the broker is used. The fact that the broker was straight forward and easy to use with out any hassle was the reason I choose it. However, I might change to a more relaible solution in future if the project grows to complicated for a free MQTT broker. ![](https://i.imgur.com/7TRkG3q.png) Figure 8. Illustrates the communication process between the mobile application and LoPy4 device. There exists other options, such as [AWS IoT](https://aws.amazon.com/iot/) or the Goolge service [Core IoT](https://cloud.google.com/iot-core). Both which are bit more complicated to set up, but offer greater control over your connected devices. Both Google and AWS also offer more network services which could be combined to create more comprehensive solutions. These services also scales a lot better. ## LoPy4 and The Code The code exists of 8 files, including the boot and main files as well as the previously mentioned umqtt.simple file; which is used for communication over the internet with the MQTT protocol. The other files are: * wifi.py Used for connecting to wifi * mainloop.py Executing the loop that runs the functions which makes driving/steering possible as well as fetching the temperature. * temp.py Gets the temp from the ADC pin * drive.py Sends HIGH or LOW to the output pins aswell as deciding the PWM strength * config.py Stores config data, such as wifi parameters and broker configuration ![](https://i.imgur.com/WQaxm1X.png) Figure 9. Shows the flow of the program. Dashed lines means that the code is executed as soon as imported. Colors other than blue on the flow rectangles means calls to other python files. **boot.py**: ``` # boot.py -- run on boot-up # can run arbitrary Python, but best to keep it minimal import gc gc.collect() ``` **main.py:**: ``` import time import wifi import mainloop mainloop.run() print('END') ``` **wifi.py**: ``` import network import config import pycom import time #Inorder to change led heartbeat must be false pycom.heartbeat(False) # connecting to network wlan = network.WLAN(mode=network.WLAN.STA) wlan.connect(config.WIFI_SSID, auth=(network.WLAN.WPA2, config.WIFI_PASS)) searchCount = 0 print('searching...') while not wlan.isconnected() and searchCount < 1000: pycom.rgbled(0xFFFF00) # Yellow time.sleep_ms(50) searchCount += 1 if wlan.isconnected(): print('connected') pycom.rgbled(0x0000FF) # Blue print(wlan.ifconfig()) else: print('could not connect') pycom.rgbled(0xFF0000) # Red time.sleep_ms(2000) ``` **mainloop.py**: ``` from simple import MQTTClient import machine import time import ubinascii import temp import config import machine import _thread import drive import math import pycom #callback which is exectued when message from broker is found def sub_cb(topic, msg): pycom.rgbled(0x00FFFF) #Blue msg_s = str(msg) #get values from str values = [int(s) for s in msg_s.split() if s.lstrip('-').isdigit()] duty_cycle_steer = math.fabs(values[0]/100) * 2 duty_cycle_drive = math.fabs(values[1]/100) * 2 #increase duty_cycle to make driving more uniformed if duty_cycle_drive >= 0.8: duty_cycle_drive = 1 elif duty_cycle_drive: duty_cycle_drive += 0.2 steer_right = True drive_forward = True if values[0] < 0: steer_right = False if values[1] < 0: drive_forward = False drive.steer(steer_right=steer_right, duty_cycle=duty_cycle_steer) drive.drive(drive_forward=drive_forward, duty_cycle=duty_cycle_drive) def connect_and_subscribe(): client_id = ubinascii.hexlify(machine.unique_id()) client = MQTTClient(client_id, config.MQTT_SERVER, config.MQTT_PORT, config.MQTT_USER, config.MQTT_PASS) client.set_callback(sub_cb) client.connect() client.subscribe(config.TOPIC_DRIVE) print('Connected to %s MQTT broker, subscribed to %s topic' % (config.MQTT_SERVER, config.TOPIC_DRIVE)) return client def restart_and_reconnect(): print('Failed to connect to MQTT broker. Reconnecting...') time.sleep(10) machine.reset() def sendTempToBroker(client,apin): while True: tempString = str(temp.getTemp()) print("Temperature = %s C" % temp) client.publish(config.TOPIC_TEMP, tempString) time.sleep(config.MSG_INTERVAL) #function sub_cb will be called if message is availble def checkForMessages(client): while True: client.check_msg() def run(): try: client = connect_and_subscribe() adc = machine.ADC() apin = adc.channel(pin='P16') #creating two threads so that the two loops can be run in parallel temp_thread = _thread.start_new_thread(sendTempToBroker, ((client, apin, ))) drive_thread = _thread.start_new_thread(checkForMessages, ((client, ))) pycom.rgbled(0x00FF00) #Green except OSError as e: restart_and_reconnect() ``` **temp.py:** ``` import machine adc = machine.ADC() apin = adc.channel(pin='P16') def getTemp(): value = apin() return ((value * 1100)/ 4096 - 500) / 10 ``` **drive.py**: ``` from machine import PWM from machine import Pin # initialize pins in gpio mode and make it an output p_out_backward = Pin('P23', mode=Pin.OUT) p_out_forward = Pin('P22', mode=Pin.OUT) p_out_right = Pin('P21', mode=Pin.OUT) p_out_left = Pin('P20', mode=Pin.OUT) # initialize pins in pwm mode to control dc motor speed pwm = PWM(0, frequency=490) pwm_c_steer = pwm.channel(0, pin='P9', duty_cycle=0) pwm_c_drive = pwm.channel(0, pin='P11', duty_cycle=0) def drive(drive_forward, duty_cycle): print(duty_cycle) pwm_c_drive.duty_cycle(duty_cycle) p_out_forward(drive_forward) p_out_backward(not drive_forward) def steer(steer_right, duty_cycle): print(duty_cycle) pwm_c_steer.duty_cycle(duty_cycle) pwm_c_drive.duty_cycle(duty_cycle) p_out_right(steer_right) p_out_left(not steer_right) ``` **config.py:**: (Hiding some information for security reasons) ``` # wifi configuration WIFI_SSID = '*******' WIFI_PASS = '*******' # IoT Broker Configuration MQTT_SERVER = 'www.maqiatto.com' MQTT_PORT = 1883 MQTT_USER = '**********@gmail.com' MQTT_PASS = '***********' TOPIC_DRIVE = b'***********/drive' TOPIC_TEMP = b'*************/temp' MSG_INTERVAL = 30 #seconds ``` ## Transmitting the data / connectivity The project uses the Message Queuing Telemetry Transport protocol (MQTT for short). The MQTT makes use of the publish–subscribe pattern to deliver lightweigth communication between devices. Perfect for machine to machine communication, as often is the case with IoT devices. The fact that MQTT is lightweight improves the transfer speed over the internet over other options, such as the HTTP protocol. The LoPy uses the MQTT to subscribe to the driving/steering topic which are published from the Android application. In the same vein, the Android application is subscribed to the temprature topic which are published from the LoPy4. It does this via the MQTT broker, see figure 10 above. Due to the steering need to be as responsive as possible WiFi was choosen to communicate wirelessly. This is because WiFi generlly have higher transfer speed than LoRa/Sigfox. The temprature is sent every thrity seconds as to not bloat the application with MQTT messages, as the application would crash if messages were sent to often. Moreover, the temperature generally does not vary too much in the timeframe of a few seconds, making multiple messages a second redunant. The driving/steering instruction is sent everytime the users chooses (touches the virtual joystick on the mobile application). ## The Android application and data visualization The application has been coded by me in Android studio using kotlin. I made use of the following git repositories: * https://github.com/controlwear/virtual-joystick-android (for the virtual joystick) * https://github.com/jjoe64/GraphView (for the graph) Here is the [APK file](https://www.dropbox.com/s/adhq54yyzzb9cq1/rovercontroller.apk?dl=0) for the application if you want to try it for yourself. As of right now there's a bug where you have to press the connect button multiple times before connecting correctly (I will fix this soon). The application has two activites, one where you send and visualize the data and one where you connect to the broker, see Figure 10 and 11. ![](https://i.imgur.com/Bs7ifhD.jpg) Figure 10. The joystick is used to send driving/steering instruction and the graph shows the temperature. ![](https://i.imgur.com/Sw3bMvb.png) Figure 11. The connection parameters to send to the MQTT broker. Data is never stored in a database, instead the data only lives for as long as the application is open. This makes it impossible to compare old data to the newly fetched data. This is something I plan to change later. To store the data somewhere (either internal on the mobile's SQL database or some cloud database). Together with adding more sensors I plan on making the car more useful as measuerment tool. The reason for not having a database at the moment, is because the temperature data is not all that intresting, so for now, having a database didn't seem worth the extra work. ## Finalizing the design I am proud over my project. And driving the car with my mobile application is very satisfying. I also think the car looks rather cool, see Figure 12. ![](https://i.imgur.com/Ss6LyYV.jpg) Figure 12. A Picture of the finished (for now) car. There are of course some things which could be improved: * Store the temperature data in a database and enable comperasion between data * Add a 3D printed casing to the car * Add more sensor to get more valubale data Etc. But these are things I plan to implement as I continue to tinker with the project.