💡 划重点
- 主控选用ESP32,成本低、联网快,完美承接定时投喂与远程管理
- 出粮机构用步进电机带动螺旋杆,定量精准、卡粮概率低
- 出口开合用舵机控制门板,防潮防虫,闲置时闭合
- 联网全走MQTT,手机随时查看进食记录、手动补喂,断网也能按本地定时执行
- 硬件总成本控制在90元内,全部使用通用模块,自己就能组装和维修
需求洞察
目标用户:朝九晚六的上班族猫主、经常短途出差但不想寄养的人群、家里有多只猫需要分餐控制的家庭。
真实痛点:
- 加班或堵车时无法准时喂食,猫饿到吐黄水,长期会引发肠胃病。
- 传统机械定时喂食器出粮量不准,容易卡粮,且无法远程确认“究竟有没有出粮”。
- 普通喂食器没有防虫防潮设计,南方回南天时猫粮变软发霉,猫拒食甚至中毒。
- 宠物医院建议少食多餐,但人工操作难以严格执行,自动定时能显著降低肥胖和泌尿问题风险。
为什么值得做:用不到一顿火锅的成本,解决猫最基础的生存需求,出差两天也不用麻烦邻居。主板自带联网能力,未来还能扩展摄像头、称重传感器,硬件和软件的二次开发空间都非常大,完全可作为智能家居的入门实战项目。
方案设计
感知层
- 时间基准:ESP32 通过 NTP 联网对时,定时任务在本地运行,网络中断不影响当日已设定的喂食计划。
- 手动触发:一个物理按键(接 GPIO32)实现“立刻出粮一份”,长按 5 秒恢复出厂设置。
- 状态指示:板载 LED(GPIO2)闪烁表示正在连接 WiFi/ 未联网,常亮表示已连接 MQTT。
控制层
- ESP32 双核分工:Core 0 负责步进电机脉冲序列和舵机动作,Core 1 跑 WiFi、MQTT 和定时轮询。
- 定时任务采用
millis()非阻塞比对,支持每天最多 6 个喂食时间点(可改代码扩展)。 - MQTT 主题规划:
catfeeder/status上报投喂结果,catfeeder/feed接收远程手动指令,catfeeder/config接收新的定时表。
执行层
- 步进电机:28BYJ-48 配 ULN2003 驱动板,4 线(IN1–IN4)接 GPIO25/26/27/14,按半步步进模式转动储粮桶底部的螺旋推杆,每转 64 步对应约 10g 粮。
- 舵机:SG90 接 GPIO13,平时保持 0°(关闭出口),收到出粮指令后转至 90° 打开 3 秒,再归位。
日志 / 联网层
- WiFi 连接成功后自动同步 NTP,校准内部时钟。
- 每次投喂完成后,通过 MQTT 上报 Unix 时间戳、出粮份数、剩余动作次数,手机端可形成喂食日历。
- 若 MQTT 服务器断连,本地喂食记录缓存于 RTC 内存,最多保存 20 条,重连后一次性补发。
物料清单
| 序号 | 物料名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|---|
| 1 | ESP32 开发板 | 1 | 主控、联网 | 20 |
| 2 | 28BYJ-48 步进电机 + ULN2003 驱动板 | 1 | 旋转出粮螺旋杆 | 10 |
| 3 | SG90 舵机 | 1 | 出口门板开闭 | 5 |
| 4 | 轻触按键 | 2 | 手动喂食、复位 | 1 |
| 5 | 5V 2A 电源适配器 | 1 | 系统供电 | 10 |
| 6 | Micro USB 数据线 | 1 | 供电及烧录 | 3 |
| 7 | 面包板 + 杜邦线 | 1套 | 电路连接 | 10 |
| 8 | 10KΩ 电阻 | 4 | 按键上拉 | 1 |
| 9 | 3D 打印储粮桶外壳及螺旋杆 | 1套 | 结构件 | 15 |
| 10 | 杂项(扎带、热缩管等) | 1批 | 装配 | 5 |
| 合计 | 80 |
总成本 80 元,预留 10 元缓冲,完全满足 90 元上限。若已有 3D 打印机,外壳成本可进一步降至材料费约 8 元。
接线与结构
接线表(使用给定的 GPIO,无需微调):
| ESP32 引脚 | 连接模块 | 说明 |
|---|---|---|
| GPIO25 | ULN2003 IN1 | 步进电机 A 相 |
| GPIO26 | ULN2003 IN2 | 步进电机 B 相 |
| GPIO27 | ULN2003 IN3 | 步进电机 C 相 |
| GPIO14 | ULN2003 IN4 | 步进电机 D 相 |
| GPIO13 | SG90 信号线 | 舵机 PWM 控制 |
| GPIO32 | 按键1(手动喂食) | 一端接 GPIO32,另一端接 GND,内部上拉 |
| GPIO33 | 按键2(复位) | 同按键 1 接法 |
| GPIO2 | 板载 LED | 低电平点亮,指示状态 |
| 5V / GND | ULN2003、SG90、面包板电源轨 | 驱动供电由适配器经面包板分配 |
结构简述:
储粮桶底部伸入一根螺旋推杆,步进电机通过联轴器直接驱动。推杆末端连接出口通道,通道上缘安装由舵机驱动的弧形挡板。按下手动按键或定时触发时,舵机先开门,步进电机旋转固定步数推粮,随后舵机关门。按键另一侧留有复位孔,避免猫误触。
核心代码
以下为 Arduino IDE 可直接编译的骨架代码,使用 WiFi、PubSubClient、ESP32Servo 库,步进电机采用自定义时序,无需额外库。
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32Servo.h>
const char* ssid = "你的WiFi";
const char* password = "你的密码";
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
WiFiClient espClient;
Servo doorServo;
// 步进引脚
const int IN1 = 25, IN2 = 26, IN3 = 27, IN4 = 14;
// 按键
const int BTN_FEED = 32;
const int BTN_RESET = 33;
// 舵机
const int SERVO_PIN = 13;
// 状态 LED
const int LED_BUILTIN = 2;
// 半步步序
const int steps[8][4] = {
{1,0,0,0}, {1,1,0,0}, {0,1,0,0}, {0,1,1,0},
{0,0,1,0}, {0,0,1,1}, {0,0,0,1}, {1,0,0,1}
};
unsigned long lastFeedTime = 0;
const unsigned long feedInterval = 28800000; // 8小时,示例
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
digitalWrite(LED_BUILTIN, LOW); // 常亮表示连接
}
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
if (String(topic) == "catfeeder/feed" && msg == "1") {
doFeed();
}
}
void doFeed() {
doorServo.write(90); // 开门
delay(1000);
// 步进电机旋转一圈(64*8=512步), 10g粮
for (int i = 0; i < 64; i++) {
for (int j = 0; j < 8; j++) {
delay(2);
}
}
delay(2000);
doorServo.write(0); // 关门
// 关闭所有相
client.publish("catfeeder/status", "feed_done");
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ESP32CatFeeder")) {
client.subscribe("catfeeder/feed");
} else {
delay(5000);
}
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
doorServo.attach(SERVO_PIN);
doorServo.write(0);
Serial.begin(115200);
setup_wifi();
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
// 手动喂食
if (digitalRead(BTN_FEED) == LOW) {
delay(50); // 消抖
if (digitalRead(BTN_FEED) == LOW) {
doFeed();
while(digitalRead(BTN_FEED) == LOW); // 等待松开
}
}
// 定时喂食
if (millis() - lastFeedTime > feedInterval) {
lastFeedTime = millis();
doFeed();
}
}
代码中定时间隔写死为 8 小时,实际可扩展为读取配置结构或通过 MQTT 动态设定。NTP 校时可自行添加 configTime,不影响骨架结构。
调试步骤
- 硬件分步测试:先不装粮,单独测试步进电机,用示例代码让它正反转 5 圈,观察是否丢步。
- 舵机校准:给舵机接上电源,在
setup()中改角度,检查开门 90° 和关门 0° 是否与结构匹配,必要时微调联杆长度。 - WiFi 与 MQTT 联通:打开串口监视器,复位后查看 WiFi 连接状态,再用 MQTT 调试工具发送
catfeeder/feed为1,板载 LED 应有相应闪烁且电机动。 - 空载全流程跑通:不装粮食,模拟定时触发和按键触发,记录出口门板动作与步进电机旋转是否同频,确认延时合理。
- 装粮定量测试:装入猫粮,连续执行 10 次喂食指令,用厨房秤称量每次出粮重量,调整步进步数以逼近理想单份克数。
- 长期运行:至少连续运行 24 小时,观察是否有内存泄漏(
heap_caps_get_free_size打印剩余堆),确保不会死机。
设计图
猫咪自动喂食器结构flow
1
感知输入
→
2
控制处理
→
3
执行反馈
→
4
数据上报