← 返回全部文章

ESP32 入门:一晚上做出第一个会响应的硬件项目

从 LED、按钮到手机控制,带零基础读者跑通 ESP32 的第一条输入、代码、输出链路。

很多人学单片机,第一步就陷进了电路理论、引脚图、库文件和一大盒零件。资料看了不少,开发板还没插上电脑。

零基础的第一个晚上,目标可以小一点:让一台便宜的小电脑感知一个动作,再用代码回应这个动作。

ESP32 很适合做这个练习。它是一块带 Wi-Fi 和蓝牙的微控制器开发板,能读取传感器、控制 LED 、运行一个小网页,也能在没有云服务的情况下响应现实世界。它当然不能替代笔记本电脑,但足够帮你建立第一条完整链路:

输入 → 代码 → 输出

这篇文章不追求一次学完 ESP32,而是带你完成一个可修改的最小项目:先让 LED 闪烁,再加按钮,最后用手机网页控制 LED 。

先准备几样东西

第一套材料不用买得太复杂:

  • 一块 ESP32 开发板;
  • 一根 USB 数据线,注意不是只能充电的线;
  • 一块面包板和几根杜邦线;
  • 一个 LED;
  • 一个 220~330 Ω 电阻;
  • 一个轻触按键。

ESP32 开发板和入门材料

不同 ESP32 开发板的 USB 接口、引脚排列和板载 LED 位置可能不同。这套接线示例按经典 ESP32-DevKitC V4 / ESP32-WROOM 风格开发板来写。如果你手里的是 ESP32-C3 、 C6 、 S3 或其他变体,先看板子上的引脚标识,不要照搬 GPIO 编号。

第一晚先别买一整套传感器大礼包。零件越多,选择越多,项目越容易停在“准备开始”。温度传感器也可以放到下一个项目,因为不同传感器的电压要求、引脚和库都不一样。

只记住四个词

Sketch:Arduino 程序,也就是你写给开发板的代码。

GPIO:开发板上的可控引脚,可以读取或输出电信号。

GND:地线,可以理解为电路的公共回路,也常被叫作“负极”。

串口监视器:Arduino IDE 里用来查看开发板输出信息的小窗口。示例里会用到 115200 这个通信速度。

不用背定义。接线、上传和排错各做过一次,这些词自然就熟了。

给自己安排 90~120 分钟

可以按这个顺序推进:

  1. 前 30 分钟:安装工具,让外接 LED 闪烁;
  2. 接下来 25 分钟:加一个按钮,让按钮控制 LED;
  3. 再用 35 分钟:让 ESP32 连上 Wi-Fi,用手机网页控制 LED;
  4. 最后留 20~30 分钟:只加一个你真正想保留的小功能。

每一步都要先验证,再进入下一步。硬件项目最怕一次接太多东西,出了问题却不知道是哪一环出了错。

第一步:让 LED 闪起来

先安装 Arduino IDE,然后添加 ESP32 的开发板支持。

  1. 打开 Arduino IDE 的 Preferences,在 Additional Boards Manager URLs 中加入官方稳定地址:

    https://espressif.github.io/arduino-esp32/package_esp32_index.json

  2. 打开 Tools → Board → Boards Manager

  3. 搜索 ESP32,安装 Espressif Systems 发布的开发板包。

  4. 用 USB 数据线连接 ESP32 。

  5. Tools → Board 中选择你板子上标注的型号。无法确认型号的通用 DevKit,可以先尝试 ESP32 Dev Module

  6. Tools → Port 中选择插入开发板后出现的端口。 Windows 通常类似 COM3,macOS 通常以 /dev/cu.usb 开头。

这些步骤只是准备环境。先不要急着点 Upload,先把 LED 电路接好。

LED 怎么接

按经典 DevKitC V4 示例:

ESP32 GPIO 4 → 220~330 Ω 电阻 → LED 长脚(正极)
LED 短脚(负极) → ESP32 GND

电阻不能省,它负责限制通过 LED 的电流。电阻本身没有方向,但必须和 LED 串联,不能放到面包板的另一排做并联。

