Community project
Untitled Project
КИТЫ ИНВЕСТИЦИЙ
Published August 8, 2026 · Updated August 11, 2026
Generated with AIThis 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
Pan and zoom to explore the wiring. Remix the project to edit it in your own workspace.
Parts list
Bill of materials| Component | Qty | Notes |
|---|---|---|
| DFRobot MDV 2x2A DC Motor Controller (L298N)L298N motor driver module | 1 | L298N 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 gearmotor | 1 | DC motor (requires motor driver like L298N) |
| DC Motor3-6 V TT gearmotor | 1 | DC motor (requires motor driver like L298N) |
| DC Motor5 V blower | 1 | DC motor (requires motor driver like L298N) |
| IRLZ44N Logic-Level N-Channel MOSFETIRLZ44N | 1 | Logic-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 ModuleTCRT5000 | 1 | Single-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 ModuleTCRT5000 | 1 | Single-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 A | 1 | USB-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 diode1N5819 | 1 | Suppresses inductive voltage spike from the blower fan when switched off. |
| 100 ohm gate resistor100 Ω | 1 | Series resistor between ESP32 fan-control GPIO and MOSFET gate. |
| 10 kilohm gate pulldown resistor10 kΩ | 1 | Keeps fan MOSFET off while the ESP32 starts. |
Assembly
6 stepsСоберите шасси и пылесборник
Закрепите два TT‑редукторных мотора с колёсами по бокам лёгкого основания. Спереди поставьте скользящую опору. Перед центробежным вентилятором сделайте небольшой закрытый контейнер‑пылесборник с входной щелью и фильтром: крыльчатка должна тянуть воздух из контейнера и выбрасывать его наружу, а не быть открытой рядом с пальцами.
- Tip: Расположите входную щель и мягкую щётку на передней кромке корпуса.
- Tip: Оставьте фильтр доступным для очистки.
- ⚠ Не запускайте вентилятор без защитного кожуха и фильтра.
- ⚠ Этот компактный вариант собирает крошки и пыль, но не рассчитан на жидкость или тяжёлый мусор.
Установите датчики края
Закрепите edge_left и edge_right на нижней стороне передней части корпуса, направив их строго вниз. Между датчиком и столом оставьте примерно 4–8 мм; датчики должны быть разнесены к левому и правому углу.
- Tip: Провода датчиков закрепите так, чтобы они не касались колёс.
- Tip: На тёмном или глянцевом столе чувствительность придётся подстроить позже.
- ⚠ Перед первым движением обязательно проверьте реакцию датчиков, держа робот над поверхностью.
Подключите моторный драйвер и ходовые моторы
Подайте +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.
Соберите силовой ключ вентилятора
Подключите + вентилятора 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; это приведёт к неправильной работе или перегреву.
- ⚠ Отключайте питание перед любыми изменениями проводки.
Подключите датчики и питание
Для каждого 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 на шину питания.
Настройте безопасное обнаружение края
После прошивки через кнопку Deploy в Schematik удерживайте робота над поверхностью. Поверните подстроечный винт каждого TCRT5000 так, чтобы при наличии столешницы под датчиком DO был LOW, а при свисании за край — HIGH. Затем поставьте робота далеко от края и проверьте, что он едет вперёд, отступает и поворачивает при поднесении одного датчика к краю.
- Tip: Если робот поворачивает не туда, поменяйте местами провода одного мотора на выходе драйвера.
- Tip: Начните тест на большой пустой поверхности и держите руку рядом, чтобы остановить робот.
- ⚠ Не тестируйте возле воды, стекла, людей, клавиатуры или края выше безопасной высоты.
- ⚠ Никогда не оставляйте настольный робот без присмотра.
Pin assignments
Board wiring reference| Pin | Connection | Type |
|---|---|---|
| 5V | usb_supply +5V | power |
| GND | usb_supply GND | ground |
| 5V | driver VS | power |
| 5V | driver 5V | power |
| GND | driver GND | ground |
| GPIO 4 | driver IN1 | digital |
| GPIO 13 | driver IN2 | digital |
| GPIO 14 | driver IN3 | digital |
| GPIO 16 | driver IN4 | digital |
| GPIO 17 | driver ENA | pwm |
| GPIO 18 | driver ENB | pwm |
| EXT | driver OUT1 → DC Motor VCC | output |
| EXT | driver OUT2 → DC Motor GND | output |
| EXT | driver OUT3 → DC Motor VCC | output |
| EXT | driver OUT4 → DC Motor GND | output |
| 5V | blower VCC | power |
| EXT | blower GND → IRLZ44N Logic-Level N-Channel MOSFET DRAIN | ground |
| GND | fan_mosfet SOURCE | ground |
| GPIO 25 | gate_resistor A | data |
| EXT | gate_resistor B → IRLZ44N Logic-Level N-Channel MOSFET GATE | data |
| EXT | gate_pulldown A → IRLZ44N Logic-Level N-Channel MOSFET GATE | data |
| GND | gate_pulldown B | ground |
| 5V | flyback_diode K | power |
| EXT | flyback_diode A → IRLZ44N Logic-Level N-Channel MOSFET DRAIN | data |
| 3V3 | edge_left VCC | power |
| GND | edge_left GND | ground |
| GPIO 32 | edge_left DO | digital |
| 3V3 | edge_right VCC | power |
| GND | edge_right GND | ground |
| GPIO 33 | edge_right DO | digital |
| EXT | left_motor IN1 → DFRobot MDV 2x2A DC Motor Controller (L298N) OUT1 | digital |
| EXT | left_motor IN2 → DFRobot MDV 2x2A DC Motor Controller (L298N) OUT2 | digital |
| EXT | right_motor IN1 → DFRobot MDV 2x2A DC Motor Controller (L298N) OUT3 | digital |
| EXT | right_motor IN2 → DFRobot MDV 2x2A DC Motor Controller (L298N) OUT4 | digital |
| 5V | blower IN1 | power |
| EXT | blower IN2 → IRLZ44N Logic-Level N-Channel MOSFET DRAIN | digital |
Firmware
ESP32#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.