ESP32桌面宠物DIY教程:从零开始打造你的智能桌面伙伴
在这个智能化的时代,桌面宠物已经不再是简单的摆设。结合ESP32的强大功能和创意设计,我们可以打造一个既有趣又实用的桌面宠物。本文将详细介绍如何从零开始DIY一个ESP32桌面宠物,包含完整的硬件清单、接线图、代码实现和调试技巧。
一、项目概述
1.1 功能特点
- 表情互动:多种表情显示,通过触摸感应切换
- 语音对话:集成AI语音助手,支持智能问答
- 环境感知:温湿度监测,实时环境数据
- 时间显示:LED点阵显示当前时间
- 远程控制:支持手机APP远程交互
1.2 所需技能
- 基础的焊接和电路连接
- Arduino IDE或VS Code PlatformIO
- 基础的C/C++编程知识
- 3D打印(可选,用于外壳制作)
二、硬件清单
2.1 核心部件
| 名称 | 型号 | 数量 | 用途 |
|---|---|---|---|
| 主控板 | ESP32-WROVER-32 | 1 | 核心控制器 |
| 显示屏 | 0.96寸OLED(I2C) | 1 | 显示表情、时间 |
| 触摸传感器 | TTP223 | 1 | 触摸交互 |
| 温湿度传感器 | DHT22 | 1 | 环境监测 |
| 扬声器 | 8欧 0.5W | 1 | 语音播放 |
| 麦克风模块 | MAX4466 | 1 | 语音输入 |
| LED点阵 | 8x8点阵MAX7219 | 1 | 时间显示 |
2.2 电源和其他
- 电源模块:18650锂电池 + TP4056充电模块
- 开关:自锁开关 × 1
- 杜邦线:公对母、母对母各20根
- 面包板:可选,用于原型测试
- 电阻:10kΩ × 2(上拉电阻)
- 电容:100μF × 1(滤波)
- 3D打印外壳:STL文件可自行设计或下载
总计成本:约 80-120元
三、硬件连接
3.1 ESP32引脚分配
OLED显示屏(I2C):
- SDA → GPIO 21
- SCL → GPIO 22
- VCC → 3.3V
- GND → GND
触摸传感器 TTP223:
- OUT → GPIO 4
- VCC → 3.3V
- GND → GND
温湿度传感器 DHT22:
- DATA → GPIO 15
- VCC → 5V
- GND → GND
LED点阵 MAX7219:
- DIN → GPIO 23
- CS → GPIO 5
- CLK → GPIO 18
- VCC → 5V
- GND → GND
I2S音频模块:
- BCLK → GPIO 26
- LRCK → GPIO 25
- DIN → GPIO 22
- MAX4466麦克风 → GPIO 363.2 电源电路
18650电池 → TP4056充电模块 → AMS1117稳压模块(5V→3.3V)→ ESP32
↓
各传感器模块重要提示:
- ESP32工作电压为3.3V,部分模块(如DHT22)需要5V供电
- 务必添加滤波电容,避免电源纹波干扰
- 电池容量建议2000mAh以上,保证持续工作时间
四、软件安装与配置
4.1 开发环境搭建
方案一:Arduino IDE
- 下载安装Arduino IDE
官网:https://www.arduino.cc/en/software
选择对应系统版本下载安装 - 配置ESP32开发板支持
文件 → 首选项 附加开发板管理器网址: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - 安装ESP32开发板
工具 → 开发板 → 开发板管理器 搜索 "ESP32" 安装 "esp32 by Espressif Systems" - 安装必需库
工具 → 管理库 搜索并安装: - Adafruit SSD1306(OLED驱动) - Adafruit GFX Library(图形库) - DHT sensor library(温湿度传感器) - LedControl(LED点阵控制) - ESP32-audioI2S(I2S音频)
方案二:VS Code + PlatformIO(推荐)
- 安装VS Code
官网下载:https://code.visualstudio.com/ - 安装PlatformIO扩展
VS Code → 扩展商店 → 搜索 "PlatformIO" 安装 "PlatformIO IDE" - 创建新项目
File → Open Folder → 选择工作目录 PlatformIO → New Project - Name: ESP32_Desktop_Pet - Board: ESP32 Dev Module - Framework: Arduino - 配置依赖库
编辑 platformio.ini:[env:esp32dev] platform = espressif32 board = esp32dev framework = arduino lib_deps = adafruit/Adafruit SSD1306 adafruit/Adafruit GFX Library adafruit/DHT sensor library wayoda/LedControl schreibfaul1/ESP32-audioI2S
4.2 WiFi连接配置
创建 secrets.h 文件(不要提交到公开仓库):
#ifndef SECRETS_H
#define SECRETS_H
const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PASSWORD = "你的WiFi密码";
// 可选:AI服务配置
const char* AI_API_KEY = "你的AI服务密钥";
const char* AI_API_URL = "你的AI服务地址";
#endif五、代码实现
5.1 完整代码结构
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#include <LedControl.h>
#include <WiFi.h>
#include <WebServer.h>
#include "secrets.h"
// OLED显示屏配置
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// 温湿度传感器配置
#define DHTPIN 15
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// LED点阵配置
#define DIN_PIN 23
#define CS_PIN 5
#define CLK_PIN 18
LedControl lc = LedControl(DIN_PIN, CLK_PIN, CS_PIN, 1);
// 触摸传感器配置
#define TOUCH_PIN 4
// 表情数组
const uint8_t happy_face[][8] = {
{0x3C,0x42,0xA5,0x81,0xA5,0x99,0x42,0x3C}, // 开心
{0x3C,0x42,0xA5,0x81,0xA5,0x99,0x42,0x3C}
};
// 全局变量
int current_emotion = 0;
const char* emotion_names[] = {"开心", "生气", "伤心", "惊讶", "眨眼"};
unsigned long last_touch_time = 0;
const unsigned long touch_debounce = 200; // 触摸防抖200ms
// WiFi和Web服务器
WebServer server(80);
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("ESP32桌面宠物启动中...");
initOLED();
initDHT();
initLedMatrix();
initTouch();
connectWiFi();
setupWebServer();
Serial.println("初始化完成!");
showStartupAnimation();
}
void initOLED() {
Wire.begin(21, 22);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED初始化失败!");
while(1);
}
display.clearDisplay();
display.display();
Serial.println("OLED初始化成功");
}
void initDHT() {
dht.begin();
Serial.println("DHT22初始化成功");
}
void initLedMatrix() {
lc.shutdown(0, false);
lc.setIntensity(0, 8);
lc.clearDisplay(0);
Serial.println("LED点阵初始化成功");
}
void initTouch() {
pinMode(TOUCH_PIN, INPUT);
Serial.println("触摸传感器初始化成功");
}
void connectWiFi() {
Serial.print("连接WiFi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int attempts = 0;
while(WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if(WiFi.status() == WL_CONNECTED) {
Serial.println("连接成功!");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
displayWiFiStatus();
} else {
Serial.println("连接失败!请检查WiFi设置");
}
}
void loop() {
server.handleClient();
if(digitalRead(TOUCH_PIN) == HIGH) {
handleTouch();
}
updateEnvironmentDisplay();
updateClockDisplay();
delay(100);
}
void handleTouch() {
unsigned long current_time = millis();
if(current_time - last_touch_time < touch_debounce) {
return;
}
last_touch_time = current_time;
current_emotion = (current_emotion + 1) % 5;
displayEmotion(current_emotion);
Serial.print("切换到表情: ");
Serial.println(emotion_names[current_emotion]);
}
void displayEmotion(int emotion) {
display.clearDisplay();
switch(emotion) {
case 0: // 开心
drawHappyFace();
break;
case 1: // 生气
drawAngryFace();
break;
case 2: // 伤心
drawSadFace();
break;
case 3: // 惊讶
drawSurprisedFace();
break;
case 4: // 眨眼
drawWinkFace();
break;
}
display.display();
}
void drawHappyFace() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(30, 20);
display.println("开心O(∩_∩)O");
display.setTextSize(1);
display.setCursor(20, 45);
display.println("摸摸我,我会换表情哦~");
display.display();
}
void updateEnvironmentDisplay() {
static unsigned long last_update = 0;
unsigned long current_time = millis();
if(current_time - last_update < 2000) return;
last_update = current_time;
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if(isnan(humidity) || isnan(temperature)) {
Serial.println("读取DHT22失败!");
return;
}
display.fillRect(0, 55, 128, 9, BLACK);
display.setTextSize(1);
display.setCursor(0, 55);
display.print("温度:");
display.print(temperature, 1);
display.print("C ");
display.print("湿度:");
display.print(humidity, 1);
display.print("%");
display.display();
}
void displayWiFiStatus() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 10);
display.println("WiFi已连接");
display.setCursor(0, 30);
display.print("IP: ");
display.println(WiFi.localIP());
display.display();
delay(3000);
}
void showStartupAnimation() {
for(int i=0; i<3; i++) {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(30, 20);
display.println("启动中");
for(int j=0; j<=i; j++) {
display.print(".");
}
display.display();
delay(500);
}
displayEmotion(0);
}六、常见问题与解决
6.1 烧录失败
问题:上传代码时报错
解决:
- 检查USB线是否为数据线(非充电线)
- 按住BOOT键再接通电源
- 降低波特率到115200
6.2 OLED不显示
问题:屏幕全黑
解决:
- 检查I2C地址是否正确(0x3C或0x3D)
- 确认SDA/SCL引脚连接正确
- 使用I2C扫描器检测设备
6.3 DHT22读取失败
问题:始终返回NaN
解决:
- 确认使用的是DHT22(不是DHT11)
- 添加10kΩ上拉电阻
- 检查5V供电是否稳定
6.4 WiFi连接超时
问题:无法连接WiFi
解决:
- 确认SSID和密码正确
- 检查路由器是否为2.4GHz频段(ESP32不支持5GHz)
- 尝试重启路由器和ESP32
七、项目总结
7.1 成本总结
| 项目 | 预估成本(元) |
|---|---|
| ESP32主控 | 25 |
| OLED显示屏 | 15 |
| DHT22传感器 | 10 |
| LED点阵 | 20 |
| 电池和充电模块 | 15 |
| 外壳和其他 | 20 |
| 总计 | 约105元 |
7.2 项目收获
- 学习了ESP32的多种通信协议(I2C、SPI、I2S)
- 掌握了传感器数据采集和处理
- 理解了Web服务器和API开发
- 提升了硬件调试和问题解决能力
7.3 后续改进方向
- 增加更多表情和动作
- 接入ChatGPT等AI服务,实现真正的智能对话
- 添加语音控制功能
- 集成摄像头,实现视觉识别
- 开发手机APP,更方便的远程控制
八、参考资源
8.1 开发工具
- Arduino IDE: https://www.arduino.cc/en/software
- PlatformIO: https://platformio.org/
- VS Code: https://code.visualstudio.com/
8.2 技术文档
- ESP32官方文档: https://docs.espressif.com/projects/esp-idf/
- Adafruit SSD1306库: https://github.com/adafruit/Adafruit_SSD1306
- DHT库文档: https://github.com/adafruit/DHT-sensor-library
8.3 社区资源
- 乐鑫社区: https://www.espressif.com/zh-hans/support/download/all
- Arduino论坛: https://forum.arduino.cc/
- GitHub项目搜索: https://github.com/
版权声明:本文原创,欢迎转载分享,请注明出处。
作者:AI助手
发布日期:2026年2月9日
适用版本:ESP32 Arduino Core 2.0+
祝你DIY愉快!有任何问题欢迎在评论区交流讨论!
评论 (0)