Community project

Untitled Project

КИТЫ ИНВЕСТИЦИЙ

Published August 8, 2026 · Updated August 11, 2026

ESP3211 components6 assembly steps
Remix this project
Photo of Untitled ProjectGenerated with AI

This guide builds an autonomous edge-detecting robot vacuum powered by an ESP32 microcontroller. The robot uses dual DC motors for mobility, IR line tracking sensors to detect table edges, and a fan motor controlled by a logic-level MOSFET for suction. The L298N motor driver coordinates the drive motors while the IRLZ44N handles high-current fan switching with protection from a Schottky flyback diode.

Followers will receive a complete wiring diagram showing motor controller connections, sensor pinouts, and power distribution, a full parts list with recommended suppliers, the Arduino firmware for autonomous edge avoidance behavior, and step-by-step assembly instructions for chassis construction, sensor calibration, and safety testing.

Wiring diagram

Interactive · read-only
Wiring diagram for Untitled Project

Pan and zoom to explore the wiring. Remix the project to edit it in your own workspace.

Parts list

Bill of materials
ComponentQtyNotes
DFRobot MDV 2x2A DC Motor Controller (L298N)L298N motor driver module1L298N dual H-bridge motor driver carrier. 2A continuous per channel, 5-46V motor supply, ~1.8V dropout (BJT-based, hot at high currents). Drives 2 brushed DC motors or 1 bipolar stepper. Pair with PWM on EN pins for speed control.
DC Motor3-6 V TT gearmotor1DC motor (requires motor driver like L298N)
DC Motor3-6 V TT gearmotor1DC motor (requires motor driver like L298N)
DC Motor5 V blower1DC motor (requires motor driver like L298N)
IRLZ44N Logic-Level N-Channel MOSFETIRLZ44N1Logic-level N-channel MOSFET commonly used as a low-side switch for DC loads from 3.3V or 5V microcontroller GPIO. Use a gate resistor, a gate pulldown, and a flyback diode for inductive loads.
TCRT5000 IR Line Tracking Sensor ModuleTCRT50001Single-channel infrared reflective sensor module built around the Vishay TCRT5000 IR emitter/phototransistor pair. An onboard LM393 comparator with a sensitivity trim-pot drives a thresholded digital output (DO) for line-detection or obstacle-avoidance, while a separate analog pin (AO) exposes the raw reflected-IR reading. Runs on 3.3V-5V, senses reflective surfaces roughly 1-25mm away, and is the standard low-cost sensor on line-following and obstacle-avoiding robot kits. Sold as a generic 4-pin (VCC/GND/DO/AO) breakout under many brand names (HiLetgo, ACEIRMC, OSOYOO, etc.) rather than by a single official manufacturer.
TCRT5000 IR Line Tracking Sensor ModuleTCRT50001Single-channel infrared reflective sensor module built around the Vishay TCRT5000 IR emitter/phototransistor pair. An onboard LM393 comparator with a sensitivity trim-pot drives a thresholded digital output (DO) for line-detection or obstacle-avoidance, while a separate analog pin (AO) exposes the raw reflected-IR reading. Runs on 3.3V-5V, senses reflective surfaces roughly 1-25mm away, and is the standard low-cost sensor on line-following and obstacle-avoiding robot kits. Sold as a generic 4-pin (VCC/GND/DO/AO) breakout under many brand names (HiLetgo, ACEIRMC, OSOYOO, etc.) rather than by a single official manufacturer.
USB-C 5V Adapter5 V, 2 A1USB-C wall adapter delivering regulated 5 V to the board's USB or VBUS rail. Default wired power source for desktop / stationary projects.
1N5819 Schottky flyback diode1N58191Suppresses inductive voltage spike from the blower fan when switched off.
100 ohm gate resistor100 Ω1Series resistor between ESP32 fan-control GPIO and MOSFET gate.
10 kilohm gate pulldown resistor10 kΩ1Keeps fan MOSFET off while the ESP32 starts.

Assembly