LED 通常是长脚接正极,短脚接地。塑料外壳带平边的一侧,通常也对应短脚一侧。

新建 Arduino 项目,删除默认代码,粘贴下面的程序:

const int ledPin = 4;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
}

点击 Upload 。上传时如果一直停在 Connecting...,可以在开始连接时按住开发板的 BOOT 按钮,连接成功后松开。仍然失败的话,先检查开发板型号、端口和 USB 线,不要马上重写代码。

LED 闪起来,说明整条链路已经打通了:电脑能看到开发板,USB 驱动和数据线正常,开发板型号和端口选对了,代码也确实变成了物理动作。

delay(500) 改成 delay(100),再次上传。你已经完成了一次编辑、编译、写入和观察结果的循环。

如果 LED 不亮,优先检查四件事:LED 方向、电阻连接、选中的端口,以及 USB 线是否支持数据传输。

第二步:加一个按钮

把按钮跨在面包板中间的沟槽上。按钮的一侧接 GPIO 18,另一侧接 GND:

按钮一侧 → ESP32 GPIO 18
按钮另一侧 → ESP32 GND

按钮的两组引脚在内部分别相连,所以如果没有跨过面包板中间的沟槽,它可能始终无法正常切换。

这次程序让 LED 只在按住按钮时点亮:

const int ledPin = 4;
const int buttonPin = 18;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  digitalWrite(ledPin, LOW);
}

void loop() {
  bool buttonIsPressed = digitalRead(buttonPin) == LOW;
  digitalWrite(ledPin, buttonIsPressed ? HIGH : LOW);
}

这里的 INPUT_PULLUP 会打开开发板内部的上拉电阻。按钮松开时,GPIO 读到 HIGH;按钮按下后,GPIO 通过按钮接到 GND,读到 LOW 。所以代码里是“LOW 代表按下”。这和直觉相反,但可以少接一个外部电阻。

这段程序可以抽象成一个很有用的硬件模型:

循环执行:
  读取一个引脚
  判断它代表什么
  写入另一个引脚

动作传感器、继电器、马达、显示屏和蜂鸣器,都可以套进这个模型。输入和输出会变,真正需要你设计的是中间那段判断逻辑。

先别换项目。你可以在现有程序上做一个小改动:按下按钮后让 LED 闪几次,把按钮状态打印到串口监视器,或者把“按下亮灯”改成“按下熄灭”。

第三步:用手机控制 LED

ESP32 的方便之处在于,它可以连接 Wi-Fi 并运行一个很小的网页服务器。这样手机就能变成这个项目的操作界面。

下面的程序会在本地网络上提供两个按钮,用来打开和关闭 LED:


#include <WiFi.h>

#include <WebServer.h>

const char* wifiName = "YOUR_WIFI_NAME";
const char* wifiPassword = "YOUR_WIFI_PASSWORD";
const int ledPin = 4;

WebServer server(80);

void showHome() {
  String page = "<h1>ESP32 desk light</h1>";
  page += "<p><a href='/on'><button>Turn on</button></a> ";
  page += "<a href='/off'><button>Turn off</button></a></p>";
  server.send(200, "text/html", page);
}

void turnOn() {
  digitalWrite(ledPin, HIGH);
  server.sendHeader("Location", "/");
  server.send(303);
}

void turnOff() {
  digitalWrite(ledPin, LOW);
  server.sendHeader("Location", "/");
  server.send(303);
}

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);

  WiFi.begin(wifiName, wifiPassword);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Open: http://");
  Serial.println(WiFi.localIP());

  server.on("/", showHome);
  server.on("/on", turnOn);
  server.on("/off", turnOff);
  server.begin();
}

void loop() {
  server.handleClient();
}

YOUR_WIFI_NAMEYOUR_WIFI_PASSWORD 换成自己的网络信息,上传后打开 Tools → Serial Monitor,选择 115200 baud 。串口窗口会打印一个本地 IP 地址,在同一个 Wi-Fi 网络里的手机浏览器打开它,就能看到控制页面。

