Bluetooth remote controlled robot
Make your own bluetooth remote controlled robot using a Raspberry Pi Pico W and MicroPython
3 July 20234 minute read
By Kevin McAleer
Share this article on
Make your own bluetooth remote controlled robot using a Raspberry Pi Pico W and MicroPython
3 July 2023
By Kevin McAleer
Share this article on
Watch the associated video here:
Hello fellow Makers! Today, weโre going to learn how to use Bluetooth on the Raspberry Pi Pico using MicroPython.
Back in mid-June this year, the Raspberry Pi team announced that the Bluetooth functionality is now available for Raspberry Pi Pico. Exciting, isnโt it?
Weโll upgrade our firmware, and create two programs; one for the remote control and one for the robot itself.
Iโve used the BurgerBot robot as a platform for experimenting with bluetooth, and you can learn how to build your own using with the information in the link provided.
Before we get started, letโs dive into some Bluetooth basics. Bluetooth is a wireless communication technology used to exchange data over short distances. Invented by Ericsson in 1989, it was intended to replace RS-232 data cables to create wireless communication between devices.
Bluetooth operates between 2.4 and 2.485 GHz in the ISM Band, and typically has a range of up to a hundred meters. Itโs ideal for creating personal area networks for devices such as smartphones, PCs, peripherals, and even for controlling robots.

There are two different types of Bluetooth technologies:
Classic Bluetooth or Human Interface Devices (HID): This is used for devices like keyboards, mice, and game controllers. It allows users to control the functionality of their device from another device over Bluetooth.
Bluetooth Low Energy (BLE): A newer, power-efficient version of Bluetooth, itโs designed for short bursts of long-range radio connections, making it ideal for Internet of Things applications where power consumption needs to be kept to a minimum.

To access this new functionality, all we need to do is update the firmware on our Raspberry Pi Pico. This can be done either using an updater or by downloading the file from micropython.org and dragging it onto our Pico from the explorer or Finder window.
A Bluetooth connection goes through a series of different stages. First, we need to advertise a service on the server (in our case, the Raspberry Pi Pico). Then, on the client side (the robot, for instance), we need to scan for any remote control nearby. Once itโs found one, we can then establish a connection.
Remember, you can only have one connection at a time with Raspberry Pi Picoโs implementation of Bluetooth in MicroPython. After the connection is established, we can transfer data (up, down, left, right commands to our robot). Once weโre done, we can disconnect.

GATT, or Generic Attribute Profiles, is used to establish the communication between two devices. However, itโs only used once weโve established the communication, not at the advertising and scanning stage.
To implement GATT, we will need to use asynchronous programming. In asynchronous programming, we donโt know when a signal is going to be received from our server to move the robot forward, left, or right. Therefore, we need to use asynchronous code to handle that, to catch it as it comes in.
There are three essential commands in asynchronous programming:
async: Used to declare a function as a coroutine.
await: Used to pause the execution of the coroutine until the task is completed.
run: Starts the event loop, which is necessary for asynchronous code to run.


There is a module in Python and MicroPython that enables asynchronous programming, this is the asyncio (or uasyncio in MicroPython).
We can create special functions that can run in the background, with multiple tasks running concurrently. (Note they donโt actually run concurrently, but they are switched between using a special loop when an await call is used). These functions are called coroutines.
Remember, the goal of asynchronous programming is to write non-blocking code. Operations that block things, like input/output, are ideally coded with async and await so we can handle them and have other tasks running elsewhere.
The reason I/O (such as loading a file or waiting for a user input are blocking is because they wait for the thing to happen and prevent any other code from running during this waiting time).
Itโs also worth noting that you can have coroutines that have other coroutines inside them. Always remember to use the await keyword when calling a coroutine from another coroutine.
Iโve uploaded the working code to Github Gists so you can understand whats going on.
To use this code:
main.py - this will ensure it runs when the Pico is powered up.main.pyThe picos should flash quickly when not connected, and slowly once the connection is established.
Kevin McAleer
I build robots, bring them to life with code, and have a whole load of fun along the way
Social Links:
If you found this high quality content useful please consider supporting my work, so I can continue to create more content for you.
I give away all my content for free: Weekly video content on YouTube, 3d Printable designs, Programs and Code, Reviews and Project write-ups, but 98% of visitors don't give back, they simply read/watch, download and go. If everyone who reads or watches my content, who likes it, helps fund it just a little, my future would be more secure for years to come. A price of a cup of coffee is all I ask.
There are a couple of ways you can support my work financially:
If you can't afford to provide any financial support, you can also help me grow my influence by doing the following:
Thank you again for your support and helping me grow my hobby into a business I can sustain.
- Kevin McAleer
Comments