Basic Raspberry Pi WebSocket Robot

Dmitry Mosquid
4 min readNov 25, 2022


I’ve been using Raspberry Pi as a home server for years until one day I decided to find out “what are those pins for”? I ended up reading a lot about GPIO and it felt like I must find a proper use for my retired Raspberry Pi 2 Model B. So I decided to build a robot.

Before we begin

  • You need to have your Raspberry Pi ready with Raspbian (or any other Linux distro) on board (guide).
  • You need to have Python 3 (guide) and Git (guide) installed on your RPi.
  • You should be able to control your Raspberry Pi either via ssh or with a physical keyboard and screen (guide for the headless setup).


  • Chassis. I got somewhat lucky as my local Raspberry distributor had this little guy (STS-Pi by Pimoroni) in stock. But any other dual-motor chassis will do just fine.
  • Wiring. I built my prototype using a breadboard, jumper wires, and a highly convenient T-Shaped GPIO extension board.
  • L293D chip. It was an absolute game-changer for me. L293D is a super straightforward and very convenient motor driver. If you are new to the field, it will surprise you how much you get for less than a dollar.
  • Power supply. Any USB power bank should work. For this example, I picked one that has two USB outputs: one for powering the Pi and another one for the motors.
  • Camera (optional). In my stockpiles, I found a wide-angle camera for Raspberry Pi. It fit nicely on my chassis so decided to set up a simple streaming service using Picamera.
  • Raspberry Pi. And, of course, the brain center of our project. Please note that older Pi’s come with no onboard WiFi module. For the 1st and 2nd generations, you are going to need a USB dongle.


  • Server. I made a fairly simple Python WebSocket server and hooked up the message handler to the motor controller. Each message contains directional and speed parameters for both motors.
  • Client. I made a little React app using an amazing React Joystick Component. My code is available here. It’s also deployed to Vercel. You can just enter your robot’s IP address and control it from there.
  • Video streamer. I made it a part of the server code but in fact, it’s a separate process, listening to a different port (pending refactoring). It’s basically just a rewrite of one of the recipes I found in the Picamera documentation.

Wiring diagram

Yeah, I know. I’ve also seen a prettier schematic

You need two pins per motor to control the direction of the rotation (one pin for moving forward, one for reverse). The rotation speed is controlled by the frequency of pulses. This is elegantly handled by gpiozero library, which I use in this project. For controlling the left motor I chose GPIO pins 12 and 13. For the right one 25 and 21. The pins are interchangeable so if you choose to use a different combination you have to make corresponding edits in the server code.

Setting up your Raspberry Pi

Connect to your Pi via ssh and clone the WebSocket server:

git clone

Install the dependencies and make the server start automatically on boot:

cd py-robot-websocket-server && sh

The controller

For the controller app, I wanted to have a proper CI/CD pipeline so that the changes I push to the main branch will be automatically deployed. Vercel is a perfect solution for that. But it has one “flaw”: only HTTPS connections are allowed. By default, browsers won’t let you connect to a non-secure WebSocket (ws://) from a webpage served over HTTPS. My solution was to set up a basic Nginx reverse proxy directly on my RPi. It acts as an https-to-http proxy, providing http access to my app deployed at Vercel. Alternatively, you can go with self-signed certificates.

Nginx proxy config:

server {
location / {

Or just clone react-remote-control and run it locally. It will run on port 3000 over HTTP:

git clone
cd react-remote-control
npm install
npm start
`Beep` and `Lights` are a part of the React Controller v2 :)

Connecting the dots

If everything is done correctly, you should have:

  • The Python WebSocket server running on your Raspberry Pi.
  • The WebSocket server listening to port 5000 (e.g. The camera broadcast is on port 8000.
  • If you went the extra step and spent time setting up Nginx server, the frontend should be available on port 80 of your Raspberry Pi’s IP address.

Feel free to reach out in the comments section if something isn’t clear or doesn’t work.