桌面情绪伙伴电子表情盒
划重点
- 以 ESP32 为主控,通过 OLED 双屏显示拟人化表情,舵机驱动耳朵实现物理动态反馈,结合语音识别实现声控交互。
- 项目总成本控制在 120 元以内,适合入门级硬件爱好者、创客教育及桌面摆件市场。
- 双屏采用 SPI 总线复用方案,一块显示主表情(眼睛/嘴),另一块显示辅助信息(心情文字、天气、时间等)。
- 语音识别模块采用本地离线识别方案,无需联网,保护隐私且响应迅速。
- 整体结构小巧,可直接放置于桌面、床头或工位,充当「有温度」的电子宠物。
需求洞察
目标用户
- 独居青年、远程办公者、学生群体。
- 喜欢桌搭文化、电子宠物、DIY 硬件的创客人群。
- 需要情感陪伴但不想承担养宠物责任的都市白领。
真实痛点
- 长时间面对电脑屏幕,缺乏情感反馈与互动,容易产生孤独感和倦怠感。
- 传统桌面摆件只能静态装饰,无法提供情绪价值与陪伴感。
- 智能手机上的虚拟宠物缺乏物理存在感,互动方式单一,不够「真实」。
为什么值得做
- 当前市场上桌面陪伴机器人价格普遍在 300-1000 元,本项目以 120 元内的成本实现核心互动功能,性价比极高。
- 通过 OLED 表情 + 舵机耳朵联动 + 语音识别,打造「看得见、听得懂、有反应」的桌面伙伴,满足用户对情感寄托的需求。
- 项目具备良好的扩展性,后续可接入物联网平台实现天气播报、日程提醒、情绪日志记录等增值功能。
方案设计
感知层
- 语音识别模块:采用 ESP32 内置的语音识别功能或外接 INMP441 麦克风,采集用户语音指令,通过关键词识别(如「开心」「难过」「睡觉」)触发对应表情切换。
- 可选扩展:光敏传感器用于检测环境亮度,调节表情亮度;触摸传感器用于手动互动。
控制层
- ESP32 作为主控制器,负责语音数据处理、表情状态机切换、舵机运动控制。
- 自定义简单状态机,定义多种情绪状态(高兴、伤心、生气、疲惫、惊讶等),每种状态对应特定的 OLED 画面和舵机角度组合。
执行层
- 双 OLED 屏(SPI 接口)实时显示表情画面与辅助信息。
- 两个舵机分别驱动左右「耳朵」,根据不同情绪做出摆动、竖起、耷拉等物理动作。
- 可选:小型蜂鸣器播放简单音效,增强反馈效果。
日志/联网层
- ESP32 通过 Wi-Fi 连接网络,可在本地记录用户互动次数与情绪变化日志,上传至简易网页端或 MQTT 平台。
- 预留 OTA 升级接口,方便后续远程更新表情库或交互逻辑。
物料清单
| 物料名称 | 数量 | 用途说明 | 估算单价(元) | 合计(元) |
|---|---|---|---|---|
| ESP32 开发板 | 1 | 主控芯片 | 25 | 25 |
| 0.96 寸 OLED 屏(SPI) | 2 | 双屏表情显示 | 18 | 36 |
| SG90 舵机 | 2 | 带动耳朵动作 | 8 | 16 |
| INMP441 麦克风模块 | 1 | 语音采集输入 | 15 | 15 |
| 面包板及跳线若干 | 1 | 电路连接 | 8 | 8 |
| 3D 打印外壳/纸盒 | 1 | 结构支撑与外观 | 10 | 10 |
| TYPE-C 数据线等配件 | 1 | 供电与烧录 | 5 | 5 |
| 合计 | - | - | - | 115 |
接线与结构
OLED 双屏接线
- 两块 OLED 共用 SPI 总线(VCC、GND、SCK、MOSI)。
- 两屏的 DC 引脚均接 GPIO2。
- 屏幕 1 的 CS 片选接 GPIO15(CS1),屏幕 2 的 CS 片选接 GPIO27(CS2)。
- 通过切换 CS 电平实现分时复用,同一时刻只驱动一块屏幕刷新,避免总线冲突。
舵机接线
- 左耳朵舵机信号线接 GPIO13。
- 右耳朵舵机信号线接 GPIO14。
- 电源统一接 5V,舵机建议外接 5V 电源或使用开发板 VIN 引脚供电。
结构设计
- 外壳采用 3D 打印或硬纸板拼接,内部预留 OLED 开窗两个,舵机固定在顶部两侧。
- 麦克风放置在壳体正面开孔处,便于采集语音信号。
- 底部留出 TYPE-C 接口位置,便于供电与烧录程序。
核心代码
以下为 Arduino 框架下的核心骨架代码,实现双屏驱动、舵机控制与简单语音识别逻辑:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Servo.h>
#define OLED_DC 2
#define OLED_CS1 15
#define OLED_CS2 27
#define OLED_MOSI 23
#define OLED_SCK 18
#define SERVO_L 13
#define SERVO_R 14
Servo servoLeft, servoRight;
// 情绪状态枚举
enum Emotion {
HAPPY,
SAD,
ANGRY,
SLEEPY
};
Emotion currentEmotion = HAPPY;
void setup() {
Serial.begin(115200);
// 初始化双屏
display1.clearDisplay();
display2.clearDisplay();
// 初始化舵机
servoLeft.attach(SERVO_L);
servoRight.attach(SERVO_R);
// 初始表情
setEmotion(HAPPY);
}
void loop() {
// 模拟语音识别结果(实际接入麦克风识别后替换)
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "happy") setEmotion(HAPPY);
else if (cmd == "sad") setEmotion(SAD);
else if (cmd == "angry") setEmotion(ANGRY);
else if (cmd == "sleep") setEmotion(SLEEPY);
}
delay(50);
}
void setEmotion(Emotion emo) {
currentEmotion = emo;
display1.clearDisplay();
display1.setTextSize(2);
display1.setCursor(20, 20);
switch (emo) {
case HAPPY:
display1.println(":)");
servoLeft.write(180);
servoRight.write(180);
break;
case SAD:
display1.println(":(");
servoLeft.write(0);
servoRight.write(0);
break;
case ANGRY:
display1.println(">.<");
servoLeft.write(90);
servoRight.write(180);
break;
case SLEEPY:
display1.println("-.-");
servoLeft.write(0);
servoRight.write(90);
break;
}
display1.display();
// 辅屏显示当前情绪名称
display2.clearDisplay();
display2.setTextSize(2);
display2.setCursor(10, 20);
display2.println("State:");
display2.setCursor(10, 40);
display2.display();
}
const char* emoName(Emotion emo) {
switch (emo) {
case HAPPY: return "Happy";
case SAD: return "Sad";
case ANGRY: return "Angry";
case SLEEPY: return "Sleepy";
}
}
调试步骤
- 基础电路检查:使用万用表确认电源与地导通正常,无短路。
- OLED 屏测试:分别烧录单屏显示测试代码,确认两屏独立工作正常,再启用 CS 片选切换逻辑。
- 舵机调零与行程测试:烧录舵机扫动程序,确认两个舵机角度范围,并在外壳上调试安装位置,避免卡滞。
- 语音识别调试:初版可用串口发送命令模拟语音识别结果,验证表情与舵机状态切换逻辑;随后接入麦克风模块,调整唤醒词与识别阈值。
- 整机联调:装入外壳,进行 30 分钟连续运行测试,观察有无过热、卡死或显示异常。
- 功耗与稳定性测试:测量运行电流,确认 Type-C 供电能力充足;检查 Wi-Fi 连接稳定性。
设计图
桌面情绪伙伴电子表情盒结构flow
1
感知输入
→
2
控制处理
→
3
执行反馈
→
4
数据上报