零知派(零知开源)是一个专为电子初学者/电子兴趣爱好者设计的开源软硬件平台,在硬件上提供超高性价比STM32系列开发板、物联网控制板。取消了Bootloader程序烧录,让开发重心从“配置环境”转移到“创意实现”,极大降低了技术门槛。零知开源编程软件,内置上千个覆盖多场景的示例代码,支持项目源码一键下载,项目文章在线浏览。零知派(零知开源)平台通过软硬件协同创新,让你的创意快速转化为实物,来动手试试吧!
访问零知实验室,获取更多实战项目和教程资源吧!
www.lingzhilab.com
本教程将教你使用ESP32 搭建 Web 服务器,通过网页端颜色选择器实时、无刷新控制 RGB LED 灯的颜色,操作简单、响应流畅,手机 / 电脑浏览器均可使用。
一、软件和硬件
硬件清单
零知派 - ESP32 开发板
RGB 全彩 LED 模块(带限流电阻,3.3V/5V 通用,高电平点亮)
软件工具
零知派开发工具
硬件接线
| RGB LED 引脚 | ESP32 GPIO 引脚 |
|---|---|
| 红色引脚 | GPIO25 |
| 绿色引脚 | GPIO26 |
| 蓝色引脚 | GPIO27 |

二、完整代码与使用说明
将代码中ssid(WiFi 名称)和password(WiFi 密码)修改为你自己的 WiFi 信息,其他代码无需改动。
/**************************************************************************************
* 文件: LED.ino
* 作者:零知派(深圳市在芯间科技有限公司)
* -^^- 零知派,让电子制作变得更简单! -^^-
* 时间: 2026-5-8 15:36:27
* 说明:
* 功能:
***************************************************************************************/
#include < WiFi.h >
// 网络凭据
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";
// Web服务器
WiFiServer server(80);
// 引脚定义
const int redPin = 25;
const int greenPin = 26;
const int bluePin = 27;
// PWM 配置
const int freq = 5000;
const int resolution = 8;
// HTML 网页(修复乱码和颜色预览问题)
const char index_html[] PROGMEM = R"rawliteral(
< !DOCTYPE html >
< html >
< head >
< meta charset="UTF-8" >
< meta name="viewport" content="width=device-width, initial-scale=1" >
< link rel="icon" href="data:," >
< link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" >
< style >
body { padding: 20px; }
.container { max-width: 600px; margin: 0 auto; }
.color-preview {
width: 100%;
height: 100px;
margin: 20px 0;
border: 2px solid #ddd;
border-radius: 5px;
background-color: #000;
}
#colorPicker {
width: 100%;
height: 50px;
border: 1px solid #ddd;
border-radius: 5px;
cursor: pointer;
}
.rgb-value {
margin-top: 10px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 5px;
text-align: center;
font-family: monospace;
font-size: 16px;
}
.status {
margin-top: 10px;
padding: 10px;
text-align: center;
font-size: 14px;
border-radius: 5px;
}
.status.success {
background-color: #d4edda;
color: #155724;
}
< /style >
< /head >
< h1 >ESP32 颜色选择器< /h1 >
< input type="color" id="colorPicker" value="#000000" >
RGB: 0, 0, 0
< script >
var colorPicker = document.getElementById('colorPicker');
var previewDiv = document.getElementById('colorPreview');
var rgbDiv = document.getElementById('rgbValue');
var statusDiv = document.getElementById('status');
// 发送颜色到ESP32
function sendColor(r, g, b) {
var url = '/?r' + r + 'g' + g + 'b' + b + '&';
fetch(url)
.then(function(response) {
// 显示成功状态
statusDiv.style.display = 'block';
statusDiv.className = 'status success';
statusDiv.innerHTML = ' 颜色已更新: RGB(' + r + ', ' + g + ', ' + b + ')';
// 2秒后隐藏状态
setTimeout(function() {
statusDiv.style.display = 'none';
}, 1000);
})
.catch(function(error) {
console.log('发送失败: ' + error);
statusDiv.style.display = 'block';
statusDiv.className = 'status';
statusDiv.style.backgroundColor = '#f8d7da';
statusDiv.style.color = '#721c24';
statusDiv.innerHTML = ' 发送失败';
setTimeout(function() {
statusDiv.style.display = 'none';
}, 1000);
});
}
// 实时更新预览并发送颜色(无需点击按钮)
colorPicker.addEventListener('input', function() {
var hex = this.value;
// 更新预览
previewDiv.style.backgroundColor = hex;
// 转换HEX到RGB
var r = parseInt(hex.substr(1, 2), 16);
var g = parseInt(hex.substr(3, 2), 16);
var b = parseInt(hex.substr(5, 2), 16);
// 显示RGB值
rgbDiv.innerHTML = 'RGB: ' + r + ', ' + g + ', ' + b;
// 自动发送颜色到ESP32
sendColor(r, g, b);
});
// 初始化:发送初始颜色
var initialHex = colorPicker.value;
var initialR = parseInt(initialHex.substr(1, 2), 16);
var initialG = parseInt(initialHex.substr(3, 2), 16);
var initialB = parseInt(initialHex.substr(5, 2), 16);
sendColor(initialR, initialG, initialB);
< /script >
< /body >
< /html >
)rawliteral";
const long timeoutTime = 2000;
// 初始化 PWM 功能
void setupPWM() {
Serial.println("正在初始化 PWM...");
// 检查 ledcAttach 是否可用
if (ledcAttach(redPin, freq, resolution)) {
Serial.println("红色引脚 PWM 初始化成功");
} else {
Serial.println("红色引脚 PWM 初始化失败");
}
if (ledcAttach(greenPin, freq, resolution)) {
Serial.println("绿色引脚 PWM 初始化成功");
} else {
Serial.println("绿色引脚 PWM 初始化失败");
}
if (ledcAttach(bluePin, freq, resolution)) {
Serial.println("蓝色引脚 PWM 初始化成功");
} else {
Serial.println("蓝色引脚 PWM 初始化失败");
}
}
// 连接 WiFi
void connectWiFi() {
Serial.println("n=================================");
Serial.print("正在连接到 WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 30) { // 增加尝试次数到30
delay(500);
Serial.print(".");
attempts++;
// 每5秒显示一次状态
if (attempts % 10 == 0) {
Serial.println();
Serial.print("仍在尝试连接... 已尝试 ");
Serial.print(attempts);
Serial.println(" 次");
}
}
Serial.println(); // 换行
if (WiFi.status() == WL_CONNECTED) {
Serial.println(" WiFi 连接成功!");
Serial.print("IP 地址: ");
Serial.println(WiFi.localIP());
Serial.println("=================================");
Serial.println("n 请在浏览器中输入以上 IP 地址 ");
Serial.println("例如: http://" + WiFi.localIP().toString());
Serial.println("=================================n");
} else {
Serial.println(" WiFi 连接失败!");
Serial.print("错误代码: ");
Serial.println(WiFi.status());
Serial.println("请检查:");
Serial.println("1. WiFi 密码是否正确");
Serial.println("2. WiFi 名称是否正确(注意大小写)");
Serial.println("3. ESP32 是否在信号范围内");
}
}
// 设置 RGB 颜色值
void setColor(int red, int green, int blue) {
ledcWrite(redPin, red);
ledcWrite(greenPin, green);
ledcWrite(bluePin, blue);
}
// 解析 HTTP 请求
bool parseColorRequest(String header, int& red, int& green, int& blue) {
int rPos = header.indexOf("/?r");
if (rPos == -1) return false;
int gPos = header.indexOf('g', rPos);
int bPos = header.indexOf('b', gPos);
int endPos = header.indexOf('&', bPos);
if (gPos == -1 || bPos == -1 || endPos == -1) return false;
red = header.substring(rPos + 3, gPos).toInt();
green = header.substring(gPos + 1, bPos).toInt();
blue = header.substring(bPos + 1, endPos).toInt();
red = constrain(red, 0, 255);
green = constrain(green, 0, 255);
blue = constrain(blue, 0, 255);
return true;
}
// 处理客户端请求
void handleClient(WiFiClient& client) {
unsigned long currentTime = millis();
unsigned long previousTime = currentTime;
String header = "";
String currentLine = "";
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
if (client.available()) {
char c = client.read();
header += c;
if (c == 'n') {
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html;charset=utf-8");
client.println("Connection: close");
client.println();
client.print(index_html);
int red, green, blue;
if (parseColorRequest(header, red, green, blue)) {
setColor(red, green, blue);
Serial.printf("颜色已设置为 红:%d 绿:%d 蓝:%dn", red, green, blue);
}
client.println();
break;
} else {
currentLine = "";
}
} else if (c != 'r') {
currentLine += c;
}
}
}
}
// 初始化
void setup() {
Serial.begin(115200);
delay(1000); // 等待串口就绪
Serial.println("nn=================================");
Serial.println("ESP32 RGB LED 控制器启动中...");
Serial.println("=================================");
setupPWM();
connectWiFi();
server.begin();
Serial.println("HTTP 服务器已启动");
// 初始化为关闭状态
setColor(0, 0, 0);
// 如果 WiFi 连接成功,闪烁 LED 提示
if (WiFi.status() == WL_CONNECTED) {
for (int i = 0; i < 3; i++) {
setColor(255, 255, 255); // 白光
delay(200);
setColor(0, 0, 0); // 关闭
delay(200);
}
}
}
// 主循环
void loop() {
WiFiClient client = server.available();
if (client) {
Serial.println("新客户端已连接");
handleClient(client);
client.stop();
Serial.println("客户端已断开");
}
}
/******************************************************************************
* 深圳市在芯间科技有限公司
* 淘宝店铺:在芯间科技零知板
* 店铺网址:https://shop533070398.taobao.com
* 版权说明:
* 1.本代码的版权归【深圳市在芯间科技有限公司】所有,仅限个人非商业性学习使用。
* 2.严禁将本代码或其衍生版本用于任何商业用途(包括但不限于产品开发、付费服务、企业内部使用等)。
* 3.任何商业用途均需事先获得【深圳市在芯间科技有限公司】的书面授权,未经授权的商业使用行为将被视为侵权。
******************************************************************************/
三、上传与使用步骤
新建工程:打开零知派开发工具,新建一个空白工程。
粘贴代码:将上方完整代码复制到工程中,修改 WiFi 名称和密码。
选择开发板:在软件右侧开发板列表中,选择ESP32。
编译上传:点击「验证」→「上传」,将程序烧录到 ESP32 开发板。
查看服务器地址:打开软件串口调试窗口,等待 WiFi 连接成功,复制打印的IP 地址(如:192.168.3.165)。
网页控制:用手机 / 电脑浏览器(需和 ESP32 连接同一个 WiFi),输入复制的 IP 地址,打开控制页面。
实时调色:点击颜色选择器,无需刷新页面、无需点击按钮,LED 会实时同步你选择的颜色,同时页面显示当前 RGB 数值和操作状态。