6 steps
  1. Соберите шасси и пылесборник

    Закрепите два TT‑редукторных мотора с колёсами по бокам лёгкого основания. Спереди поставьте скользящую опору. Перед центробежным вентилятором сделайте небольшой закрытый контейнер‑пылесборник с входной щелью и фильтром: крыльчатка должна тянуть воздух из контейнера и выбрасывать его наружу, а не быть открытой рядом с пальцами.

    • Tip: Расположите входную щель и мягкую щётку на передней кромке корпуса.
    • Tip: Оставьте фильтр доступным для очистки.
    • Не запускайте вентилятор без защитного кожуха и фильтра.
    • Этот компактный вариант собирает крошки и пыль, но не рассчитан на жидкость или тяжёлый мусор.
  2. Установите датчики края

    Закрепите edge_left и edge_right на нижней стороне передней части корпуса, направив их строго вниз. Между датчиком и столом оставьте примерно 4–8 мм; датчики должны быть разнесены к левому и правому углу.

    • Tip: Провода датчиков закрепите так, чтобы они не касались колёс.
    • Tip: На тёмном или глянцевом столе чувствительность придётся подстроить позже.
    • Перед первым движением обязательно проверьте реакцию датчиков, держа робот над поверхностью.
  3. Подключите моторный драйвер и ходовые моторы

    Подайте +5 V на VS и 5V драйвера driver, а общий минус на GND. Соедините OUT1/OUT2 с двумя выводами left_motor, OUT3/OUT4 — с двумя выводами right_motor. К ESP32 подключите IN1→GPIO4, IN2→GPIO13, IN3→GPIO14, IN4→GPIO16, ENA→GPIO17, ENB→GPIO18.

    • Tip: Если колесо вращается в обратную сторону, поменяйте местами только два провода соответствующего мотора на OUT‑выходах.
    • Tip: Общий GND обязателен для ESP32, драйвера, датчиков и питания.
    • L298N заметно греется и имеет падение напряжения; используйте только малые 3–6 V моторы и не закрывайте радиатор.
    • Не берите питание моторов с контакта 3V3 ESP32.
  4. Соберите силовой ключ вентилятора

    Подключите + вентилятора blower к шине +5 V, его минус — к DRAIN ключа fan_mosfet. SOURCE ключа соедините с общим GND. У диода flyback_diode катод K подключите к +5 V, анод A — к DRAIN. От GPIO25 проведите сигнал через gate_resistor 100 Ω к GATE. Резистор gate_pulldown 10 kΩ соедините между GATE и GND.

    • Tip: Полоса на корпусе 1N5819 обозначает катод — он должен смотреть к +5 V.
    • Tip: Расположите диод близко к проводам вентилятора.
    • Не перепутайте DRAIN и SOURCE MOSFET; это приведёт к неправильной работе или перегреву.
    • Отключайте питание перед любыми изменениями проводки.
  5. Подключите датчики и питание

    Для каждого TCRT5000: VCC подключите к 3V3 ESP32, GND — к общему GND; DO левого датчика подключите к GPIO32, правого — к GPIO33. Питание usb_supply +5 V подключите к общей шине +5 V, GND — к общей земле. ESP32 также питается от этой регулируемой 5‑вольтовой USB линии через свой USB-разъём или 5V/VIN, но не подключайте одновременно два разных USB‑источника.

    • Tip: Нужен стабильный адаптер минимум 5 V / 2 A; короткие толстые провода питания уменьшают просадки при старте моторов.
    • Tip: Сначала включайте робот, удерживая его поднятым над столом.
    • Все земли должны быть соединены вместе.
    • Не подавайте более 5 V на шину питания.
  6. Настройте безопасное обнаружение края

    После прошивки через кнопку Deploy в Schematik удерживайте робота над поверхностью. Поверните подстроечный винт каждого TCRT5000 так, чтобы при наличии столешницы под датчиком DO был LOW, а при свисании за край — HIGH. Затем поставьте робота далеко от края и проверьте, что он едет вперёд, отступает и поворачивает при поднесении одного датчика к краю.

    • Tip: Если робот поворачивает не туда, поменяйте местами провода одного мотора на выходе драйвера.
    • Tip: Начните тест на большой пустой поверхности и держите руку рядом, чтобы остановить робот.
    • Не тестируйте возле воды, стекла, людей, клавиатуры или края выше безопасной высоты.
    • Никогда не оставляйте настольный робот без присмотра.

Pin assignments

Board wiring reference
PinConnectionType
5Vusb_supply +5Vpower
GNDusb_supply GNDground
5Vdriver VSpower
5Vdriver 5Vpower
GNDdriver GNDground
GPIO 4driver IN1digital
GPIO 13driver IN2digital
GPIO 14driver IN3digital
GPIO 16driver IN4digital
GPIO 17driver ENApwm
GPIO 18driver ENBpwm
EXTdriver OUT1DC Motor VCCoutput
EXTdriver OUT2DC Motor GNDoutput
EXTdriver OUT3DC Motor VCCoutput
EXTdriver OUT4DC Motor GNDoutput
5Vblower VCCpower
EXTblower GNDIRLZ44N Logic-Level N-Channel MOSFET DRAINground
GNDfan_mosfet SOURCEground
GPIO 25gate_resistor Adata
EXTgate_resistor BIRLZ44N Logic-Level N-Channel MOSFET GATEdata
EXTgate_pulldown AIRLZ44N Logic-Level N-Channel MOSFET GATEdata
GNDgate_pulldown Bground
5Vflyback_diode Kpower
EXTflyback_diode AIRLZ44N Logic-Level N-Channel MOSFET DRAINdata
3V3edge_left VCCpower
GNDedge_left GNDground
GPIO 32edge_left DOdigital
3V3edge_right VCCpower
GNDedge_right GNDground
GPIO 33edge_right DOdigital
EXTleft_motor IN1DFRobot MDV 2x2A DC Motor Controller (L298N) OUT1digital
EXTleft_motor IN2DFRobot MDV 2x2A DC Motor Controller (L298N) OUT2digital
EXTright_motor IN1DFRobot MDV 2x2A DC Motor Controller (L298N) OUT3digital
EXTright_motor IN2DFRobot MDV 2x2A DC Motor Controller (L298N) OUT4digital
5Vblower IN1power
EXTblower IN2IRLZ44N Logic-Level N-Channel MOSFET DRAINdigital

