💡 划重点
- 目标:做一个能判断你在不在桌前、一旦开小差就“摇头+蜂鸣”提醒你的学习伙伴。
- 主控:ESP32,自带 Wi-Fi,方便后续把学习时长上传云端。
- 感知:人体红外传感器(PIR)检测桌前是否有人。
- 输出:OLED 显示状态与学习计时,舵机模拟“摇头提醒”,蜂鸣器发出警告音。
- 成本:全部物料控制在 40 元以内(不含电池)。
- 接线基准:OLED SDA=GPIO21、SCL=GPIO22,PIR=GPIO18,舵机=GPIO13,蜂鸣器=GPIO27。
需求洞察
目标用户:小初中学生、考研考公备考党,尤其是自制力不足、需要外部监督的学习者。
真实痛点:
- 坐上书桌就想刷手机,一刷半小时过去毫无知觉。
- 传统番茄钟只靠时间提醒,根本不关心你“人在不在”;人去厕所半小时它还以为你在学习。
- 家长或自习室需要低成本、物理直观的“是否在座”判断工具,而不是装摄像头侵犯隐私。
为什么值得做:
- 用 40 元就能解决“假学习”的痛点,比买一个智能台灯便宜太多。
- PIR 是非侵入式检测,不录像,家长和同学的接受度更高。
- ESP32 自带 Wi-Fi,未来可以免费接入物联网平台,生成学习报告,可扩展空间大。
- 项目涉及输入、处理、输出、联网四个环节,作为硬件编程教学案例非常完整。
方案设计
整个系统划分为四层结构:
- 感知层
- 人体红外传感器(HC-SR505 或 mini PIR)贴在显示器下方或桌面前方,检测桌前是否有人。
- 当人体离开超过设定时长(如 5 分钟),判定为“离座”。
- OLED 显示实时状态:“学习中”“离开中”以及计时。
- 控制层
- 主控 ESP32-WROOM-32 开发板,负责逻辑判断、模块驱动、Wi-Fi 通信。
- 状态机分为:WAITING(待机)、STUDYING(正常学习)、AWAY(暂时离开)、WARNING(警告提醒)。
- 学习时段内若检测到持续离座,则进入 WARNING 状态。
- 执行层
- OLED (SSD1306 128×64):显示当前状态、学习累计时间、离开倒计时。
- SG90 舵机:固定在 3D 打印或瓦楞纸支架上,在警告时快速左右摆动,模拟“摇头”。
- 有源蜂鸣器:发出短促滴声,配合舵机提醒。
- 日志/联网层
- 利用 ESP32 内置 Wi-Fi,每 30 秒将学习状态、离开次数通过 HTTP GET 发送至 Blynk 或自建 MQTT 服务器。
- 手机端可看是否在座。该层为可选扩展,不影响基础功能,且不增加额外硬件成本。
物料清单
| 名称 | 数量 | 用途 | 估算单价(元) | 小计(元) |
|---|---|---|---|---|
| ESP32 开发板(WROOM) | 1 | 主控、Wi-Fi 通信 | 15.0 | 15.0 |
| 0.96 寸 OLED (I2C) | 1 | 状态与计时显示 | 8.0 | 8.0 |
| SG90 舵机 | 1 | 摇头提醒 | 5.0 | 5.0 |
| HC-SR505 人体红外传感器 | 1 | 检测桌前是否有人 | 3.5 | 3.5 |
| 有源蜂鸣器模块 | 1 | 声音提醒 | 1.5 | 1.5 |
| 面包板 + 杜邦线若干 | 1 套 | 接线 | 5.0 | 5.0 |
| Micro USB 供电线 | 1 | 供电 | 2.0 | 2.0 |
| 合计 | 40.0 |
*注:价格参考电商零售价,如已有部分材料则总成本更低。若需固定支架可使用废纸板或 3D 打印边角料,不计入成本。*
接线与结构
采用 I2C OLED 可节省 GPIO,方便后续扩展。接线基本沿用给定方案:
- OLED:VCC→3.3V,GND→GND,SDA→GPIO21,SCL→GPIO22
- PIR:VCC→3.3V,GND→GND,OUT→GPIO18
- 舵机:信号线→GPIO13,电源(红线)→5V(开发板 VIN 引脚),地线→GND
- 蜂鸣器:正极→GPIO27,负极→GND
微调说明:给定 GPIO 已经合理,未作改动。唯一注意的是舵机电源取自开发板的 VIN 引脚(5V),而不是 3.3V,以保证舵机扭力。若使用 USB 供电,VIN 通常直接输出 USB 5V,足够驱动一个 SG90。
结构建议:将 PIR 固定在屏幕下方或书桌挡板上,检测区域对准坐姿位置。舵机装在摇臂上,摇头幅度约 ±30°,必要时可用橡皮筋固定两个小纸板模拟耳朵。ESP32 与面包板放在桌角收纳盒里,仅露出 OLED 和舵机。
核心代码
下面给出 Arduino/PlatformIO 骨架,可直接编译。需要安装 U8g2、ESP32Servo、WiFi 库。代码中 WiFi 与日志部分注释掉,可根据需要启用。
#include <Wire.h>
#include <U8g2lib.h>
#include <ESP32Servo.h>
// OLED
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 22, /* data=*/ 21);
// PIR
const int PIR_PIN = 18;
// 蜂鸣器
const int BUZZER_PIN = 27;
// 舵机
Servo myservo;
const int SERVO_PIN = 13;
unsigned long lastPresence = 0;
const unsigned long AWAY_TIMEOUT = 5 * 60 * 1000UL; // 5分钟
bool isPresent = false;
unsigned long studyStart = 0;
int warningCount = 0;
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
myservo.attach(SERVO_PIN);
myservo.write(90); // 居中
u8g2.begin();
studyStart = millis();
// 可选 WiFi 初始化
// WiFi.begin("ssid", "password");
}
void loop() {
// 读取 PIR,高电平有人
int pirState = digitalRead(PIR_PIN);
bool currentPresence = (pirState == HIGH);
if (currentPresence) {
lastPresence = millis();
if (!isPresent) {
// 刚回来
isPresent = true;
}
}
unsigned long now = millis();
unsigned long awayDuration = (now - lastPresence);
if (isPresent && awayDuration > AWAY_TIMEOUT) {
isPresent = false; // 判定离开
warningCount++;
}
// 更新 OLED
u8g2.clearBuffer();
unsigned long studyMinutes = (now - studyStart) / 60000;
char buf[32];
sprintf(buf, "学习 %lu 分钟", studyMinutes);
u8g2.drawStr(0, 10, buf);
if (!isPresent && awayDuration > AWAY_TIMEOUT) {
// 提醒
u8g2.drawStr(0, 25, "状态:开小差!");
u8g2.drawStr(0, 40, "快回来学习!");
u8g2.sendBuffer();
// 舵机摇动 + 蜂鸣
for (int angle = 60; angle <= 120; angle += 30) {
myservo.write(angle);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
delay(100);
}
myservo.write(90);
} else if (isPresent) {
u8g2.drawStr(0, 25, "状态:专注中");
u8g2.sendBuffer();
digitalWrite(BUZZER_PIN, LOW);
myservo.write(90);
// 可选定时上传学习日志
} else {
u8g2.drawStr(0, 25, "状态:暂时离开");
u8g2.sendBuffer();
digitalWrite(BUZZER_PIN, LOW);
myservo.write(90);
}
delay(500);
}
调试步骤
- 单独验证 OLED:仅连接 OLED,运行 I2C 扫描器示例确保地址 0x3C 可见,再用 U8g2 的 HelloWorld 点亮屏幕。
- PIR 灵敏度调节:接上 PIR,串口打印电平变化,调整传感器上两个旋钮(延时、灵敏度)直到人离开约 30 秒输出变低即可。
- 舵机中位校准:写入 servo.write(90),观察舵机臂是否水平,必要时调整机械安装角度。
- 蜂鸣器测试:直接让 GPIO27 高低翻转,确认有滴声。若为无源蜂鸣器则需 PWM,本项目采用有源模块更简单。
- 联合运行:上传完整代码,坐在桌前看 OLED 是否跳转“专注中”,起身离开 5 分钟后检查舵机是否摇头并蜂鸣。
- 外壳组装:用纸板折叠一个矩形“小机器人”外壳,将 OLED 嵌在面部,舵机装在头部,增加趣味性。