桌面作业提醒机器人:硬件编程项目方案
💡 划重点
- 主控芯片:ESP32,支持Wi-Fi与蓝牙,成本低且性能充足。
- 核心功能:通过人体传感器感知入座,利用OLED屏与蜂鸣器提醒作业计划,用舵机做出“点头”或“摇头”等趣味反馈。
- 目标成本:40 元以内,所有物料均为常见模块,兼容性强。
- 关键接线:OLED使用I2C接口(SDA=21,SCL=22),PIR人体传感器接GPIO18,舵机接GPIO13,蜂鸣器接GPIO27。
- 开发方式:采用Arduino框架编写,代码结构清晰,适合初学者和进阶用户二次开发。
需求洞察
目标用户:主要面向中小学生、考研自习者以及在书桌前长时间进行脑力劳动的人群。他们的学习桌通常在卧室或书房,环境较为安静,但缺乏外部学习监督,容易被手机、杂念等干扰。
真实痛点:学生坐下后往往忘记时间,要么一坐就是数小时导致颈椎疲劳,要么刚坐下几分钟就起身玩手机。传统的番茄钟需要手动操作,而家长提醒又容易引发亲子矛盾。这个项目解决的问题是“坐在书桌前却没有按照计划学习”这一高频且真实的场景。
为什么值得做:首先,硬件成本低,一套不超过40元,具有很高的可复制性。其次,ESP32是其学习平台;通过这一项目可综合练习传感器输入、执行器输出、无线通信和外壳装配等多项技能。最后,这个项目具有实用价值,能真正改变用户的学习习惯,不是“吃灰玩具”。
方案设计
感知层
感知层由PIR人体红外传感器构成,安置于桌面朝向用户的支架上,用于检测用户是否坐在书桌前。当用户入座后,传感器输出高电平信号至ESP32的GPIO18。为了降低误报,可在代码中设置连续高电平超过3秒才判定为“有效入座”。
控制层
控制层以ESP32为核心,负责信号采集、状态管理和任务调度。系统维护一个简单的时间状态机,分为“未入座”、“已入座未开始任务”、“任务进行中”、“超时提醒”四种状态。使用定时器记录在座时长,并与设定的学习时段(例如50分钟)进行对比。此外,ESP32可获取本地时间(通过NTP),在预设的学习时段内若检测到人,则自动启动提醒流程。
执行层
执行层包括OLED显示屏、舵机和蜂鸣器。
- OLED在空闲时显示当前时间,在检测到入座后显示“今日任务清单”,若任务超时则轮播“该休息了”。
- 舵机连接一只3D打印或纸板制作的“小熊猫”,入座时做出“点头”动作表示欢迎;超时时做出“摇头”动作表示提醒。
- 蜂鸣器在入座时发出短暂提示音,在超时时发出三短两长的警报音。
日志/联网层
ESP32通过Wi-Fi连接到本地网络,使用NTP获取时间。为保证日志不依赖外部服务,使用SD卡或闪存记录每日入座与离开的时间戳。若未来需要实现远程监控,可通过MQTT将日志发送至家中服务器或手机APP,但该功能初始版本不强制开启。
物料清单
| 序号 | 物料名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|---|
| 1 | ESP32开发板 | 1 | 主控芯片 | 18 |
| 2 | 0.96寸OLED显示屏(I2C) | 1 | 状态显示 | 8 |
| 3 | PIR人体传感器 | 1 | 感知用户是否入座 | 3 |
| 4 | SG90舵机 | 1 | 制作机械提醒动作 | 4 |
| 5 | 有源蜂鸣器 | 1 | 声音提醒 | 2 |
| 6 | 面包板与跳线若干 | 1套 | 电路搭建 | 3 |
| 7 | 纸板或亚克力外壳 | 1 | 固定传感器与舵机 | 1 |
| 8 | 杜邦线、扎带、胶枪 | 若干 | 组装 | 1 |
| 合计 | 40元以内(按实际采购冗余,总价约39元) |
接线与结构
接线明确如下:
- OLED:VCC→3.3V,GND→GND,SDA→GPIO21,SCL→GPIO22。
- PIR传感器:VCC→5V,GND→GND,OUT→GPIO18。
- 舵机:红线→5V,棕线→GND,橙线→GPIO13。
- 蜂鸣器:正极→GPIO27,负极→GND(有源蜂鸣器可通过三极管驱动,但GPIO27直接驱动低功耗蜂鸣器亦可)。
微调说明:原定GPIO没有变动。若使用SSD1306的OLED,地址通常为0x3C;若为其他地址,可在代码中修改。舵机电源建议从5V引脚接入,避免ESP32板载稳压器过载。
核心代码
以下为Arduino骨架,可直接在PlatformIO或Arduino IDE中编译。不依赖复杂库,仅使用Wire、Adafruit_SSD1306和ESP32Servo。
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Servo.h>
#define OLED_SDA 21
#define OLED_SCL 22
#define PIR_PIN 18
#define SERVO_PIN 13
#define BUZZER_PIN 27
Adafruit_SSD1306 display(128, 64, &Wire;, -1);
Servo reminderServo;
const int STUDY_MINUTES = 50;
unsigned long sitStartTime = 0;
bool isSitting = false;
bool isReminded = false;
void setup() {
pinMode(PIR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
display.clearDisplay();
display.setTextSize(1);
reminderServo.write(90);
Serial.begin(115200);
}
void loop() {
int pirState = digitalRead(PIR_PIN);
if (pirState == HIGH && !isSitting) {
isSitting = true;
sitStartTime = millis();
isReminded = false;
playTone(200, 100);
nodHead(2);
displayMessage("Welcome!");
}
if (isSitting && !isReminded && (millis() - sitStartTime > STUDY_MINUTES * 60000UL)) {
isReminded = true;
playTone(800, 200);
playTone(400, 200);
playTone(800, 200);
shakeHead(3);
displayMessage("Break Time!");
}
if (pirState == LOW && isSitting) {
isSitting = false;
isReminded = false;
reminderServo.write(90);
}
delay(100);
}
void nodHead(int times) {
for (int i = 0; i < times; i++) {
reminderServo.write(60);
delay(200);
reminderServo.write(120);
delay(200);
}
reminderServo.write(90);
}
void shakeHead(int times) {
for (int i = 0; i < times; i++) {
reminderServo.write(30);
delay(200);
reminderServo.write(150);
delay(200);
}
reminderServo.write(90);
}
void playTone(int freq, int ms) {
tone(BUZZER_PIN, freq, ms);
delay(ms + 20);
noTone(BUZZER_PIN);
}
void displayMessage(String msg) {
display.clearDisplay();
display.setCursor(0, 0);
display.println(msg);
display.display();
}
此代码编译时需安装Adafruit_SSD1306库与ESP32Servo库。若蜂鸣器为无源蜂鸣器,建议在信号线上串联一个1kΩ电阻。
调试步骤
- 硬件自检:先单独测试OLED,烧写简单I2C扫描代码确认地址。再分别测试PIR,用手遮挡传感器触发蜂鸣器。
- 舵机校正:上电时舵机应处于90度位置。若上电后抖动,检查电源和接地。
- 状态机验证:将
STUDY_MINUTES临时改为0.2分钟,快速模拟超时,观察舵机点头与蜂鸣器提醒是否正常。 - NTP时间校准:若后续加入联网功能,需在
setup()中添加Wi-Fi连接,并调用configTime。注意蜂窝或校园网可能屏蔽NTP端口。 - 整体联动测试:放置在桌面,正常入座30秒,判断是否误触发;离开后是否重置状态。
设计图
本设计图展示系统的信息流向:感知输入(PIR与时钟)→控制处理(ESP32状态机)→执行反馈(OLED、舵机、蜂鸣器)→数据上报(Wi-Fi日志,可选)。整体模块化程度高,各环节解耦,便于后期升级。用户可在调试过程中将舵机与小熊猫模型固定于OLED上方,形成完整的桌面陪伴式提醒机器人。