ESP32 常见型号主要连接 2.4 GHz Wi-Fi,只有 5 GHz 的网络可能无法使用。手机和开发板需要处在同一个本地网络里。不要把真实 Wi-Fi 密码放进公开仓库、截图或聊天记录。

这个页面没有登录功能。知道地址的同一网络设备都可能控制 LED,所以只在自己信任的家庭网络中测试,不要把它直接暴露到公网。也不要把电机、继电器或其他真实负载直接接到 GPIO 上。 GPIO 只适合输出小电流控制信号,这类负载需要独立电源和合适的驱动电路,例如 MOSFET 。

如果串口监视器一直打印点,先检查 Wi-Fi 名称和密码,再检查路由器是否提供 2.4 GHz 网络。如果 ESP32 已打印 IP,但手机打不开页面,检查手机是否连接到了访客网络或正在使用移动数据。

LED 与按钮的连接示意

AI 可以帮忙,但不能替你看电路

硬件项目很适合用 AI 做辅助。它可以把一个模糊想法拆成几步,也能根据错误信息帮你缩小排查范围。但它并不知道你手里那块板子的真实引脚,也不能替你确认一根线到底插在哪里。

给 AI 提问时,至少说明五件事:

  1. 硬件:具体板型,或者把板子上的引脚标签抄下来,再列出所有零件;
  2. 目标:用一句话说清楚设备要做什么;
  3. 当前状态:已经接了什么、什么环节正常、看到了什么错误;
  4. 限制条件:初学者、不能买新零件、只允许本地网络等;
  5. 希望的回答形式:接线表、一步一步操作、最小代码修改,还是概念解释。

可以直接套用这个项目提示词:

我是第一次做 ESP32 项目的初学者。

开发板:具体型号,或“未知;我能读到的标签是:……”
零件:列出手头所有零件
目标:用一句话描述想做什么
已经正常的部分:或“目前还没有”
限制:时间、不能买新零件、只用本地网络等

请先列出你的假设,再给我接线表和最小测试顺序。
一次只给一个下一步,说明成功后应该看到什么,等我反馈后再修改设计。
请使用通俗语言,并给出适合初学者的电压安全提醒。

遇到故障时,用这个版本比一句“帮我修代码”更有效:

请作为 ESP32 初学者的排错伙伴。
开发板:具体型号
接线:每条连接单独写一行
代码:粘贴最小相关程序
现象或完整错误:我实际看到的内容

请按可能性列出三个原因,只给我下一项诊断测试,
并说明什么结果能确认或排除它。
先不要重写整个项目。
检查引脚名称和电压假设;无法确认的地方请明确说出来。

每次只改一个地方,把真实结果反馈给 AI,再做下一步。建议逐项核对引脚、电压、库和接线。 AI 可能给出语气很确定但实际错误的答案,实物测试才是最后的判断依据。密码不要粘贴进提示词、截图或代码仓库。

最后只加一个小功能

如果前面的三步都跑通了,最后 20~30 分钟只选一个小升级:

  • 做一个手机控制的桌面状态灯;
  • 按下按钮后,在本地网页记录时间;
  • 接入温度显示;
  • 让动作触发一个提示灯;
  • 按键后让状态灯切换颜色或闪烁方式。

如果你无法用一句话描述项目,它就超出今晚的范围了。

先别碰这些内容:FreeRTOS 内部机制、自制 PCB 、电池管理、深度睡眠、蓝牙配网和一堆传感器库。它们都值得学,但不适合塞进第一个晚上。

这次练习真正留下来的能力,是把陌生硬件拆成一条可以测试的链路:

  1. 能不能让一个输出发生变化?
  2. 能不能读到一个输入?
  3. 能不能让设备连接到另一个设备?
  4. 能不能把它变成一个有用的小行为?

ESP32 只是练习对象。掌握这条链路后,Arduino 、 RP2040 、 STM32 和其他业余电子开发板都会更容易上手。引脚和工具会变,排查方法基本不变。

先从一个 LED 开始。一个晚上结束时,让它对你的动作做出回应,就够了。

来源:https://x.com/ardchain/status/2087213058800099724