Robot Lab ESP32-CAM · Motors · MQTT · Node-RED
Module 0 · Start here

Build a WiFi camera robot, then drive it with MQTT and Node-RED

A step-by-step workshop for the ESP32 Camera 4WD Robot Car Kit. Every lab has code you can copy with one click. Work through the modules in order; each one builds on the last.

Your team settings

Fill these in once. Every code block on this site updates with your values, so the code you copy is ready to upload. Your instructor will give you the team ID, WiFi and broker address.

Saved in this browser only.

What's in the kit

All parts of the ESP32 Camera 4WD Robot Car Kit laid out
Kit contents (from the kit manual)
PartQtyWhat it does
ESP32-CAM board + USB adapter1The brain: WiFi, Bluetooth and a camera
L298N motor driver1Lets the small ESP32 signals switch big motor currents
TT DC gear motors + wheels4Move the robot (wired as a left pair and a right pair)
External WiFi antenna1Longer WiFi range
18650 Li-ion batteries3About 11.1–12.6 V for the motors and board (often bought separately)
USB cable1Uploads code from your PC
Safety

18650 batteries store a lot of energy. Insert them the right way round (check + and −), never short the terminals, switch the robot off when you are not using it, and only charge them in a proper 18650 charger with someone watching.

Watch the robot in action

Have the kit folder on your computer? Open Tutorial Video › Demo Video › Demo Video.mp4 here to play it on this page.

How to use this site

Copy

The yellow Copy button copies a whole code block. Paste it into a new Arduino sketch with Ctrl+V.

Download

Download gives you a .zip with a ready-made sketch folder. Unzip it and open the .ino in Arduino IDE.

Tick it off

Press Mark done when a lab works. Your progress shows in the course map on the left.

Module 1

Set up your PC

You need three things before you can upload code: the Arduino IDE, the ESP32 board package, and the CH340 USB driver. Do this once per computer.

STEP A

Install Arduino IDE 2

≈ 10 min
  1. Go to arduino.cc/en/software and download Arduino IDE 2.x for your system (Windows, macOS or Linux).

  2. Run the installer and accept the defaults. If Windows asks to install USB drivers, click Install.

  3. Open Arduino IDE. You should see an empty sketch with setup() and loop().

Tip

Already have an old Arduino IDE 1.x? The kit manual recommends uninstalling it and installing the latest version.

STEP B

Add ESP32 boards

≈ 10 min
  1. Click the Boards Manager icon on the left side (or Tools › Board › Boards Manager…).

  2. Type esp32 in the search box. Find esp32 by Espressif Systems.

  3. Pick version 3.1.0 (the version the kit was tested with; newer 3.x versions also work with this site's code) and click INSTALL. It downloads a lot, so give it a few minutes.

  4. Wait for "Successfully installed platform esp32" in the Output panel.

esp32 doesn't show up in the search?

Open File › Preferences, paste this URL into Additional boards manager URLs, click OK, then search again.

STEP C

Install the CH340 USB driver

≈ 5 min

The USB adapter under the ESP32-CAM uses a CH340 chip to turn USB into serial. Windows needs a driver for it, otherwise no COM port appears.

  1. Download CH341SER from the chip maker's site: wch-ic.com › CH341SER (Windows). Mac and Linux usually work without a driver.

  2. Plug the ESP32-CAM adapter into your PC with the USB cable, run the installer and click INSTALL. You should see "Driver install success!"

  3. Open Device Manager (search for it in the Start menu) › Ports (COM & LPT). You should see USB-SERIAL CH340 (COMx). Remember the number.

No port?
  • Try a different USB cable. Many cables only carry power, not data.
  • Try another USB socket or another computer.
  • Uninstall the driver, restart the PC, and install again.
STEP D

Your upload checklist

use every time
USB cable plugged into the ESP32-CAM adapter on the robot
Plug the USB cable into the adapter board under the ESP32-CAM.
SettingChoose
Tools › Boardesp32 › AI Thinker ESP32-CAM
Tools › PortThe COMx you saw in Device Manager
Serial Monitor speed115200 baud
UploadClick the round → button and wait for "Done uploading"
Upload fails?
  • "Failed to connect… wrong boot mode": hold the IO0 button on the adapter, press and release RST, release IO0, then click Upload again. Press RST after "Done uploading".
  • Brownout / keeps resetting: your PC's USB port can't supply enough power. Switch the robot's battery on while uploading (wheels off the table!).
  • Port is greyed out: close the Serial Monitor in any other window, then try again.
Module 2

ESP32-CAM basics

Get to know the board before it drives anything. You'll print messages, blink LEDs, scan for WiFi and stream live video.

ESP32-CAM pinout showing GPIO 4, 2, 14, 15, 13, 12, 0, 16, 1, 3 and power pins
ESP32-CAM pins. The robot uses IO12, IO13, IO14, IO15 for the motors.

Board tour

ChipESP32 (dual core, up to 240 MHz), 4 MB PSRAM
WirelessWiFi 802.11 b/g/n + Bluetooth 4.2 / BLE
CameraOV3660 on this kit (3 MP)
GPIO 4White flash LED (very bright)
GPIO 33Small red LED, on when LOW
GPIO 12–15Free pins → motor driver
RST buttonRestarts your program
LAB 1

Hello ESP32-CAM

≈ 10 min

Goal: upload your first sketch and read messages from the board in the Serial Monitor.

  1. In Arduino IDE choose File › New Sketch, delete everything, and paste the code below.

  2. Check Board = AI Thinker ESP32-CAM and the right Port, then click Upload.

  3. Open Tools › Serial Monitor and set the speed to 115200 baud. Press RST on the board if the screen is empty.

You should see

"Hello from my ESP32-CAM!" followed by the chip model, CPU speed, PSRAM size (about 4096 KB) and MAC address every second.

Try this

Change delay(1000) to delay(250). What happens? Write your own name into the first message.

LAB 2

Blink the red LED

≈ 10 min

Goal: control an output pin with digitalWrite(). This LED is "active LOW", which surprises everyone the first time.

You should see

The tiny red LED on the back of the ESP32-CAM blinks twice per second.

Try this

Make it blink an SOS: three short, three long, three short.

LAB 3

Fade the flash LED with PWM

≈ 15 min

Goal: learn PWM, the same trick we'll use later to control motor speed.

PWM switches a pin on and off thousands of times per second. The duty (0–255) is how much of each cycle the pin is ON. 0 = always off, 128 = half the time, 255 = always on. The LED (or motor) only "feels" the average.

Eyes

The flash LED is extremely bright at full power. Keep MAX_BRIGHTNESS low and don't look straight into it.

Try this

Make the LED "breathe" faster or slower by changing delay(20).

LAB 4

WiFi scanner

≈ 10 min

Goal: first wireless lab. See every network around you and how strong it is.

You should see

A numbered list of networks every 5 seconds. Find your classroom WiFi. Is the signal better than −70 dBm?

Try this

Screw on the external antenna and compare the numbers. (Some boards need a tiny jumper resistor moved to use the antenna; ask your instructor.)

LAB 5

Live camera web server

≈ 20 min

Goal: stream live video from the robot's camera to a browser on the classroom WiFi. This uses an example that comes with the ESP32 package.

  1. Open File › Examples › ESP32 › Camera › CameraWebServer.

  2. Find the Select camera model lines (in the main tab, or in the board_config.h tab on newer versions). Switch off the model that's on and switch on AI_THINKER:

  3. Find the WiFi lines near the top of the main tab and replace them with:

  4. Upload. Open the Serial Monitor (115200) and press RST. Wait for Camera Ready! Use 'http://192.168.x.x' to connect.

  5. On a phone or laptop on the same WiFi, open that address and click Start Stream.

Notice

Here the ESP32 joins an existing WiFi network (station mode). In Module 4 the robot makes its own hotspot (access-point mode). Both are useful.

Problems?
  • "Camera init failed": the camera model is wrong, or the ribbon cable is loose. Reseat it gently.
  • "Sketch too big": Tools › Partition Scheme › Huge APP.
  • Dots forever after "WiFi connecting": check the WiFi name/password in your team settings (they are case-sensitive). ESP32 only uses 2.4 GHz WiFi.
Module 3

Motors & wiring

The ESP32 can't power a motor directly: its pins give a few milliamps at 3.3 V, and a motor wants hundreds of milliamps. The L298N driver sits in between, like a set of electronic switches.

Assembled robot labelled: ESP32 camera module, L298N motor drive module, external antenna, battery case, TT motor
The assembled robot and its main parts.
L298N pinout: OUT1, OUT2 for motor A, OUT3, OUT4 for motor B, +12V, GND, +5V, jumper, ENA, IN1 to IN4, ENB
L298N pins. Keep the 5 V jumper and the ENA/ENB caps in place.
BUILD

Wire the robot

≈ 30 min

Goal: connect the battery, the L298N, the four motors and the ESP32-CAM exactly like the kit diagram. Batteries OUT while you wire.

Kit wiring diagram: battery through switch to L298N 12V and GND; motors M3 and M4 to OUT1/OUT2, M1 and M2 to OUT3/OUT4; ESP32-CAM adapter 5V, GND, IO12, IO13, IO15, IO14 to L298N 5V, GND, IN4, IN3, IN2, IN1
Kit wiring diagram. Two motors share each L298N output: one pair per side.
From (ESP32-CAM adapter)Wire in diagramTo (L298N)Job
5Vred5VPowers the ESP32-CAM from the L298N's regulator
GNDblackGNDShared ground (must be connected!)
IO14orangeIN1Motor A (OUT1/OUT2) direction
IO15blueIN2Motor A (OUT1/OUT2) direction
IO13tanIN3Motor B (OUT3/OUT4) direction
IO12yellowIN4Motor B (OUT3/OUT4) direction
Battery +red, via switch12VMotor power (3 × 18650 ≈ 11.1–12.6 V)
Battery −blackGNDBattery ground
Quick test

The kit comes with its firmware already loaded. Insert the batteries, lift the robot, switch on and press RST: the motors briefly run. That tells you the motor wiring is alive.

How the L298N makes a motor turn

Each motor channel has two inputs. Make one input "on" and the other "off" and the motor spins one way; swap them and it spins the other way; both off and it stops. In this kit the ENA/ENB jumpers stay on (channels always enabled), and the code sends PWM to the IN pins to set the speed. So a "1" in the table below really means "PWM at the current speed".

Direction explorer

Click a direction to see which pins are driven and how each side's wheels turn.

MoveIO13
IN3
IO12
IN4
IO14
IN1
IO15
IN2
Forward0speed0speed
Backwardspeed0speed0
Turn leftspeed00speed
Turn right0speedspeed0
Stop0000

FRONT (camera) ▲ ▲ ▲ ▲ LEFT side ← → RIGHT side FORWARD
LAB 6

Motor test

≈ 15 min

Goal: check that every motor turns the right way. This replaces the kit firmware; you can re-upload it later from Module 4.

  1. Put the robot on a box or cup so the wheels hang in the air.

  2. Upload the sketch. Switch the battery on. After 2 seconds it runs forward, backward, left, right, once.

  3. Watch each wheel. Press RST to repeat.

What you seeFix
One wheel turns backwards on "Forward"Swap that motor's two wires in its OUT terminal.
A whole side turns backwardsSwap the two wires of that side's OUT terminal (or swap IN1↔IN2 / IN3↔IN4).
"Left" turns rightSwap the pin numbers of LEFT_* and RIGHT_* in the code.
Motors only buzzRaise speed (try 200) or charge the batteries.
Nothing movesBattery switch on? Shared GND wire connected? Batteries above 11.1 V?
Read the code

setMotors(l0, l1, r0, r1) writes one PWM value to each of the four L298N inputs. Every movement is just a different pattern of those four numbers, exactly like the table above.

LAB 7

Drive from your PC keyboard (USB)

≈ 15 min

Goal: your first "remote control", through the USB cable. The PC sends letters, the ESP32 turns them into movements.

  1. Upload, open the Serial Monitor at 115200, robot still on its box.

  2. Type w and press Enter. The wheels spin forward until you send x.

Try this

Add a b key that blinks the flash LED, or a q key that spins on the spot for exactly one second.

Module 4

Control from your phone or PC

Now we cut the cable. The robot runs a small web server, and any phone or laptop browser becomes the remote. First with the kit's own firmware (with live camera), then with code you write yourself.

PART A

Drive with the kit firmware

≈ 15 min

Goal: use the factory program: camera stream plus drive buttons. If you uploaded Labs 1–7, re-upload the kit code first (Part B).

  1. Turn on the power switch. The small red LED on the ESP32-CAM lights up when its WiFi is ready. If not, press RST.

  2. On your phone open WiFi settings and join ESP32-CAM Robot (no password).

  3. Open a browser and go to 192.168.4.1.

  4. Hold a green button to drive; release to stop. Yellow buttons switch the flash LED.

Phone browser at 192.168.4.1 showing camera image, Forward, Left, Stop, Right, Backward and Light buttons
The kit's remote page.
Page won't load?
  • Turn mobile data off. Phones often send traffic over 4G/5G when the WiFi "has no internet".
  • Check you joined the right robot's WiFi.
  • Low batteries cause random resets. The total should be above 11.1 V.

Every button is just a URL

The remote page simply opens these addresses in the background. Try typing them into a PC browser that's connected to the robot's WiFi:

PART B

Re-upload the kit firmware (and rename its WiFi)

≈ 15 min

Goal: put the camera robot program back on the board, with a WiFi name that's unique to your team, so twenty robots called "ESP32-CAM Robot" don't confuse everyone.

Kit main codeESP32_Camera_4WD_Robot_Car_OV3660_V3: .ino + app_httpd.cpp + camera_index.h
  1. Unzip it. Keep all three files in the folder ESP32_Camera_4WD_Robot_Car_OV3660_V3.

  2. Open the .ino file. All three files appear as tabs.

  3. Change line 9 so the hotspot carries your team name:

  4. Board AI Thinker ESP32-CAM, your Port, Upload. Then repeat Part A with your new WiFi name.

LAB 8

Build your own web remote

≈ 30 min

Goal: write the web server yourself: hold-to-drive buttons for phones, WASD keys for PCs, a speed slider, and a safety stop.

  1. Upload. The Serial Monitor shows Hotspot: Robot-student01.

  2. Join that WiFi (password robot1234) and open 192.168.4.1.

  3. Phone: hold the arrows. PC: hold W A S D or the arrow keys.

AddressWhat the ESP32 does
/Sends the remote page (HTML stored in PAGE)
/cmd?c=forwardDrives. While you hold a button, the page repeats this every 200 ms
/speed?v=200Sets PWM speed 0–255
/light?on=1Flash LED on (0 = off)
Why the failsafe?

If your phone locks or walks out of range, the "stop" message may never arrive. The robot stops itself when it hears nothing for 0.6 s. Real robots always have a failsafe like this.

Try this

Add a "Spin" button that sends /cmd?c=left, or change the button colours in the <style> part of PAGE.

Module 5

MQTT: talk to robots through a broker

With a web remote, your phone talks straight to one robot. With MQTT, everything talks to a central broker, and the broker passes messages on. One dashboard can drive many robots, and many screens can watch one robot.

Node-RED your laptop · dashboard Broker Mosquitto · port 1883 Robot ESP32-CAM · PubSubClient …/cmd "forward:800" …/status {"state":"forward","speed":170,…} publish deliver publish deliver
WordMeaningIn our robot
BrokerThe post office. Receives every message and forwards it.Mosquitto on the instructor's PC
TopicThe address on the envelope, like a folder pathimakewemake/robot/student01/cmd
PublishSend a message to a topicNode-RED publishes forward:800
SubscribeAsk the broker for every message on a topicThe robot subscribes to its /cmd topic
RetainedThe broker keeps the last message for newcomers/online stays "online" or "offline"
Last WillA message the broker sends if a client vanishesRobot loses power → broker publishes "offline"
Wildcards+ = one level, # = everything belowimakewemake/robot/+/online
Instructor: set up the classroom broker (Mosquitto on Windows) · once per class
  1. Download and install Mosquitto from mosquitto.org/download (the Windows 64-bit installer). Mac: brew install mosquitto.

  2. Open C:\Program Files\mosquitto\mosquitto.conf in Notepad (as Administrator), and add these lines at the end. Without them, Mosquitto 2 only accepts connections from the same PC.

  3. Allow port 1883 through the Windows firewall:

  4. If the Mosquitto Windows service is already running, stop it in Services, then start the broker so you can see every connection:

  5. Find this PC's IP address with ipconfig (IPv4 Address, e.g. 192.168.1.100) and write it on the board. That's the broker IP students type into their settings.

  6. Watch robots join:

Network

Robots, student laptops and the broker PC must be on the same 2.4 GHz-capable WiFi, and the network must allow devices to talk to each other. Guest networks with "client isolation" block this. A cheap dedicated router works best.

WARM-UP

Publish and subscribe with MQTT Explorer

≈ 10 min

Goal: see MQTT messages with your own eyes before the robot joins in.

  1. Install MQTT Explorer from mqtt-explorer.com.

  2. New connection → Host 192.168.1.100, Port 1883, no username → Connect.

  3. In the Publish panel, topic imakewemake/robot/student01/cmd, message hello, click Publish. It appears in the topic tree on the left.

  4. Look at what other teams are publishing. That's the "many screens, one broker" idea.

LAB 9

Turn the robot into an MQTT robot

≈ 30 min

Goal: the robot joins the classroom WiFi, connects to the broker, obeys commands on its /cmd topic and reports its status.

  1. Install the library: Sketch › Include Library › Manage Libraries…, search PubSubClient, install the one by Nick O'Leary.

  2. Check your team settings at the top of the code (they come from the settings on the Start page).

  3. Upload, open the Serial Monitor. You should see WiFi OK then MQTT OK, listening on …/cmd. The red LED on the board turns on when it's connected to the broker.

Test it

In MQTT Explorer, publish forward:1000 to your /cmd topic. The robot drives for one second. Open the /status topic to see its JSON report. Command-line fans can use:

Safety built in
  • Plain forward stops by itself after 3 s (MAX_MOVE_MS).
  • If WiFi or the broker connection drops, the robot stops immediately.
rc = −2 ?

The robot can't reach the broker. Check the broker IP, that the broker PC's firewall allows port 1883, and that the robot and broker are on the same network.

Module 6

Node-RED: flows and a robot dashboard

Node-RED lets you program by wiring boxes ("nodes") together in a browser. It speaks MQTT out of the box, and with Dashboard 2.0 it can build a control panel that works on any phone or PC.

SETUP

Install and start Node-RED

≈ 15 min
  1. Install Node.js LTS from nodejs.org (accept the defaults).

  2. Open Command Prompt (Windows) or Terminal (Mac/Linux) and run these one at a time. The first line should print a version like v22.x. On Mac/Linux you may need sudo before npm.

  3. Leave that window open. Open http://127.0.0.1:1880 in your browser: that's the Node-RED editor.

  4. Install the dashboard: menu ☰ › Manage palette › Install, search for this and click install:

Import a flow

For each lab below: click Copy, then in Node-RED open ☰ › Import, paste with Ctrl+V, click Import, then the red Deploy button (top right). Or use Download and choose select a file to import.

LAB 10

Drive with inject buttons

≈ 20 min

Goal: send commands with one click and watch the robot's status come back. Your team ID and broker IP are already filled in.

  1. Import and Deploy. Under each MQTT node a small green connected label should appear.

  2. Click the square button on the left of Forward 1 s. The robot drives for a second.

  3. Open the Debug sidebar (bug icon, top right) to see the status messages arriving every 2 seconds.

  4. Click Dance!. The Square dance function sends eight timed moves in a row.

NodeWhat it does
injectA button inside the editor. Sends a fixed message, e.g. forward:1000
mqtt outPublishes whatever arrives to your robot's /cmd topic
mqtt inSubscribes to /status and /online
functionA little JavaScript. Here: a timed list of moves
debugPrints messages in the Debug sidebar
Try this

Open the Square dance node and design your own routine: a zig-zag, a figure eight, a "parking" move. Change the numbers, Deploy, click Dance!

LAB 11

Build a robot control dashboard

≈ 25 min

Goal: a real control panel with drive buttons, speed and step-time sliders, a light switch and live status, usable from any phone on the classroom WiFi.

  1. Make sure @flowfuse/node-red-dashboard is installed (Setup step 4), then import and Deploy.

  2. Each tap of an arrow moves the robot for the Step time set on the slider. STOP stops at once.

  3. On your phone (same WiFi), open http://<your-laptop-IP>:1880/dashboard. Find your laptop IP with ipconfig.

How it works

An arrow button sends forward → the add step time function turns it into forward:600 using the slider value it remembered in flow.stepMs → mqtt out publishes it. The robot's status JSON comes back through mqtt in → split status → four text widgets.

Challenges
  • Add a gauge widget that shows WiFi signal strength from msg.payload.rssi.
  • Add buttons for a second team's robot: copy the mqtt out node and change the topic.
  • Make the robot drive a square when its /online topic changes to "online".
  • Instructor challenge: one dashboard that sends the same dance to every robot in the room.

You made it

You've gone from blinking an LED to driving a robot through a broker from a dashboard. The same pattern (sensor or actuator → ESP32 → MQTT → Node-RED) runs smart greenhouses, factory monitors and home automation. Swap the motors for a sensor and you have an IoT device.

Reference

Cheat sheet & files

Files

Kit main codeFactory camera + remote firmware (3 source files)
All lab sketchesLabs 1–9, personalized with your team settings, one folder each
Node-RED flowsLab 10 basics + Lab 11 dashboard (.json)
This course as a PDFEvery module and this cheat sheet, with your team's code filled in
Kit user manualAssembly, wiring, upload steps, L298N and ESP32-CAM specs (PDF, 38 pages)
Ask your instructor for the PDF.

Pins

GPIOConnected toNotes
14L298N IN1Right motors (code: RIGHT_M0)
15L298N IN2Right motors (code: RIGHT_M1)
13L298N IN3Left motors (code: LEFT_M0)
12L298N IN4Left motors (code: LEFT_M1). Boot-sensitive pin; if the board won't boot, unplug this wire while uploading
4White flash LEDPWM brightness, keep low
33Red status LEDActive LOW
0Boot button / camera clockHold during reset for upload mode

MQTT

Arduino code you'll use again and again

CodeMeaning
pinMode(33, OUTPUT);Make pin 33 an output
digitalWrite(33, LOW);Set the pin to 0 V (turns the red LED on)
ledcAttachChannel(pin, 2000, 8, 4);PWM on pin: 2000 Hz, 8-bit (0–255), channel 4
ledcWrite(pin, 170);Set PWM duty (speed or brightness)
Serial.println("hi");Print to the Serial Monitor
WiFi.softAP(name, pass);Make a hotspot (robot is 192.168.4.1)
WiFi.begin(name, pass);Join an existing WiFi network
mqtt.publish(topic, text);Send an MQTT message
mqtt.subscribe(topic);Receive messages on a topic

Troubleshooting

ProblemMost likely fix
No COM portData USB cable, CH340 driver, different USB socket
"Failed to connect" when uploadingHold IO0, tap RST, release IO0, upload again
Board keeps restarting (brownout)Turn the battery on, charge the batteries
Robot doesn't moveBattery switch, shared GND, batteries above 11.1 V, speed above ~120
Wheel goes the wrong waySwap that motor's two wires
192.168.4.1 won't openPhone mobile data off, right robot WiFi, press RST
Stuck on "WiFi connecting…"Name/password exact? 2.4 GHz network?
MQTT rc=−2Wrong broker IP, firewall port 1883, different network
Node-RED MQTT says "disconnected"Edit the broker node, check the IP, Deploy again
Dashboard nodes show as "unknown"Install @flowfuse/node-red-dashboard, then restart Node-RED