Firmware

ESP32
main.cppDeploy to device
#include <Arduino.h>


// Hoisted type definitions
enum MotionState { CRUISE, BACK_UP, TURN_LEFT, TURN_RIGHT };


// Forward declarations
void setMotor(int in1, int in2, int enablePin, int speed, bool forward);
void stopMotors();
void driveForward(uint8_t speed);
void driveBackward(uint8_t speed);
void turnInPlace(bool right);
bool edgeDetected();
void beginAvoidance(unsigned long now);

const int LEFT_IN1 = 4;
const int LEFT_IN2 = 13;
const int RIGHT_IN1 = 14;
const int RIGHT_IN2 = 16;
const int LEFT_EN = 17;
const int RIGHT_EN = 18;
const int FAN_GATE = 25;
const int EDGE_LEFT = 32;
const int EDGE_RIGHT = 33;

const uint8_t DRIVE_SPEED = 155;
const uint8_t TURN_SPEED = 175;
const uint8_t FAN_SPEED = 220;
const unsigned long BACKUP_MS = 420;
const unsigned long TURN_MS = 520;
const unsigned long CRUISE_CHANGE_MS = 2600;


MotionState state = CRUISE;
unsigned long stateStarted = 0;
unsigned long cruiseStarted = 0;
bool turnRightNext = true;

void setMotor(int in1, int in2, int enablePin, int speed, bool forward) {
  digitalWrite(in1, forward ? HIGH : LOW);
  digitalWrite(in2, forward ? LOW : HIGH);
  analogWrite(enablePin, speed);
}

void stopMotors() {
  analogWrite(LEFT_EN, 0);
  analogWrite(RIGHT_EN, 0);
  digitalWrite(LEFT_IN1, LOW);
  digitalWrite(LEFT_IN2, LOW);
  digitalWrite(RIGHT_IN1, LOW);
  digitalWrite(RIGHT_IN2, LOW);
}

void driveForward(uint8_t speed) {
  setMotor(LEFT_IN1, LEFT_IN2, LEFT_EN, speed, true);
  setMotor(RIGHT_IN1, RIGHT_IN2, RIGHT_EN, speed, true);
}

void driveBackward(uint8_t speed) {
  setMotor(LEFT_IN1, LEFT_IN2, LEFT_EN, speed, false);
  setMotor(RIGHT_IN1, RIGHT_IN2, RIGHT_EN, speed, false);
}

void turnInPlace(bool right) {
  setMotor(LEFT_IN1, LEFT_IN2, LEFT_EN, TURN_SPEED, right);
  setMotor(RIGHT_IN1, RIGHT_IN2, RIGHT_EN, TURN_SPEED, !right);
}

bool edgeDetected() {
  // Adjust each sensor trimmer so DO is HIGH only when the sensor sees no tabletop.
  return digitalRead(EDGE_LEFT) == HIGH || digitalRead(EDGE_RIGHT) == HIGH;
}

void beginAvoidance(unsigned long now) {
  state = BACK_UP;
  stateStarted = now;
  driveBackward(DRIVE_SPEED);
}

void setup() {
  pinMode(LEFT_IN1, OUTPUT);
  pinMode(LEFT_IN2, OUTPUT);
  pinMode(RIGHT_IN1, OUTPUT);
  pinMode(RIGHT_IN2, OUTPUT);
  pinMode(LEFT_EN, OUTPUT);
  pinMode(RIGHT_EN, OUTPUT);
  pinMode(FAN_GATE, OUTPUT);
  pinMode(EDGE_LEFT, INPUT);
  pinMode(EDGE_RIGHT, INPUT);
  stopMotors();
  analogWrite(FAN_GATE, FAN_SPEED);
  stateStarted = millis();
  cruiseStarted = stateStarted;
}

void loop() {
  const unsigned long now = millis();
  if (state == CRUISE) {
    if (edgeDetected()) {
      beginAvoidance(now);
    } else if (now - cruiseStarted >= CRUISE_CHANGE_MS) {
      state = turnRightNext ? TURN_RIGHT : TURN_LEFT;
      turnRightNext = !turnRightNext;
      stateStarted = now;
      turnInPlace(state == TURN_RIGHT);
    } else {
      driveForward(DRIVE_SPEED);
    }
    return;
  }
  if (state == BACK_UP) {
    if (now - stateStarted >= BACKUP_MS) {
      state = turnRightNext ? TURN_RIGHT : TURN_LEFT;
      turnRightNext = !turnRightNext;
      stateStarted = now;
      turnInPlace(state == TURN_RIGHT);
    }
    return;
  }
  if (now - stateStarted >= TURN_MS) {
    state = CRUISE;
    cruiseStarted = now;
    driveForward(DRIVE_SPEED);
  }
}

“Deploy to device” opens this project in Schematik, where you can flash it to your board over USB.

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik