ZeroBot - Raspberry Pi Zero FPV Robot

Raspberry Pi Zero 3D Printed Video Streaming Robot

Similar projects worth following
ZeroBot is a Raspberry Pi Zero W based robot. It can be controlled using any computer or smartphone via a web browser. The integrated camera module makes for a low latency video stream. In addition the Raspberry Pi acts as a Wifi access point, so no router is required. The parts for the hull as well as the wheels can easily be printed on any regular 3D printer.

Some of the key features are:
- Compact CAD design with 3D printed components
- Analog control via a joystick (and multitouch)
- Simple battery solution using only a standard power bank
- Low latency streaming (~0.2s)
- Easy and cheap to build using widely available components

STL files on thingiverse:

View all 6 components

  • The new Zerobot Pro

    Max.K02/20/2018 at 22:02 8 comments

    All new features: More battery power, a charging port, battery voltage sensing, headlights, camera mode, safe shutdown, new UI

    The new software should work on all existing robots. 

    When I designed the ZeroBot last year, I wanted to have something that "just works". So after implementing the most basic features I put the parts on Thingiverse and wrote instructions here on Hackaday. Since then the robot has become quite popular on Thingiverse with 2800+ downloads and a few people already printed their own versions of it. Because I felt like there were some important features missing, I finally made a new version of the robot.

    The ZeroBot Pro has some useful, additional features:

    • Instead of a single battery with a power-bank circuit, the ZeroBot Pro is now powered by two 2600mAh batteries in parallel. Thanks to a cheap TP4056 Micro-USB charger the case does not have to be opened to recharge the batteries. 5V for the Pi and 6V (optional) for the motors are regulated by MT3608 boost converters.
    • Thanks to a ADS1115 ADC the Raspberry can measure the battery voltage and display it on the user interface
    • The entire user interface has been optimized for various screen sizes. There are now buttons for different functions:
      • A photo button for taking pictures in full resolution. This is not as easy as it appears. The stream has to be stopped to start the raspistill application and then restarts.
      • A toggle button to turn the LED headlights on and off. The LEDs are connected via a transistor to an IO pin. (I adopted this idea from franciscorps version of the ZeroBot:
      • Finally there is a shutdown button that turns the Pi off safely after displaying a confirmation prompt. This should prevent the file system from corrupting
    • The 3D printed parts have been optimized as well to reduce warping and to fit the front panel more easily. 

    If you are interested in building the robot, you can head over here for the instructions: 

    The 3D files are hosted on Thingiverse:

    Download the SD card image:

    After flashing the image to a 8GB SD card, open the file "wpa_supplicant.conf" with your PC and enter your WiFi settings.

  • Easy Setup using SD Image

    Max.K06/24/2017 at 13:07 11 comments

      After a few people ran into problems with the tutorial, I decided to create a less complicated solution. You can now download an SD card image for the robot, so there is no need for complicated installs and command line tinkering. The only thing left is getting the Pi into your network:

      1. Download the image file from here and unzip it to your PC:
      2. Flash the image to an 8GB or bigger micro SD card with the software of your choice (e.g. Etcher). Don't plug the SD into the Raspberry yet!
      3. In the boot partition of the SD, open the file wpa_supplicant.conf (e.g. using notepad). Change wifi ssid and password to your wifi name and password. The file will be automatically moved to its spot of the Pi's file system on boot. If you make a mistake, you just need to create the file again.
      4. After the Pi has booted up, find out its IP address using your routers interface or through an app like Fing. Connect to this address (e.g. with any browser on your computer

      If you don't want the robot to be restricted to your home network, you can easily configure it to work as a wireless access point. This is described in the tutorial.

      EDIT 29.7. Even easier setup - the stream ip is selected automatically now

  • Introduction

    Max.K05/29/2017 at 20:53 1 comment

    The goal for this project was to build a small robot which could be controlled wirelessly with video feed being sent back to the user. Most of my previous projects involved Arduinos but while they are quite capable and easy to program, there are a lot of limitations with simple microcontrollers when it comes to processing power. Especially when a camera is involved, there is now way around a Raspberry Pi. The Raspberry Pi Zero W is the ideal hardware for a project like this: It is cheap, small, has built in Wifi and enough processing power and I/O ports.

    Because I had barely ever worked with a Raspberry, I first had to find out how to program it and what software/language to use. Fortunately the Raspberry can be set up to work without ever needing to plug in a keyboard or Monitor and instead using a VNC connection to a remote computer. For this, the files on the boot partition of the SD card need to be modified to allow SSH access and to connect to a Wifi network without further configuration.

    The next step was to get a local website running. This was surprisingly easy using Apache, which creates and hosts a sample page after installing it.

    To control the robot, data would have to be sent back from the user to the Raspberry. After some failed attempts with Python I decided to use Node.js, which features a library. With the library it is rather easy to create a web socket, where data can be sent to and from the Pi. In this case it would be two values for speed and direction going to the Raspberry and some basic telemetry being sent back to the user to monitor e.g. the CPU temperature.

    For the user interface I wanted to have a screen with just the camera image in the center and an analog control stick at the side of it. While searching the web I found this great javascript example by Seb Lee-Delisle: which even works for multitouch devices. I modified it to work with a mouse as well and integrated the socket communication.

    I first thought about using an Arduino for communicating with the motor controller, but this would have ruined the simplicity of the project. In fact, there is a nice Node.js library for accessing the I/O pins: I soldered four pins to the PWM motor controller by using the library, the motors would already turn from the javascript input.

    After I finally got a camera adapter cable for the Pi Zero W, I started working on the stream. I used this tutorial to get the mjpg streamer running: The latency is surprisingly low at just 0.2-0.3s with a resolution of 640x480 pixels. The stream was then included in the existing HTML page.

    With most of the software work done, I decided to make a quick prototype using an Asuro robot. This is a ancient robot kit from a time before the Arduino existed. I hooked up the motors to the controller and secured the rest of the parts with painters tape on the robot's chassis:

    After the successful prototype I arranged the components in Fusion 360 to find a nice shape for the design. From my previous project ( I knew that I would use a half-shell design again and make 3D printed parts.

    The parts were printed in regular PLA on my Prusa i3 Hephestos. The wheels are designed to have tires made with flexible filament (in my case Ninjaflex) for better grip. For printing the shells, support materia is necessary. Simplify3D worked well with this and made the supports easy to remove.

    After printing the parts and doing some minor reworking, I assembled the robot. Most components are glued inside the housing. This may no be professional approach, but I wanted to avoid screws and tight tolerances. Only the two shells are connected with four hex socket screws. The corresponding nuts are glued in on the opposing shell. This makes it easily to access the internals of the robot.


    Read more »

View all 3 project logs

  • 1
    Installing The Latest Raspbian Image

    DISCLAIMER: This is not a comprehensive step-by-step tutorial. Some previous experience with electronics / Raspberry Pi is required. I am not responsible for any damage done to your hardware.

    I am also providing an easier alternative to this setup process using a SD card image:

    This tutorial is based on Raspbian Jessie 4/2017

    Personally I used the Win32DiskImage for Windows to write the image to the SD card. You can also use this program for backing up the SD to a .img file.

    IMPORTANT: Do not boot the Raspberry Pi yet!

  • 2
    Headless Setup

    Access the Raspberry via your Wifi network with VNC:

    Put an empty file named "SSH" in the boot partiton on the SD.

    Create a new file "wpa_supplicant.conf" with the following content and move it to the boot partition as well:

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
        ssid="wifi name"
        psk="wifi password"

    Only during the first boot this file is automatically moved to its place in the Raspberry's file system.

    After booting, you have to find the Raspberry's IP address using the routers menu or a wifi scanner app.

    Use Putty or a similar program to connect to this address with your PC.

    After logging in with the default details you can run

    sudo raspi-config

    In the interfacing options enable Camera and VNC

    In the advanced options expant the file system and set the resolution to something like 1280x720p.

    Now you can connect to the Raspberry's GUI via a VNC viewer:

    Use the same IP and login as for Putty and you should be good to go.

  • 3
    Installing the required software (update 2018)
    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get install apache2 node.js npm
    git clone Desktop/touchUI
    cd Desktop/touchUI
    sudo npm install express
    sudo npm install
    sudo npm install pi-gpio
    sudo npm install pigpio

    Run the app.js script using:

    cd Desktop/touchUI
    sudo node app.js

    You can make the node.js script start on boot by adding these lines to /etc/rc.local before "exit 0":

    cd /home/pi/Desktop/touchUI
    sudo node app.js&

    The HTML file can easily be edited while the node script is running, because it is sent out when a host (re)connects.

View all 7 instructions

Enjoy this project?



manu663 wrote 7 days ago point

Hi all, The zerobot works as a charm but when I forward the port through my router, I get only access to the remote CTL but I receive no video stream. Any advice ? Thx !

  Are you sure? yes | no

Max.K wrote 5 days ago point

There are two ports that you have to forward, 9000 and 3000.

User averneus wrote that he got this to work in the comments here:

  Are you sure? yes | no

manu663 wrote 5 days ago point

Thank you so much ! 

I certainely read that to quickly! My bad !

  Are you sure? yes | no

peppegti wrote 04/13/2018 at 11:16 point


I want to connect with ssh, but I don't know the user and pass

  Are you sure? yes | no

Max.K wrote 04/13/2018 at 14:03 point

It's the default: "pi" and "raspberry"

  Are you sure? yes | no

laflaf3d wrote 04/05/2018 at 11:23 point

Hi Max,

I try your code during I wait to receive component. When I hit "Off" button, my pi shutdown even if I answer "cancel". So in the code I saw :

if(confirm("This will shutdown the Pi.\nAre you sure?"))
alert('Shutting down...\nPlease wait 20s before turning the power off.')
socket.emit('power', 1);

I guess "{ }" are missing !? And alert() and socket.emit() are always executed...

So I wrote that :

if(confirm("This will shutdown the Pi.\nAre you sure?")){ 
alert('Shutting down...\nPlease wait 20s before turning the power off.');
socket.emit('power', 1);
alert("Okay, on the road again!");

I aim to redesign the body to avoid support and add lego compatibility. I will tell you more.

Very very thanks for your work. Beautifull job!

Best regards

  Are you sure? yes | no

Max.K wrote 04/05/2018 at 12:44 point

Thanks, Good catch! I must have though I was using Python. Will be fixed asap.

  Are you sure? yes | no

laflaf3d wrote 04/05/2018 at 13:17 point

and about Nodejs ?

  Are you sure? yes | no

dinujohnk wrote 04/03/2018 at 12:45 point

Hey, why is the USB port and Ethernet disabled in the given image?? Is there any particular reason, what if I turn it on. How to turn it on? 

  Are you sure? yes | no

Max.K wrote 04/05/2018 at 07:48 point

Sorry about the late answer. If you scroll down on this site, spencerjack96 has asked the same question and got a solution from someone.

  Are you sure? yes | no

abuse.twink wrote 04/03/2018 at 12:30 point

Thanks for the detailed description of the process, it turned out very cool

  Are you sure? yes | no

laflaf3d wrote 03/30/2018 at 07:46 point

Hi, I love this project. I have yet the Pi zero and motors. I ordered the other components.

I have some idea to upgrade this robot after my first try :

- make body "Lego" (and "Lego technic") compatible

- improve code to add other stuff (other light, servo, WS2812 lights).

Best regards

  Are you sure? yes | no

Hack&Invent wrote 03/22/2018 at 22:40 point

Hey nice job! wondering why your project didn't win the 2017's edition?

  Are you sure? yes | no

zhongyuhong wrote 03/13/2018 at 20:25 point

I tried your project and finally entered the ip


Well done so far! This is the right IP for the Raspberry Pi

Click here to control the robot

Web page cannot be displayed after 2 seconds

How to solve?

  Are you sure? yes | no

Max.K wrote 03/13/2018 at 22:02 point

I'm not exactly sure what the link does. What version of the image file are you using? Have you tried adding ":3000" after the IP? This should get you to the interface immediately.

  Are you sure? yes | no

zhongyuhong wrote 03/14/2018 at 14:12 point

Yes,i have use port:3000.I  download image file at first ,and I have upgrade to second version by changing "app.js" and "touch.html". I also change  "etc/rc.local" to second version as yours ,but an error still occurred. The message like this:"Well done so far! This is the right IP for the Raspberry Pi Click here to control the robot." But it still can't work when I use it.

  Are you sure? yes | no

Max.K wrote 03/17/2018 at 22:50 point

Did it work before you upgraded to the newer version? The message that you get should only show when the port is not entered after the ip, but I'm no sure about that. In most occasions it might be easier to download the Zerobot Pro image and flash that to the sd card. 

  Are you sure? yes | no

electrobob wrote 03/01/2018 at 14:53 point


  Are you sure? yes | no

kentfisker wrote 01/17/2018 at 13:50 point

This looks awesome - I am trying to buy the components to make one.

What is the little board between your battery and one of the motors?

  Are you sure? yes | no

juandelacosta wrote 03/06/2018 at 03:27 point

battery charger

  Are you sure? yes | no

spencerjack96 wrote 01/05/2018 at 17:38 point

Hi. Did you lock down the USB ports as they don't appear to work booting from a fresh image :(

  Are you sure? yes | no

Max.K wrote 01/10/2018 at 09:25 point

Sorry for the late answer. Yes, at some point I configured the usb port as a usb-lan bridge to my computer. It should be reversible but I would have to look that up. 

  Are you sure? yes | no

juandelacosta wrote 01/12/2018 at 07:37 point

that explains why i couldnot  pair the ps3 controller directly. had to do pair separately via pc app

  Are you sure? yes | no

juandelacosta wrote 01/16/2018 at 06:13 point

if you can please do so next step is trying to add a usb mic and speaker

  Are you sure? yes | no

juandelacosta wrote 02/01/2018 at 04:10 point

 you need to edit /boot/cmdline to remove modules-load=dwc2,g_ether  .. and remove the reference dtoverlay=dwc2  from /boot/config.txt

seems to work

  Are you sure? yes | no

juandelacosta wrote 12/20/2017 at 10:15 point

i dont know but doing a update and upgrade killed node and a few other things. what should i do?

  Are you sure? yes | no

Max.K wrote 12/20/2017 at 21:15 point

I'm not sure what that problem could be. Maybe it installed a new version of that is not compatible with the code. If nothing else works you can flash the SD image again.

  Are you sure? yes | no

juandelacosta wrote 12/20/2017 at 21:23 point

yeah but im adding other features like ps3 controller,audio mic and  sound and i got the robot also to samba share files.

  Are you sure? yes | no

Max.K wrote 12/21/2017 at 14:10 point

Maybe you can try to run the node script from the command line to see if there are any errors. But I‘m not an expert on this.

  Are you sure? yes | no

juandelacosta wrote 01/11/2018 at 01:53 point

its strange the ccd its self fried

  Are you sure? yes | no

juandelacosta wrote 01/11/2018 at 01:54 point

picked up a new pi 5mp and did a bit of testing everythung works and even the pcb works but not the ccd. ill find a new ccd hopefully

  Are you sure? yes | no

guiducci.alessandro wrote 10/24/2017 at 19:15 point

hi! I'm creating your robot, unfortunately i haven't your same motor driver so I've tried with this model: 

2Pcs L9110S H Bridge Stepper Motor Dual DC Driver Controller Module  The wbe interface works and the motor too, but both motors sping with no sense, not according with the direction given by the web interface. Do you thing the driver is wrong or can it works with this project too? I'm using same wiring diagram 

  Are you sure? yes | no

Max.K wrote 10/25/2017 at 16:06 point

Your motor driver should be compatible. 

The Raspberry generates a voltage between 0 and 3.3V on the output pins that are connected to the driver. Try using a multimeter to check if the voltages change when you move the joysticks. 

Maybe it's just a simple problem with the wiring of these pins.

  Are you sure? yes | no

guiducci.alessandro wrote 10/25/2017 at 17:35 point

with multimeter  i read on both motor tension within a range of + 3,26 and -3,26V, depending on the joystick directions, but the problem is that when I move the joystick:

- forward -> M1 spin forward, M2 not move

- right -> M1 and M2 move forward

- left -> M1 spin backward 

- backward -> M1 spin backward , M2 spin forward

How can I debug this kind of problem, there is some mapping on the SW to set?

  Are you sure? yes | no

Max.K wrote 10/25/2017 at 19:34 point

As you're describing it, the behavior of motor 1 is correct. M2 would need to be reversed and is also missing one direction of movement. This still looks like a wire that is attached to the wrong pin. You can configure the directions via software but that would be the same as reversing the motor cables.

Try measuring the voltage between each pin and ground instead of between two output pins (the negative voltage would suggest that you did that previously).

You can also test the motor driver without the raspberry using a 5V or 3V source on the input pins to see if the motors are turning.

  Are you sure? yes | no

juandelacosta wrote 09/11/2017 at 01:47 point

can we use 40mm zero camera cable?

  Are you sure? yes | no

Max.K wrote 09/11/2017 at 07:58 point

It's difficult to tell even from looking at the cad model. I don't have such a cable but it could work. Maybe it's a bit too short, you have to try it.

  Are you sure? yes | no

juandelacosta wrote 11/27/2017 at 12:04 point

ok got bot up and running 40mm cable works bends are almost too tight.

  Are you sure? yes | no

DavidD wrote 08/06/2017 at 18:11 point

First, thank you for this tutorial. It will allow some intresting project in the future. 

Then, i have a problem with app.js when I try to connect to "My IP":3000 I get the message :


that was corrected by adding :

cd Desktop/touchUI

sudo npm init -Y 

sudo npm install express

to Madsen's comment. 

Here again thank you this code was adapted in short time to one of my previous project 

  Are you sure? yes | no

Dan DWRobotics wrote 07/29/2017 at 21:26 point

Such a well thought out and well designed project. It all seems to work so perfectly, combining multiple skills to make it work.

  Are you sure? yes | no

zer0flag wrote 07/18/2017 at 12:00 point

Is there any config file? Forward and backwards works fine, but my steering works the wrong way.

  Are you sure? yes | no

Max.K wrote 07/18/2017 at 15:21 point

You can either change the wiring or look for the files touchUI or app.js in the folder TouchUI on the desktop. Its probably the easiest thing to just swap the cables for the left and right motor.

  Are you sure? yes | no

zer0flag wrote 07/18/2017 at 15:47 point

I found the touch.html-File and added

x = 0 - x; 

to the function tankDrive(x, y). Now the bot works fine!

  Are you sure? yes | no

5haun wrote 07/08/2017 at 04:48 point

Works very well-- Even over the internet. Impressed by how responsive the websocket/mjpg combo is and how intuitive the browser based controls are. I used two batteries, added a charging port, and it still fits just fine. Thanks for the guide!

  Are you sure? yes | no

Max.K wrote 07/08/2017 at 07:38 point

That's great to hear! If you want you could upload a picture of your robot to Thingiverse:

  Are you sure? yes | no

MP wrote 07/01/2017 at 00:05 point

Hey! I finally made it! Works pretty well and the video stream is pretty responsive.

One thing though... it's quite difficult to control, especially because it turns so easily... One slight movement to the right/left, and it starts spinning. Is there any way to adjust the sensitivity?

  Are you sure? yes | no

Max.K wrote 07/02/2017 at 07:23 point

Well done so far! The motors are not really made for slow movement. I tried to adjust the dead-zone so that the robot starts driving immediately instead of just beeping the motors. You can reverse this by removing these lines of code from Touch.html:

if(leftMot > 0) leftMot += 90;
if(leftMot < 0) leftMot -= 90;
if(rightMot > 0) rightMot += 90;
if(rightMot < 0) rightMot -= 90;

A charging port would be nice and will definitely be included if I'm going to make a second version. Right now you can easily modify the original CAD files (link is on this page) to include any charging port you need.

  Are you sure? yes | no

MP wrote 07/28/2017 at 18:05 point

Thanks. I tried that, but removing the dead zone does not completely solve the quick spin issue. I have to figure out a way to indicate that if there is not enough forward speed, turning has to be slower than the indicated.

By the way. I tried adding a microsub port on the back, but soldering it was a pain as it kept desoldering itself. I ended up creating a dock, just like a roomba. It is much easier to charge it this way, and it is possible to leave it powered on and ready to move.

  Are you sure? yes | no

MP wrote 06/30/2017 at 12:25 point

By the way, it would be convenient to have an opening in the back for a female microusb port, in order to charge the robot without having to open the cover.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates