基于ESP32的宠物喂食小屋

一、项目概述

本项目旨在通过软硬件结合的方式,设计并实现一个基于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(舵机控制)

注意事项

  1. 确保机械结构牢固,防止宠物破坏

  2. 定期清洁投食通道,防止粮食堵塞

  3. 保持重量传感器校准,确保余粮监测准确

  4. 网络连接不稳定时应有本地备用方案

  5. 电源供应稳定,建议使用适配器供电

四、代码实现过程

  1. 系统初始化模块
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("系统初始化完成");
}
  1. 硬件初始化模块
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;
}
  1. 网络通信模块
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("喂食时间表已更新");
}
  1. 喂食控制模块
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); // 模拟小时
}
  1. 数据显示模块
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]; // 返回第二天第一次喂食时间
}
  1. 数据上报模块
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());
  }
}
  1. 主循环模块
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的智能宠物喂食系统,通过软硬件结合的方式,展示了物联网技术在宠物护理领域的实际应用。系统具备远程控制、智能定时、状态监测等核心功能,为宠物主人提供了便捷科学的喂养解决方案。

主要功能

  1. 智能喂食控制:支持远程手动控制和预设时间自动喂食

  2. 余粮监测:实时监测粮食存量,低粮时自动提醒

  3. 宠物检测:红外传感器检测宠物接近情况

  4. 状态显示:OLED屏幕实时显示系统状态

  5. 云端通信:通过MQTT协议实现与移动端的双向通信

  6. 数据统计:记录喂食历史和宠物进食情况

技术创新点

  1. 多模态控制:支持本地自动控制和远程手动控制相结合

  2. 智能传感:重量传感器和红外传感器的协同工作

  3. 低功耗设计:ESP32的睡眠模式优化,降低能耗

  4. 模块化架构:各功能模块独立设计,便于维护扩展

  5. 用户友好:简洁的移动端界面和实时状态反馈

本项目通过完整的物联网系统开发流程,帮助开发者深入理解嵌入式系统设计、传感器应用、无线通信和云平台集成等技术。系统具有良好的实用价值和扩展性,可根据需要添加摄像头监控、AI识别、多宠物管理等高级功能,为智能家居和宠物护理设备开发提供了有价值的参考案例。

相关推荐
计算机毕业编程指导师3 小时前
【大数据毕设选题推荐】基于Spark的WTA职业网球赛事演变与竞技格局分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·计算机·spark·毕业设计·课程设计·wta网球
YCOSA20254 小时前
雨晨 Windows 11 IoT 企业版 Edge 轻装 VCDX 29680.1000
windows·物联网
计算机毕业编程指导师5 小时前
大数据毕设怎么做?基于Hadoop的多源社交媒体心理健康情感分析与可视化系统从零到一指导 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·计算机·数据分析·毕业设计·课程设计·媒体
计算机毕业编程指导师6 小时前
Python大数据毕设:基于Hadoop的病毒式社交媒体趋势和参与度分析系统怎么做 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·毕业设计·课程设计·社交媒体
计算机毕业编程指导师6 小时前
【计算机毕设选题推荐】基于Spark与Hadoop的AI就业收入区域差异分析系统 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·数据分析·spark·毕业设计·课程设计·ai就业收入
lzqrzpt7 小时前
临沂LED驱动电源工程选型标准与工艺对比解析
python·单片机·嵌入式硬件·物联网
vx_Biye_Design7 小时前
springboot宠物寄养服务预约与监管系统82684-计算机课程设计、毕业设计
java·vue.js·spring boot·elasticsearch·课程设计·express·宠物
microrain8 小时前
权限改了,接口立刻生效,菜单要等重新登录:SagooIoT 权限体系的四道闸门
物联网·golang·开源·sagooiot
企业数字化笔记8 小时前
视频像素分割怎么选?HSV 阈值、传统掩膜、语义分割和实例分割的效果与代价
opencv·音视频
vx_Biye_Design9 小时前
springboot宠物领养与救助平台64334-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·mysql·课程设计·宠物