一、项目概述
本项目旨在通过软硬件结合的方式,设计并实现一个基于ESP32的智能宠物喂食系统。该系统能够实现远程控制、定时投喂、余粮监测等功能,为宠物主人提供便捷的宠物喂养解决方案,广泛应用于家庭宠物喂养、宠物店管理等场景。
技术栈关键词
硬件:ESP32主控、舵机/步进电机、重量传感器、红外传感器、OLED显示屏
软件:python(Arduino框架)、WiFi/蓝牙通信、移动端APP/微信小程序
云端:MQTT协议、云平台数据存储
核心功能:远程控制、定时喂养、余粮监测、进食统计
二、系统架构
系统架构设计
本系统的硬件架构以ESP32作为控制核心,包含投食机构、传感器模块、显示模块和通信模块。系统支持本地控制和远程云端控制两种模式。
系统架构图:

组件选择
ESP32主控:集成WiFi和蓝牙功能,性能强大,适合物联网应用
投食机构:SG90舵机或28BYJ48步进电机,控制出粮量
传感器模块:HX711+称重传感器:监测余粮量,HCSR501红外传感器:检测宠物接近, DHT11温湿度传感器:环境监测
显示模块:0.96寸OLED显示屏,I2C接口,通信模块:支持WiFi和蓝牙双模通信
三、环境搭建和注意事项
环境搭建
硬件连接:
舵机/步进电机 → ESP32 PWM/GPIO引脚, HX711重量传感器 → ESP32 GPIO引脚,OLED显示屏 → ESP32 I2C接口, 红外传感器 → ESP32 GPIO引脚
软件环境:
开发环境:Arduino IDE或PlatformIO
必要库文件:WiFi.h、WebServer.h(网络功能), PubSubClient.h(MQTT通信), Adafruit_GFX.h、Adafruit_SSD1306.h(OLED显示),HX711.h(重量传感器),Servo.h(舵机控制)
注意事项
-
确保机械结构牢固,防止宠物破坏
-
定期清洁投食通道,防止粮食堵塞
-
保持重量传感器校准,确保余粮监测准确
-
网络连接不稳定时应有本地备用方案
-
电源供应稳定,建议使用适配器供电
四、代码实现过程
- 系统初始化模块
python
cpp
include <WiFi.h>
include <PubSubClient.h>
include <Wire.h>
include <Adafruit_GFX.h>
include <Adafruit_SSD1306.h>
include <HX711.h>
include <Servo.h>
// 硬件引脚定义
define SERVO_PIN 12
define LOADCELL_DOUT_PIN 16
define LOADCELL_SCK_PIN 4
define IR_SENSOR_PIN 5
define DHT_PIN 15
// 全局变量和对象
Servo feedServo;
HX711 scale;
Adafruit_SSD1306 display(128, 64, &Wire, 1);
// WiFi和MQTT配置
const char* ssid = "Your_WiFi_SSID";
const char* password = "Your_WiFi_Password";
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
// 系统状态变量
float currentFoodWeight = 0.0;
bool petDetected = false;
int feedingSchedule[3] = {8, 13, 19}; // 默认喂食时间
void setup() {
Serial.begin(115200);
// 初始化各模块
initHardware();
initWiFi();
initMQTT();
initDisplay();
Serial.println("系统初始化完成");
}
- 硬件初始化模块
python
// 硬件初始化函数
void initHardware() {
// 舵机初始化
feedServo.attach(SERVO_PIN);
feedServo.write(0); // 初始位置
// 重量传感器初始化
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(2280.f); // 校准值,需要实际校准
scale.tare(); // 清零
// 传感器引脚初始化
pinMode(IR_SENSOR_PIN, INPUT);
// 读取初始余粮
currentFoodWeight = getFoodWeight();
}
// 获取余粮重量
float getFoodWeight() {
if (scale.is_ready()) {
float weight = scale.get_units(5); // 读取5次取平均
return weight > 0 ? weight : 0.0;
}
return 0.0;
}
// 检测宠物接近
bool checkPetPresence() {
return digitalRead(IR_SENSOR_PIN) == HIGH;
}
- 网络通信模块
python
// WiFi初始化
void initWiFi() {
WiFi.begin(ssid, password);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("连接WiFi...");
display.display();
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(1000);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi连接成功");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
}
}
// MQTT初始化
void initMQTT() {
client.setServer(mqtt_server, 1883);
client.setCallback(mqttCallback);
}
// MQTT回调函数
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("收到消息: ");
Serial.print(topic);
Serial.print(" ");
Serial.println(message);
// 处理喂食指令
if (String(topic) == "petfeeder/feed") {
if (message == "NOW") {
feedPet(1); // 默认喂食1份
}
}
// 处理设置喂食时间
else if (String(topic) == "petfeeder/schedule") {
setFeedingSchedule(message);
}
}
// 设置喂食时间表
void setFeedingSchedule(String schedule) {
// 解析时间表字符串,格式:"8,13,19"
int index = 0;
int timeIndex = 0;
while (schedule.length() > 0 && timeIndex < 3) {
int commaIndex = schedule.indexOf(',');
if (commaIndex == 1) {
feedingSchedule[timeIndex] = schedule.toInt();
break;
}
feedingSchedule[timeIndex] = schedule.substring(0, commaIndex).toInt();
schedule = schedule.substring(commaIndex + 1);
timeIndex++;
}
Serial.println("喂食时间表已更新");
}
- 喂食控制模块
python
// 喂食函数
void feedPet(int portions) {
if (currentFoodWeight < 10.0) { // 余粮不足检查
Serial.println("余粮不足,请添加粮食");
sendAlert("FOOD_LOW");
return;
}
Serial.print("开始喂食,份数: ");
Serial.println(portions);
for (int i = 0; i < portions; i++) {
// 控制舵机旋转出粮
feedServo.write(90);
delay(1000);
feedServo.write(0);
delay(500);
// 更新余粮量
currentFoodWeight = getFoodWeight();
// 发送喂食记录
sendFeedingRecord();
delay(1000);
}
Serial.println("喂食完成");
}
// 检查定时喂食
void checkScheduledFeeding() {
int currentHour = getCurrentTime().toInt();
for (int i = 0; i < 3; i++) {
if (currentHour == feedingSchedule[i]) {
// 避免重复喂食
static int lastFedHour = 1;
if (lastFedHour != currentHour) {
feedPet(1);
lastFedHour = currentHour;
}
break;
}
}
}
// 获取当前时间(简化版)
String getCurrentTime() {
// 实际应用中应从NTP服务器获取时间
return String((millis() / 3600000) % 24); // 模拟小时
}
- 数据显示模块
python
// 显示初始化
void initDisplay() {
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306分配失败"));
for(;;);
}
display.display();
delay(2000);
display.clearDisplay();
}
// 更新显示
void updateDisplay() {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
// 显示余粮信息
display.print("余粮: ");
display.print(currentFoodWeight);
display.println(" g");
// 显示网络状态
display.print("WiFi: ");
display.println(WiFi.status() == WL_CONNECTED ? "已连接" : "断开");
// 显示宠物检测状态
display.print("宠物: ");
display.println(petDetected ? "检测到" : "无");
// 显示下次喂食时间
display.print("下次喂食: ");
display.print(getNextFeedingTime());
display.println("时");
display.display();
}
// 获取下次喂食时间
int getNextFeedingTime() {
int currentHour = getCurrentTime().toInt();
for (int i = 0; i < 3; i++) {
if (feedingSchedule[i] > currentHour) {
return feedingSchedule[i];
}
}
return feedingSchedule[0]; // 返回第二天第一次喂食时间
}
- 数据上报模块
python
// 发送喂食记录
void sendFeedingRecord() {
if (client.connected()) {
String record = "{\"time\":\"" + String(millis()) +
"\",\"weight\":" + String(currentFoodWeight) +
"}";
client.publish("petfeeder/records", record.c_str());
}
}
// 发送警报
void sendAlert(String alertType) {
if (client.connected()) {
String alert = "{\"type\":\"" + alertType +
"\",\"time\":\"" + String(millis()) +
"\"}";
client.publish("petfeeder/alerts", alert.c_str());
}
}
// 发送状态更新
void sendStatusUpdate() {
if (client.connected()) {
String status = "{\"food_weight\":" + String(currentFoodWeight) +
",\"pet_detected\":" + String(petDetected) +
",\"next_feeding\":" + String(getNextFeedingTime()) +
"}";
client.publish("petfeeder/status", status.c_str());
}
}
- 主循环模块
python
void loop() {
// 维护MQTT连接
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
// 更新传感器数据
currentFoodWeight = getFoodWeight();
petDetected = checkPetPresence();
// 检查定时喂食
checkScheduledFeeding();
// 更新显示
updateDisplay();
// 定期发送状态更新
static unsigned long lastStatusUpdate = 0;
if (millis() lastStatusUpdate > 30000) { // 每30秒
sendStatusUpdate();
lastStatusUpdate = millis();
}
// 低粮警报
if (currentFoodWeight < 20.0) {
static unsigned long lastAlertTime = 0;
if (millis() lastAlertTime > 60000) { // 每分钟提醒一次
sendAlert("FOOD_LOW");
lastAlertTime = millis();
}
}
delay(1000);
}
// 重连MQTT
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("尝试MQTT连接...");
if (client.connect("ESP32PetFeeder")) {
Serial.println("连接成功");
// 订阅主题
client.subscribe("petfeeder/feed");
client.subscribe("petfeeder/schedule");
} else {
Serial.print("失败,rc=");
Serial.print(client.state());
Serial.println(" 5秒后重试");
delay(5000);
}
}
}
五、项目总结
本项目成功设计并实现了一个基于ESP32的智能宠物喂食系统,通过软硬件结合的方式,展示了物联网技术在宠物护理领域的实际应用。系统具备远程控制、智能定时、状态监测等核心功能,为宠物主人提供了便捷科学的喂养解决方案。
主要功能
-
智能喂食控制:支持远程手动控制和预设时间自动喂食
-
余粮监测:实时监测粮食存量,低粮时自动提醒
-
宠物检测:红外传感器检测宠物接近情况
-
状态显示:OLED屏幕实时显示系统状态
-
云端通信:通过MQTT协议实现与移动端的双向通信
-
数据统计:记录喂食历史和宠物进食情况
技术创新点
-
多模态控制:支持本地自动控制和远程手动控制相结合
-
智能传感:重量传感器和红外传感器的协同工作
-
低功耗设计:ESP32的睡眠模式优化,降低能耗
-
模块化架构:各功能模块独立设计,便于维护扩展
-
用户友好:简洁的移动端界面和实时状态反馈
本项目通过完整的物联网系统开发流程,帮助开发者深入理解嵌入式系统设计、传感器应用、无线通信和云平台集成等技术。系统具有良好的实用价值和扩展性,可根据需要添加摄像头监控、AI识别、多宠物管理等高级功能,为智能家居和宠物护理设备开发提供了有价值的参考案例。