💡 划重点
- 主控选用ESP32,利用其Wi‑Fi与定时器资源,实现远程喂食与离线定时双保障。
- 步进电机驱动螺旋送料机构,出粮精准不卡粮;舵机负责防潮挡板开合,双重密封。
- 通过MQTT将每次喂食记录、余量告警、设备状态上报至手机,主人随时掌握喵星人饮食。
- 硬件成本控制在90元以内,结构件可3D打印或使用食品级亚克力拼接,组装门槛低。
需求洞察
目标用户:多猫家庭、经常加班或短期出差的白领养猫人,以及对宠物健康数据有管理需求的年轻群体。
真实痛点:
- 加班、堵车、周末外出无法准时投喂,猫咪暴饮暴食或长时间断粮易诱发肠胃、胰腺问题。
- 传统机械喂食器出粮量不准,干粮受潮变质,清理麻烦。
- 想远程知道“猫咪吃没吃、吃了多少”,但市面智能喂食器价格多在300‑500元,超出预算。
为什么值得做:
将物联网与精确机电控制结合,用<90元实现基础智能喂食闭环。既能解决刚性看护需求,又为程序爱好者和学生提供实战项目,兼具情感价值与学习价值。方案开放可扩展,后期可加入摄像头、AI识别多猫分食等,生命周期长。
方案设计
整体分为四层,均围绕ESP32主控展开:
感知层
- 槽型光电开关(放于出粮口),检测每次落粮脉冲,实时计算颗粒数,校准出粮克数。
- 红外接近传感器(食盆上方),判断猫咪是否靠近,离场后自动收回多余猫粮,减少浪费。
- 干簧管磁控开关(储粮桶盖),检测桶盖是否打开,用以触发补粮提醒。
控制层
- ESP32负责所有逻辑调度:Ticker硬件定时器维护本地RTC时钟,按预设的每日最多6组时间触发喂食;同时维护MQTT长连接,接收云端即时指令。
- 控制板载LED指示网络与出粮状态,引脚资源分配充分考虑步进电机、舵机、传感器的优先级。
执行层
- 28BYJ‑48步进电机配合ULN2003驱动板,推进螺旋输送杆,精准控制旋转圈数→对应出粮克数。
- SG90舵机驱动弧形挡板,喂食时打开出料口,喂食完毕或待机时关闭,防止潮气、蟑螂进入。仓门闭合力度由舵机角度拟合,避免夹伤猫咪胡须。
日志/联网层
- Wi‑Fi连接家用路由器,通过MQTT协议上报主题
catfeeder/event(JSON:时间、出粮克数、余量百分比),并订阅catfeeder/cmd接收远程喂食、紧急停止等指令。 - 本地存储最近20条喂食记录于ESP32的Flash模拟EEPROM,断网不丢数据,重连后补传。
物料清单
| 物料名称 | 数量 | 用途 | 估算单价(元) | 小计(元) |
|---|---|---|---|---|
| ESP32‑WROOM‑32D开发板 | 1 | 主控,Wi‑Fi+蓝牙 | 18 | 18 |
| 28BYJ‑48步进电机+ULN2003驱动板 | 1 | 螺旋出粮动力 | 8 | 8 |
| SG90微型舵机 | 1 | 出粮口挡板开合 | 5 | 5 |
| 槽型光电传感器 | 1 | 计数落粮颗粒 | 3 | 3 |
| 红外接近传感器模块 | 1 | 检测猫咪靠近 | 4 | 4 |
| 干簧管+小磁铁 | 1套 | 桶盖开关检测 | 2 | 2 |
| 5V/2A电源适配器+DC口母座 | 1 | 系统供电 | 10 | 10 |
| 储粮桶(3L密封米桶改造) | 1 | 主体结构 | 12 | 12 |
| 螺旋杆+亚克力管(定做) | 1套 | 送料通道 | 8 | 8 |
| 杜邦线、热缩管、螺丝、铜柱 | 若干 | 接线与固定 | 5 | 5 |
| 食品级硅胶软管(出粮口) | 1段 | 导流 | 3 | 3 |
| 合计 | 78 |
合计78元,剩余12元用作结构打印或补充线材,满足90元内硬约束。所有物料可从电商平台单件包邮购得,无需批量采购。
接线与结构
接线说明(GPIO完全按给定微调)
- 步进电机驱动板 IN1→GPIO25、IN2→GPIO26、IN3→GPIO27、IN4→GPIO14,共4线。ULN2003供电接5V。
- 舵机信号线→GPIO13,电源由5V供电。
- 槽型光电信号输出→GPIO32(带内部上拉),用于计数。
- 红外接近传感器OUT→GPIO33(可中断唤醒)。
- 干簧管一端接GND,另一端→GPIO34,使能内部上拉,触发低电平。
- MQTT走Wi‑Fi,无需额外接线。
微调理由:原给定引脚适用于步进和舵机,增加了3个传感器输入并选用闲置的ADC1通道,避免与Wi‑Fi共用的ADC2冲突,保证Wi‑Fi稳定。
结构装配:
储粮桶底部打孔,垂直安装亚克力管作为螺旋套筒,步进电机通过联轴器与螺旋杆连接。出料口侧方开窗,前方固定舵机及半圆挡板。光电传感器横跨出料口,红外朝食盆方向安装。主控板与驱动板固定在桶外侧防水盒内。整个电路仅一根电源线外露,整洁安全。
核心代码
以下提供Arduino骨架,基于PlatformIO/Arduino IDE均可编译。已包含Wi‑Fi连接、MQTT、步进电机控制、舵机防潮、掉粮计数及定时喂食核心逻辑。
#include <WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <EEPROM.h>
// 步进电机引脚
#define IN1 25
#define IN2 26
#define IN3 27
#define IN4 14
// 舵机
#define SERVO_PIN 13
// 传感器
#define PHOTO_PIN 32
#define IR_PIN 33
#define REED_PIN 34
// WiFi与MQTT
const char* ssid = "yourSSID";
const char* password = "yourPASS";
const char* mqtt_server = "broker.emqx.io";
WiFiClient espClient;
// 步进电机步序
const int step_seq[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}
};
int step_phase = 0;
Ticker feedTicker;
bool feeding_flag = false;
int grain_count = 0;
// 舵机角度
void setDoor(bool open) {
if(open) {
// 打开挡板角度,需实测调整
for(int angle=0; angle<=90; angle++) {
int pulse = map(angle,0,180,500,2400);
digitalWrite(SERVO_PIN,HIGH);
delayMicroseconds(pulse);
digitalWrite(SERVO_PIN,LOW);
delay(20);
}
} else {
for(int angle=90; angle>=0; angle--) {
int pulse = map(angle,0,180,500,2400);
digitalWrite(SERVO_PIN,HIGH);
delayMicroseconds(pulse);
digitalWrite(SERVO_PIN,LOW);
delay(20);
}
}
}
// 步进电机转一圈(2048步)
void stepMotor(int rounds) {
for(int r=0; r<rounds; r++) {
for(int i=0; i<2048; i++) {
for(int pin=0; pin<4; pin++) {
digitalWrite(IN1+pin, step_seq[step_phase][pin]);
}
step_phase = (step_phase+1)%8;
delay(2);
}
}
}
// 喂食执行
void executeFeeding(int gram) {
feeding_flag = true;
setDoor(true);
// 每圈约出粮3g,根据实际校准
int rounds = gram / 3;
stepMotor(rounds);
// 计数值清零,等待传感器新计数
grain_count = 0;
delay(500);
setDoor(false);
feeding_flag = false;
// 上报MQTT
String msg = "{\"event\":\"fed\",\"gram\":"+String(gram)+"}";
client.publish("catfeeder/event", msg.c_str());
}
// 定时喂食回调
void onTimerFeed() {
// 示例:默认早上8点、晚上20点各一次,每次出粮20g
executeFeeding(20);
}
// MQTT回调处理远程指令
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/cmd") {
if(msg.indexOf("feed")>=0) {
executeFeeding(20);
} else if(msg.indexOf("stop")>=0) {
// 紧急停止
feeding_flag = false;
setDoor(false);
}
}
}
void reconnect() {
while(!client.connected()) {
if(client.connect("ESP32CatFeeder")) {
client.subscribe("catfeeder/cmd");
} else {
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
// 引脚初始化
pinMode(SERVO_PIN,OUTPUT);
pinMode(IR_PIN,INPUT);
WiFi.begin(ssid, password);
while(WiFi.status()!=WL_CONNECTED) delay(500);
client.setCallback(callback);
// 设置定时喂食,每天8:00和20:00,需结合NTP实现,此处用Ticker模拟周期
// 实际应使用ESP32 RTC定时器唤醒,这里简化演示
feedTicker.attach(43200, onTimerFeed); // 12小时周期,仅演示
}
void loop() {
if(!client.connected()) reconnect();
client.loop();
// 落粮计数
if(digitalRead(PHOTO_PIN)==LOW && feeding_flag) {
grain_count++;
delay(20); // 消抖
}
// 红外检测猫咪靠近,可触发拍照或计数
if(digitalRead(IR_PIN)==LOW) {
// 可扩展
}
// 桶盖状态上报
static bool last_reed = HIGH;
bool now_reed = digitalRead(REED_PIN);
if(last_reed != now_reed) {
String status = now_reed?"closed":"open";
client.publish("catfeeder/event", ("{\"lid\":\""+status+"\"}").c_str());
last_reed = now_reed;
}
}
调试步骤
- 电源检测:仅给ESP32供电,观察电源指示灯,串口打印Wi‑Fi连接成功标志,确保无短路。
- 电机空载测试:断开螺旋杆联轴,烧录代码,通过MQTT发送
{"feed":1},观察步进电机是否按2048步/圈正转,是否可正反转校准。 - 舵机行程标定:手动修改代码中0‑90°对应脉冲,观察挡板能否完全遮闭出粮口且无卡阻,记录最佳角度。
- 传感器验证:遮蔽槽型光电,串口输出计数中断;手靠近红外,观察输出电平变化;打开桶盖,MQTT能收到
lid:open消息。 - 出粮量校准:装满干粮,执行一次喂食20g指令,称量实际落粮克数,反算每圈克数,修改
gram/3中的系数,重复3次取均值。 - 长时间运行:设置每日2次定时喂食,连续运行48小时,检查MQTT记录是否遗漏、电机是否丢步、结构是否松脱。
设计图
猫咪自动喂食器结构flow
1
感知输入(光电计数/红外/干簧管)
→
2
控制处理(ESP32 定时&MQTT)
→
3
执行反馈(步进电机出粮/舵机防潮)
→
4
数据上报(MQTT 喂食事件)
感知输入 --> 控制处理 --> 执行反馈
执行反馈 --> 感知输入 (计数反馈)
控制处理 --> 数据上报