💡 划重点
- 主控用 ESP32,负责定时、联网、MQTT 收发和电机控制。
- 执行层由 28BYJ-48 步进电机驱动螺旋出粮杆,SG90 舵机负责出粮口开合与防卡搅拌。
- 支持本地定时喂食、手机 MQTT 远程手动喂食、喂食记录上报和缺粮提醒。
- 目标物料成本控制在 90 元内,适合家庭宠物场景快速落地。
需求洞察
目标用户是白天上班、经常加班或短期外出的养猫家庭。真实痛点不是“猫不会吃饭”,而是主人无法按时回家添粮,猫在固定饭点反复叫唤,长期饿一顿饱一顿容易引发肠胃问题。市面上成品喂食器动辄两三百元,且很多只能本地定时,无法远程确认是否出粮。自己动手做一台 ESP32 喂食器,既能按计划自动投喂,又能通过 MQTT 接入家庭自动化平台,随手在手机上补喂一次,成本还不到百元。它值得做的原因有三点:一是解决真实刚需,二是硬件门槛低,三是可扩展性强,后续能加称重、摄像头或语音提醒。
方案设计
感知层:ESP32 通过 NTP 获取网络时间,作为定时基准;预留微动开关检测粮仓盖状态,判断是否缺粮或未关盖;MQTT 订阅主题接收远程喂食指令。
控制层:ESP32 双核运行,主循环处理 MQTT 心跳、定时比较和步进电机脉冲;喂食逻辑采用非阻塞方式,避免堵塞网络。
执行层:28BYJ-48 步进电机配合 ULN2003 驱动板,带动螺旋杆旋转,把猫粮从储粮桶推到出粮口;SG90 舵机在出粮前打开挡板,出粮后关闭,防止猫粮受潮和猫爪伸入。
日志/联网层:ESP32 连接 WiFi 后接入 MQTT,发布喂食时间、出粮份数、设备在线状态和缺粮告警;同时支持订阅远程命令,实现“手机一点,立即出粮”。
物料清单
| 物料 | 数量 | 用途 | 估算单价 | 小计 |
|---|---|---|---|---|
| ESP32 开发板 | 1 | 主控、WiFi、MQTT | 18 元 | 18 元 |
| 28BYJ-48 步进电机+ULN2003 驱动板 | 1 | 螺旋出粮 | 12 元 | 12 元 |
| SG90 舵机 | 1 | 出粮口开合/搅拌 | 6 元 | 6 元 |
| 5V 2A 电源适配器 | 1 | 整机供电 | 12 元 | 12 元 |
| DC 降压模块 5V | 1 | 稳定 5V 输出 | 4 元 | 4 元 |
| 杜邦线+面包板 | 1 | 接线与调试 | 8 元 | 8 元 |
| 3D 打印粮桶/转盘 | 1 | 储粮与出粮结构 | 15 元 | 15 元 |
| 螺旋出粮杆/亚克力件 | 1 | 定量推粮 | 8 元 | 8 元 |
| 微动开关 | 1 | 粮仓盖检测 | 2 元 | 2 元 |
| 合计 | 85 元 |
接线与结构
按给定引脚:步进电机 IN1-IN4 接 ESP32 GPIO25、GPIO26、GPIO27、GPIO14;舵机信号接 GPIO13。ULN2003 和舵机使用独立 5V 供电,ESP32 与驱动板共地。微动开关一端接 GPIO34,另一端接 GND,用于检测粮仓盖;GPIO34 仅输入,不影响原定引脚。结构上,粮桶底部开孔安装螺旋杆,步进电机固定在桶底外侧;舵机安装在出粮口上方,用连杆控制挡板。舵机电流较大,务必不要从 ESP32 的 3.3V 取电,否则容易复位。
核心代码
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32Servo.h>
#include <Stepper.h>
const char* ssid = "你的WiFi";
const char* password = "你的密码";
const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
WiFiClient espClient;
Servo gateServo;
Stepper feeder(2048, 25, 26, 27, 14); // IN1-IN4
const int servoPin = 13;
const int lidPin = 34;
unsigned long lastFeed = 0;
const unsigned long feedInterval = 21600000; // 6小时
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
if (msg == "feed") feedOnce();
}
void feedOnce() {
gateServo.write(90); // 打开挡板
delay(300);
feeder.step(512); // 约1/4圈,出粮一份
delay(300);
gateServo.write(0); // 关闭挡板
client.publish("cat/feeder/log", "fed");
}
void setup() {
Serial.begin(115200);
pinMode(lidPin, INPUT_PULLUP);
gateServo.attach(servoPin);
gateServo.write(0);
feeder.setSpeed(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
configTime(8 * 3600, 0, "pool.ntp.org");
client.setCallback(callback);
while (!client.connected()) client.connect("cat-feeder");
client.subscribe("cat/feeder/cmd");
}
void loop() {
if (!client.connected()) client.connect("cat-feeder");
client.loop();
if (millis() - lastFeed > feedInterval) {
feedOnce();
lastFeed = millis();
}
if (digitalRead(lidPin) == HIGH) {
client.publish("cat/feeder/alert", "lid_open_or_empty");
}
}
调试步骤
- 先不装粮,只接 ESP32 和串口,确认能连 WiFi 并打印 IP。
- 接入 MQTT 服务器,用手机或电脑发布
cat/feeder/cmd内容feed,观察串口是否触发。 - 单独测试舵机:上电后挡板应关闭,收到命令后打开再关闭。
- 单独测试步进电机:确认转向正确,若反转则交换 IN1/IN3 或 IN2/IN4。
- 装入少量猫粮,调整
feeder.step()数值,称量每次出粮克数。 - 设置定时喂食间隔,先用 1 分钟测试,再改为 6 小时。
- 拔掉粮仓盖,确认 MQTT 收到缺粮告警。
- 连续运行 24 小时,观察是否卡粮、丢包或重启。