四、功能亮点
无刷新实时控制:选择颜色的瞬间,LED 立即变色,操作流畅无延迟。
可视化操作:网页自带颜色预览框、RGB 数值显示、操作成功 / 失败提示。
自适应界面:手机、电脑浏览器均可完美适配,操作简单。
安全稳定:PWM 软件调光,保护 LED 不被烧坏,WiFi 连接稳定。
状态提示:串口打印连接日志、网页实时提示操作结果。
五、常见问题排查
WiFi 连接失败:检查 WiFi 名称 / 密码是否正确、ESP32 是否在 WiFi 信号范围内。
网页打不开:确保手机 / 电脑和 ESP32 连接同一个 WiFi,IP 地址输入无误。
LED 不亮:检查接线是否对应(红 25、绿 26、蓝 27),确认 RGB 模块是高电平点亮。
颜色异常:检查引脚接线是否松动,PWM 初始化是否正常(查看串口日志)。
总结
核心原理:ESP32 开启 WiFi+Web 服务器,网页通过fetch无刷新发送颜色数据,ESP32 解析后用 PWM 控制 RGB LED。
操作极简:修改 WiFi 信息→上传代码→浏览器访问 IP→实时调色,全程无需额外硬件。
扩展性强:可自行修改网页样式、添加开关、调整 PWM 参数,适配更多 RGB 灯模块。
审核编辑 黄宇