💡 划重点

  • 主控选用ESP32,成本低、联网快,完美承接定时投喂与远程管理
  • 出粮机构用步进电机带动螺旋杆,定量精准、卡粮概率低
  • 出口开合用舵机控制门板,防潮防虫,闲置时闭合
  • 联网全走MQTT,手机随时查看进食记录、手动补喂,断网也能按本地定时执行
  • 硬件总成本控制在90元内,全部使用通用模块,自己就能组装和维修

需求洞察

目标用户:朝九晚六的上班族猫主、经常短途出差但不想寄养的人群、家里有多只猫需要分餐控制的家庭。

真实痛点

  1. 加班或堵车时无法准时喂食,猫饿到吐黄水,长期会引发肠胃病。
  2. 传统机械定时喂食器出粮量不准,容易卡粮,且无法远程确认“究竟有没有出粮”。
  3. 普通喂食器没有防虫防潮设计,南方回南天时猫粮变软发霉,猫拒食甚至中毒。
  4. 宠物医院建议少食多餐,但人工操作难以严格执行,自动定时能显著降低肥胖和泌尿问题风险。

为什么值得做:用不到一顿火锅的成本,解决猫最基础的生存需求,出差两天也不用麻烦邻居。主板自带联网能力,未来还能扩展摄像头、称重传感器,硬件和软件的二次开发空间都非常大,完全可作为智能家居的入门实战项目。

方案设计

感知层

控制层

执行层

日志 / 联网层

物料清单

序号 物料名称 数量 用途 估算单价(元)
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 可直接编译的骨架代码,使用 WiFiPubSubClientESP32Servo 库,步进电机采用自定义时序,无需额外库。


#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,不影响骨架结构。

调试步骤

  1. 硬件分步测试:先不装粮,单独测试步进电机,用示例代码让它正反转 5 圈,观察是否丢步。
  2. 舵机校准:给舵机接上电源,在 setup() 中改角度,检查开门 90° 和关门 0° 是否与结构匹配,必要时微调联杆长度。
  3. WiFi 与 MQTT 联通:打开串口监视器,复位后查看 WiFi 连接状态,再用 MQTT 调试工具发送 catfeeder/feed1,板载 LED 应有相应闪烁且电机动。
  4. 空载全流程跑通:不装粮食,模拟定时触发和按键触发,记录出口门板动作与步进电机旋转是否同频,确认延时合理。
  5. 装粮定量测试:装入猫粮,连续执行 10 次喂食指令,用厨房秤称量每次出粮重量,调整步进步数以逼近理想单份克数。
  6. 长期运行:至少连续运行 24 小时,观察是否有内存泄漏(heap_caps_get_free_size 打印剩余堆),确保不会死机。

设计图

猫咪自动喂食器结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报