基于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识别、多宠物管理等高级功能,为智能家居和宠物护理设备开发提供了有价值的参考案例。

相关推荐
中科岩创4 小时前
某地公园桥梁自动化监测服务项目
大数据·人工智能·物联网·自动化
Hy行者勇哥4 小时前
物联网工控一体机操作系统选型:安卓、Ubuntu、Debian 场景化决策指南
android·物联网·ubuntu
清风6666665 小时前
基于单片机的多模式智能洗衣机设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
点灯小铭5 小时前
基于单片机的预约保温型智能电饭锅控制系统设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
北京耐用通信7 小时前
冶金车间“迷雾”重重?耐达讯自动化Profibus转光纤为HMI点亮“透视眼”!
人工智能·物联网·网络协议·网络安全·自动化
北京耐用通信7 小时前
耐达讯自动化Profibus光纤模块:智能仪表的“生命线”,极端环境通信无忧!
人工智能·物联网·网络协议·自动化·信息与通信
兆龙电子单片机设计7 小时前
【STM32项目开源】STM32单片机物联网门禁控制系统
stm32·单片机·物联网·开源·自动化
q_19132846958 小时前
基于SpringBoot+Vue2的美食菜谱美食分享平台
java·spring boot·后端·计算机·毕业设计·美食
塔能物联运维9 小时前
物联网运维中的自适应DNS解析优化与动态负载均衡技术
运维·物联网·负载均衡