基于STM32的可编程自动宠物喂食系统设计
项目开发背景
随着现代生活节奏加快,越来越多宠物主人面临因工作繁忙或短期外出导致的喂养不便问题。传统手动喂食方式难以保障宠物饮食规律性,而市面基础定时喂食器又缺乏远程交互和智能调节能力,极易出现余粮不足未被及时发现、喂食量不符合宠物实际需求等情况,直接影响宠物健康。
物联网技术与智能家居的快速发展为宠物用品智能化提供了技术基础。通过集成云端数据同步、语音控制及自适应算法,可构建更符合现代养宠需求的解决方案。该系统不仅能实现精准定时投喂和远程应急补粮,更能通过分析历史进食数据动态优化喂食策略,解决人工喂养的主观性和不稳定性问题。
本设计响应宠物健康管理的精细化需求,结合STM32的实时控制能力、华为云的可靠数据同步以及离在线混合交互模式,旨在打造一款具备智能决策、异常预警及多端协同功能的喂食系统。其开发不仅满足养宠家庭的核心痛点,也为宠物智能硬件领域提供了可扩展的技术框架。
设计实现的功能
(1)基于STM32F103C8T6主控实现系统核心控制与逻辑处理
(2)通过海凌科V20离线语音模块接收本地语音指令触发投喂
(3)使用28BYJ-48步进电机+ULN2003驱动板控制出粮机构执行投喂动作
(4)利用HX711+压力传感器实时监测储粮桶重量并计算余粮
(5)0.96寸OLED显示屏通过SPI接口本地显示时间/余粮/喂食记录
(6)ESP8266模块连接华为云,基于MQTT协议实现远程指令收发与数据同步
(7)高电平触发蜂鸣器在余粮低于阈值时发出声光报警
(8)RTC实时时钟模块支持多组定时喂食计划自动执行
(9)Qt for Android开发APP,支持远程手动投喂/记录查询/语音指令下发
(10)Qt5+C++开发上位机软件,实现喂食策略配置与历史数据分析
项目硬件模块组成
(1)主控芯片:STM32F103C8T6
(2)语音识别模块:海凌科 V20 离线语音模块
(3)喂食机构:28BYJ-48步进电机 + ULN2003驱动板
(4)粮量检测:HX711模块 + 压力传感器模块(电阻式)
(5)显示模块:0.96寸OLED显示屏(SPI接口)
(6)通信模块:ESP8266模块,连接华为云,MQTT协议
(7)报警模块:高电平触发蜂鸣器提示余粮不足
(8)时间控制:基于RTC实时时钟定时投喂
设计意义
该宠物喂食系统的设计意义主要体现在以下方面:
解决现代人因工作繁忙导致的宠物喂养难题是该系统的核心价值。通过STM32主控精准协调定时喂食与远程手动控制功能,用户即使外出也能通过手机APP远程触发喂食,结合RTC时钟确保每日定时投喂,有效避免宠物因主人行程变动而挨饿,保障宠物饮食规律性。
提升宠物喂养的科学性与健康管理水平是系统的智能化体现。压力传感器与HX711模块实时监测余粮量并在不足时触发蜂鸣器报警,避免断粮风险;系统通过分析历史投喂数据,自动学习宠物进食习惯并动态调整喂食量,既防止过度投喂又满足营养需求,实现个性化科学喂养。
构建全方位状态监控与数据追溯体系增强了系统的可靠性。本地OLED屏实时显示余粮量、投喂记录等关键状态,便于用户现场查看;同时ESP8266模块通过MQTT协议将数据同步至华为云,配合Qt开发的APP及上位机软件,用户可随时随地查询历史喂食记录、调整参数,形成完整的云端数据链,为宠物健康管理提供依据。
融合多技术模块实现人性化交互提升了用户体验。离线语音模块支持APP语音指令控制,解放用户双手;步进电机驱动机构确保投粮精准可控;本地显示与云端双备份机制强化了系统容错能力。整套硬件选型兼顾成本与可靠性,体现了嵌入式系统在智能家居领域的实用价值。
通过技术手段传递人文关怀是系统的深层意义。将物联网、语音识别、自适应算法等技术应用于宠物喂养场景,既缓解了饲养者的后顾之忧,又保障了宠物的生存福利,体现了科技对生活品质的提升,强化了人与宠物之间的情感联结。
设计思路
设计思路
系统以STM32F103C8T6为核心控制器,协调各模块实现智能化喂食管理。通过实时时钟(RTC)模块精确计时,支持预设多个定时喂食任务。用户可通过Qt开发的Android APP远程触发手动喂食指令,指令经华为云平台以MQTT协议传输至ESP8266通信模块,再由主控解析执行。
粮量监测采用电阻式压力传感器与HX711模块组合,实时采集储粮箱重量数据。当余粮低于阈值时,STM32触发蜂鸣器报警,并通过OLED屏显示警告图标。同时,系统将粮量状态同步至云端,供APP和上位机监控。
语音控制通过海凌科V20模块实现:用户说出预设指令(如"喂食")后,模块通过串口将指令码发送至STM32,主控立即驱动ULN2003步进电机驱动板,带动28BYJ-48步进电机旋转特定角度,控制出粮口开合实现定量投喂。投喂量可基于历史进食数据动态调整——系统记录每日消耗量,通过算法平滑优化后续单次投喂量。
本地交互由SPI接口的0.96寸OLED屏承担,实时显示时间、余粮百分比、下次喂食倒计时及网络状态。所有操作日志(如喂食时间、触发方式、粮量变化)均通过ESP8266上传至华为云,Qt5开发的上位机软件可调取云端数据生成喂食报表,支持远程修改定时参数。
主程序采用状态机架构:常态下轮询检测传感器数据、云端指令和语音输入;到达定时节点或收到外部指令时,中断当前任务执行喂食动作,确保系统响应实时性。硬件模块间通过UART、I2C和GPIO接口通信,低功耗设计延长电池供电场景的使用时长。
框架图
系统框架图
+-----------------------------------------------------------------------------------------+
| STM32F103C8T6 (主控) |
| +-------------------+ +-----------------+ +-----------------+ +-------------------+ |
| | RTC实时时钟 | | GPIO控制 | | SPI接口 | | UART串口通信 | |
| | (内部/外部晶振) | | (蜂鸣器控制) | | (OLED显示驱动) | | (多路通信枢纽) | |
| +-------------------+ +--------+--------+ +--------+--------+ +-------+-------+----+ |
| | | | | | |
+---------|-----------------------|-------------------|-------------------|-------|-------+
| | | | |
| (时间基准) | (报警触发) | (状态显示) | | (配置指令)
+---------|-----------+ +--------|------+ +--------|------+ +-------|-------+ +-----|-------+
| 定时喂食逻辑 | | 蜂鸣器 | | OLED显示屏 | | 海凌科V20 | | ESP8266 |
| (RTC触发喂食任务) | | (粮量不足报警)| | (0.96寸 SPI) | | 离线语音模块 | | WiFi模块|
+---------+-----------+ +---------------+ +---------------+ +---------+---------+ +----+----+
| | |
| (电机控制指令) | (语音指令解析) | (MQTT协议)
+---------|-------------------+ +--------+ |
| 喂食执行子系统 | | |
| +----------------+ | +---------|--------|--------+
| | ULN2003 | <------+ | 华为云IoT平台 |
| | 驱动板 | | (数据存储/指令转发) |
| +------+---------+ +------------+-----------+
| | |
| +------|---------+ |
| | 28BYJ-48 | |
| | 步进电机 | |
| +------+---------+ |
| | |
| +------|---------+ |
| | 储粮仓/投食机构| |
| +----------------+ |
+------------------------------------------------------------------------------------+
| |
+---------|---------+ +-----------|-----------+
| 粮量检测子系统 | | 远程控制终端 |
| +----------------+| | +-------------------+ |
| | 压力传感器 || <----------------粮量反馈--------------------------| | Android APP | |
| | (底部称重) || | | (Qt for Android) | |
| +--------+-------+| | +-------------------+ |
| | | | +-------------------+ |
| +--------|--------+| | | 上位机软件 | |
| | HX711 || | | (Qt5 + C++) | |
| | 称重模块 || | +-------------------+ |
| +-----------------+| +-----------------------+
+-------------------+
关键交互说明:
- 核心控制:STM32通过RTC定时触发喂食任务,或通过UART接收语音/WiFi的远程指令。
- 执行层:
- ULN2003驱动步进电机转动,控制投食机构出粮。
- HX711+压力传感器实时监测余粮量,触发蜂鸣器报警。
- 交互层:
- OLED显示时间、粮量、系统状态(SPI通信)。
- 海凌科V20解析语音指令(如“放粮”),通过UART发送指令到STM32。
- 云端链路:
- ESP8266通过MQTT协议连接华为云,同步喂食记录、粮量数据。
- Android APP/上位机软件通过云端下发喂食指令或配置定时任务。
- 自适应逻辑:
- STM32分析历史投食数据(存储于华为云),动态调整单次投食量。
系统总体设计
系统总体设计基于STM32F103C8T6主控芯片构建,核心功能包括定时喂食、远程控制、余粮监测与智能调节。主控通过I/O接口协调各模块:海凌科V20离线语音模块接收语音指令,解析后触发喂食动作;28BYJ-48步进电机配合ULN2003驱动板执行出粮操作,通过控制电机旋转圈数精准调节喂食量。
粮量检测由HX711模块连接电阻式压力传感器实现,实时监测储粮仓重量变化,当余粮低于阈值时触发高电平蜂鸣器报警。RTC实时时钟模块提供精确计时,支撑每日多时段定时喂食任务。系统具备学习能力,通过分析历史喂食数据与余粮变化趋势,动态优化单次投喂量。
本地交互采用0.96寸OLED显示屏(SPI接口),实时展示余粮状态、喂食计划及系统报警信息。网络通信由ESP8266模块负责,通过MQTT协议连接华为云,实现喂食记录同步与远程指令收发。Qt for Android开发的APP支持手动喂食指令下发及数据查看,同时上位机通过Qt5+C++实现远程配置与统计分析。所有硬件模块通过主控统一调度,确保定时任务、语音控制、云端交互等功能协同运作。
系统功能总结
功能描述 | 实现方式(硬件/软件) |
---|---|
定时喂食功能 | STM32主控通过RTC实时时钟定时触发步进电机转动,驱动喂食机构投放饲料 |
手动远程喂食功能 | ESP8266模块接收APP指令(MQTT协议),触发STM32控制步进电机投喂 |
余粮检测与报警 | HX711+压力传感器实时监测重量,余粮不足时STM32触发蜂鸣器报警 |
APP语音控制投喂 | Android APP语音指令→华为云→ESP8266→STM32执行;海凌科V20支持本地离线语音指令直控 |
智能调整喂食量 | STM32记录进食数据,通过算法分析习惯动态调整步进电机转动时长(投喂量) |
本地状态显示 | 0.96寸OLED实时显示余粮/时间/下次投喂计划(SPI通信) |
云端数据同步 | ESP8266上传喂食记录/余粮量至华为云(MQTT),Qt Android APP远程查看/配置 |
系统配置管理 | Qt5上位机软件远程修改定时计划、喂食量参数,数据双向同步 |
设计的各个功能模块描述
主控芯片采用STM32F103C8T6,作为系统核心控制器,负责协调各模块工作,处理传感器数据,执行喂食逻辑,并与云端通信。语音识别模块使用海凌科V20离线语音单元,通过串口接收用户语音指令,解析为投喂命令发送至主控芯片,实现APP语音控制功能。
喂食机构由28BYJ-48步进电机和ULN2003驱动板组成,主控芯片通过PWM信号控制步进电机旋转角度,精确驱动投食机构完成定量喂食,支持定时触发与远程手动触发双模式。粮量检测通过HX711模块连接电阻式压力传感器,实时采集储粮仓重量数据,主控芯片计算剩余粮量,低于阈值时触发报警。
显示模块采用0.96寸OLED屏(SPI接口),本地展示系统状态,包括实时时间、剩余粮量、喂食计划及网络连接状态。通信模块基于ESP8266,通过AT指令与主控串口交互,使用MQTT协议连接华为云,实现喂食记录同步和远程指令接收。报警模块由高电平触发蜂鸣器构成,当粮量检测异常时主控输出高电平信号驱动蜂鸣器报警。
时间控制基于STM32内部RTC实时时钟,独立供电维持计时,主控按预设时段自动执行喂食任务。APP软件使用Qt for Android开发,提供喂食记录查询、远程手动投喂及语音指令下发功能。上位机软件采用Qt5+C++实现,通过MQTT协议连接云端,提供喂食参数配置和历史数据分析界面。
上位机代码设计
上位机软件设计(Qt5 + C++)
#include <QtWidgets>
#include <QtMqtt/QtMqtt>
#include <QDateTime>
#include <QJsonObject>
#include <QJsonDocument>
class PetFeederApp : public QMainWindow {
Q_OBJECT
public:
PetFeederApp(QWidget *parent = nullptr) : QMainWindow(parent) {
// 初始化UI
setupUI();
// MQTT客户端初始化
mqttClient = new QMqttClient(this);
mqttClient->setHostname("your_huaweicloud_address.com");
mqttClient->setPort(1883);
mqttClient->setClientId("PetFeeder_PC_" + QString::number(qrand()));
mqttClient->setUsername("device_id");
mqttClient->setPassword("device_secret");
connect(mqttClient, &QMqttClient::connected, this, &PetFeederApp::onMqttConnected);
connect(mqttClient, &QMqttClient::messageReceived, this, &PetFeederApp::onMessageReceived);
// 连接MQTT
mqttClient->connectToHost();
}
private slots:
void onMqttConnected() {
statusLabel->setText("已连接华为云");
mqttClient->subscribe(QMqttTopicFilter("petfeeder/status"));
mqttClient->subscribe(QMqttTopicFilter("petfeeder/foodlog"));
}
void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic) {
QJsonDocument doc = QJsonDocument::fromJson(message);
QJsonObject json = doc.object();
if (topic.name() == "petfeeder/status") {
updateStatusDisplay(json);
} else if (topic.name() == "petfeeder/foodlog") {
addFeedingRecord(json);
}
}
void onManualFeed() {
QMqttTopicName topic("petfeeder/control");
QJsonObject cmd = {{"cmd", "manual_feed"}, {"amount", feedAmountSpin->value()}};
mqttClient->publish(topic, QJsonDocument(cmd).toJson());
}
void onSetSchedule() {
QJsonArray schedules;
for (int i = 0; i < scheduleTable->rowCount(); ++i) {
QTime time = QTime::fromString(scheduleTable->item(i, 0)->text(), "HH:mm");
int amount = scheduleTable->item(i, 1)->text().toInt();
schedules.append(QJsonObject{{"time", time.toString("HH:mm")}, {"amount", amount}});
}
QMqttTopicName topic("petfeeder/schedule");
mqttClient->publish(topic, QJsonDocument(schedules).toJson());
}
private:
void setupUI() {
// 主窗口设置
setWindowTitle("智能宠物喂食系统");
setFixedSize(800, 600);
// 状态显示区域
QGroupBox *statusGroup = new QGroupBox("系统状态");
statusLabel = new QLabel("正在连接云端...");
foodLevelBar = new QProgressBar;
foodLevelBar->setRange(0, 100);
lastFeedLabel = new QLabel("上次喂食: --:--");
QVBoxLayout *statusLayout = new QVBoxLayout;
statusLayout->addWidget(statusLabel);
statusLayout->addWidget(new QLabel("余粮水平:"));
statusLayout->addWidget(foodLevelBar);
statusLayout->addWidget(lastFeedLabel);
statusGroup->setLayout(statusLayout);
// 手动喂食控制
QGroupBox *controlGroup = new QGroupBox("手动控制");
feedAmountSpin = new QSpinBox;
feedAmountSpin->setRange(5, 100);
feedAmountSpin->setSuffix(" g");
QPushButton *feedButton = new QPushButton("立即喂食");
connect(feedButton, &QPushButton::clicked, this, &PetFeederApp::onManualFeed);
QHBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->addWidget(new QLabel("喂食量:"));
controlLayout->addWidget(feedAmountSpin);
controlLayout->addWidget(feedButton);
controlGroup->setLayout(controlLayout);
// 定时计划表
QGroupBox *scheduleGroup = new QGroupBox("喂食计划");
scheduleTable = new QTableWidget(0, 2);
QStringList headers{"时间 (HH:mm)", "喂食量 (g)"};
scheduleTable->setHorizontalHeaderLabels(headers);
QPushButton *addScheduleBtn = new QPushButton("添加计划");
QPushButton *saveScheduleBtn = new QPushButton("保存计划");
connect(addScheduleBtn, &QPushButton::clicked, this, [this](){
scheduleTable->insertRow(scheduleTable->rowCount());
});
connect(saveScheduleBtn, &QPushButton::clicked, this, &PetFeederApp::onSetSchedule);
QVBoxLayout *scheduleLayout = new QVBoxLayout;
scheduleLayout->addWidget(scheduleTable);
QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addWidget(addScheduleBtn);
btnLayout->addWidget(saveScheduleBtn);
scheduleLayout->addLayout(btnLayout);
scheduleGroup->setLayout(scheduleLayout);
// 喂食记录
QGroupBox *historyGroup = new QGroupBox("喂食记录");
recordList = new QListWidget;
QVBoxLayout *historyLayout = new QVBoxLayout;
historyLayout->addWidget(recordList);
historyGroup->setLayout(historyLayout);
// 主布局
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(statusGroup, 0, 0);
mainLayout->addWidget(controlGroup, 1, 0);
mainLayout->addWidget(scheduleGroup, 0, 1, 2, 1);
mainLayout->addWidget(historyGroup, 2, 0, 1, 2);
QWidget *centralWidget = new QWidget;
centralWidget->setLayout(mainLayout);
setCentralWidget(centralWidget);
}
void updateStatusDisplay(const QJsonObject &status) {
foodLevelBar->setValue(status["food_level"].toInt());
lastFeedLabel->setText("上次喂食: " + status["last_feed_time"].toString());
if (status["food_low"].toBool()) {
statusLabel->setText("<font color='red'>余粮不足!</font>");
} else {
statusLabel->setText("系统运行正常");
}
}
void addFeedingRecord(const QJsonObject &record) {
QString entry = QString("%1 | %2 g | %3")
.arg(record["time"].toString())
.arg(record["amount"].toInt())
.arg(record["type"].toString());
recordList->insertItem(0, entry);
}
// UI组件声明
QLabel *statusLabel;
QProgressBar *foodLevelBar;
QLabel *lastFeedLabel;
QSpinBox *feedAmountSpin;
QTableWidget *scheduleTable;
QListWidget *recordList;
// MQTT客户端
QMqttClient *mqttClient;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
PetFeederApp window;
window.show();
return app.exec();
}
#include "main.moc"
代码功能说明
-
云端通信模块
- 使用MQTT协议连接华为云IoT平台
- 订阅主题:
petfeeder/status
:接收设备状态(余粮量、最后喂食时间)petfeeder/foodlog
:接收喂食记录
- 发布主题:
petfeeder/control
:发送手动喂食指令petfeeder/schedule
:发送定时喂食计划
-
核心功能界面
- 系统状态面板:实时显示余粮进度条、连接状态和最后喂食时间
- 手动控制区:设置喂食量并立即触发喂食
- 喂食计划表:支持多时段定时计划配置
- 喂食记录:按时间倒序显示历史喂食记录
-
数据处理
- 使用JSON格式传输数据
- 状态更新:
{"food_level": 45, "last_feed_time": "14:30", "food_low": false}
- 喂食记录:
{"time": "2023-06-15 14:30", "amount": 30, "type": "scheduled"}
-
操作流程
使用说明
-
配置华为云连接
-
修改代码中的MQTT连接参数:
mqttClient->setHostname("your_huaweicloud_address.com"); mqttClient->setUsername("device_id"); mqttClient->setPassword("device_secret");
-
-
定时计划设置
- 在表格中添加/修改行
- 格式:
时间列 (HH:mm)
,喂食量 (克)
- 点击"保存计划"同步到设备
-
手动喂食
- 设置喂食量(5-100克)
- 点击"立即喂食"按钮
-
数据查看
- 余粮状态:进度条显示百分比
- 喂食记录:包含时间、喂食量和触发类型(手动/定时)
模块代码设计
设备端模块代码设计(STM32寄存器开发)
#include "stm32f10x.h"
// 硬件引脚定义
#define BUZZER_PIN GPIO_Pin_13 // PC13
#define MOTOR_PIN1 GPIO_Pin_8 // PC8
#define MOTOR_PIN2 GPIO_Pin_9 // PC9
#define MOTOR_PIN3 GPIO_Pin_10 // PC10
#define MOTOR_PIN4 GPIO_Pin_11 // PC11
#define HX711_SCK GPIO_Pin_0 // PA0
#define HX711_DOUT GPIO_Pin_1 // PA1
// 步进电机相位表
const uint8_t motorPhase[8] = {
0x09, 0x08, 0x0C, 0x04,
0x06, 0x02, 0x03, 0x01
};
// HX711读取函数
uint32_t HX711_Read(void) {
uint32_t data = 0;
GPIOA->BRR = HX711_SCK; // SCK低电平
while(GPIOA->IDR & HX711_DOUT); // 等待DOUT为低
for(uint8_t i=0; i<24; i++) {
GPIOA->BSRR = HX711_SCK; // SCK高电平
__nop(); __nop(); // 短暂延时
data <<= 1;
GPIOA->BRR = HX711_SCK; // SCK低电平
if(GPIOA->IDR & HX711_DOUT) data++;
}
// 发送第25个脉冲选择增益128
GPIOA->BSRR = HX711_SCK;
__nop(); __nop();
GPIOA->BRR = HX711_SCK;
return data ^ 0x800000; // 补码转换
}
// 步进电机驱动函数
void Motor_Rotate(int steps, uint8_t direction) {
static uint8_t phase = 0;
int step_count = (direction) ? steps : -steps;
while(step_count != 0) {
if(step_count > 0) {
phase = (phase + 1) % 8;
step_count--;
} else {
phase = (phase + 7) % 8;
step_count++;
}
GPIOC->ODR &= 0xF0FF; // 清空电机控制位
GPIOC->ODR |= (motorPhase[phase] << 8);
for(volatile int i=0; i<5000; i++); // 转速控制延时
}
GPIOC->BRR = MOTOR_PIN1 | MOTOR_PIN2 | MOTOR_PIN3 | MOTOR_PIN4; // 断电
}
// 蜂鸣器报警函数
void Buzzer_Alert(uint8_t state) {
if(state) {
GPIOC->BSRR = BUZZER_PIN;
} else {
GPIOC->BRR = BUZZER_PIN;
}
}
// RTC初始化
void RTC_Init(void) {
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
PWR->CR |= PWR_CR_DBP;
if((BKP->DR1 & 0xFFFF) != 0xA5A5) {
RCC->BDCR |= RCC_BDCR_LSEON;
while(!(RCC->BDCR & RCC_BDCR_LSERDY));
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;
RCC->BDCR |= RCC_BDCR_RTCEN;
RTC->CRL |= RTC_CRL_CNF;
RTC->PRLL = 32767; // LSE 32.768kHz
RTC->CRL &= ~RTC_CRL_CNF;
while(!(RTC->CRL & RTC_CRL_RTOFF));
BKP->DR1 = 0xA5A5;
}
}
// 系统初始化
void System_Init(void) {
// 时钟配置
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN;
// 蜂鸣器输出
GPIOC->CRH &= 0xFF0FFFFF;
GPIOC->CRH |= 0x00300000; // PC13推挽输出
// 步进电机输出
GPIOC->CRH &= 0xFFFF0000;
GPIOC->CRH |= 0x00003333; // PC8-PC11推挽输出
// HX711输入输出
GPIOA->CRL &= 0xFFFFFF00;
GPIOA->CRL |= 0x00000038; // PA0输出, PA1输入
// 初始化外设
RTC_Init();
}
// 主函数
int main(void) {
System_Init();
uint32_t last_feed = 0;
const uint32_t feed_interval = 43200; // 12小时 (RTC秒计数)
while(1) {
// 1. 检测余粮
uint32_t weight = HX711_Read();
if(weight < 50000) { // 阈值判断
Buzzer_Alert(1);
} else {
Buzzer_Alert(0);
}
// 2. RTC定时喂食
uint32_t current_time = RTC->CNTH << 16 | RTC->CNTL;
if((current_time - last_feed) >= feed_interval) {
Motor_Rotate(512, 1); // 旋转512步
last_feed = current_time;
}
// 3. 其他功能处理(OLED显示、网络通信等)
// ... (此处添加其他模块代码)
}
}
关键模块说明:
-
HX711压力传感器
- 使用PA0(SCK)和PA1(DOUT)
- 24位AD转换,补码转换处理
- 内置数据就绪检测
-
步进电机控制
- 四相八拍驱动方式
- 使用PC8-PC11控制ULN2003
- 相位表实现正反转控制
- 断电保护逻辑
-
RTC实时时钟
- LSE 32.768kHz时钟源
- 12小时定时喂食周期
- 后备寄存器初始化标志
-
蜂鸣器报警
- 高电平触发(PC13)
- 余粮阈值检测逻辑
-
系统初始化
- GPIO模式配置
- 时钟使能
- 外设初始化顺序控制
项目核心代码
以下是基于STM32F103C8T6的宠物喂食系统核心代码(寄存器开发版本),包含完整main.c实现:
#include "stm32f10x.h"
#include "hx711.h"
#include "oled.h"
#include "motor.h"
#include "rtc.h"
#include "usart.h"
#include "esp8266.h"
#include "voice.h"
// 宏定义
#define FEED_INTERVAL 8 // 默认喂食步数
#define FOOD_THRESHOLD 100 // 余粮阈值(g)
#define BUZZER_PIN GPIO_Pin_0
#define BUZZER_PORT GPIOA
// 全局变量
uint8_t feedFlag = 0; // 喂食触发标志
uint8_t foodLowAlarm = 0; // 余粮不足标志
uint32_t feedAmount = FEED_INTERVAL; // 动态喂食量
RTC_TimeTypeDef currentTime;
// 函数声明
void SystemClock_Config(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void Buzzer_Alarm(uint8_t state);
void Feed_Pet(void);
void Update_Feed_Amount(void);
void Process_MQTT_Command(uint8_t* cmd);
int main(void) {
// 初始化系统
SystemClock_Config();
GPIO_Configuration();
NVIC_Configuration();
// 外设初始化
USART1_Init(115200); // 语音模块串口
USART2_Init(115200); // ESP8266串口
OLED_Init();
HX711_Init();
RTC_Init();
Motor_Init();
// 显示启动界面
OLED_ShowString(0, 0, "PetFeeder V1.0");
OLED_ShowString(0, 2, "Init...");
Delay_ms(1000);
// 连接华为云
ESP8266_ConnectCloud();
OLED_ShowString(0, 2, "Cloud Connected");
while(1) {
// 1. 获取当前时间
RTC_GetTime(¤tTime);
// 2. 检测余粮状态
uint32_t foodWeight = HX711_GetWeight();
if(foodWeight < FOOD_THRESHOLD) {
foodLowAlarm = 1;
Buzzer_Alarm(1);
MQTT_Publish("petfeeder/alarm", "FOOD_LOW");
} else {
foodLowAlarm = 0;
Buzzer_Alarm(0);
}
// 3. 定时喂食检测 (例: 08:00和18:00)
if((currentTime.hours == 8 && currentTime.minutes == 0) ||
(currentTime.hours == 18 && currentTime.minutes == 0)) {
feedFlag = 1;
}
// 4. 处理喂食请求
if(feedFlag) {
Feed_Pet();
feedFlag = 0;
// 上传喂食记录
char feedMsg[50];
sprintf(feedMsg, "{\"time\":\"%02d:%02d\",\"amount\":%d}",
currentTime.hours, currentTime.minutes, feedAmount);
MQTT_Publish("petfeeder/feed", feedMsg);
// 更新喂食量算法
Update_Feed_Amount();
}
// 5. 处理语音指令
uint8_t voiceCmd[20];
if(VOICE_GetCommand(voiceCmd)) {
if(strcmp((char*)voiceCmd, "FEED") == 0) feedFlag = 1;
}
// 6. 处理MQTT命令
uint8_t mqttMsg[50];
if(ESP8266_ReceiveData(mqttMsg)) {
Process_MQTT_Command(mqttMsg);
}
// 7. 刷新显示
OLED_Clear();
char dispBuf[20];
sprintf(dispBuf, "Time: %02d:%02d", currentTime.hours, currentTime.minutes);
OLED_ShowString(0, 0, dispBuf);
sprintf(dispBuf, "Food: %d g", foodWeight);
OLED_ShowString(0, 2, dispBuf);
OLED_ShowString(0, 4, foodLowAlarm ? "LOW FOOD!" : "Normal");
Delay_ms(500);
}
}
// 蜂鸣器控制
void Buzzer_Alarm(uint8_t state) {
if(state) {
GPIO_SetBits(BUZZER_PORT, BUZZER_PIN);
} else {
GPIO_ResetBits(BUZZER_PORT, BUZZER_PIN);
}
}
// 执行喂食动作
void Feed_Pet(void) {
Motor_Rotate(feedAmount); // 顺时针旋转指定步数
Delay_ms(500);
Motor_Rotate(10); // 反向回旋防止卡粮
}
// 动态调整喂食量
void Update_Feed_Amount(void) {
// 简化示例:根据时间调整
if(currentTime.hours == 8) feedAmount = FEED_INTERVAL;
else feedAmount = FEED_INTERVAL + 2; // 晚餐加量
// 实际应加入机器学习算法
}
// 处理MQTT命令
void Process_MQTT_Command(uint8_t* cmd) {
if(strstr((char*)cmd, "CMD=FEED")) {
feedFlag = 1;
}
else if(strstr((char*)cmd, "CMD=SET_TIME")) {
// 解析时间设置命令
uint8_t h, m;
sscanf((char*)cmd, "CMD=SET_TIME%02d%02d", &h, &m);
RTC_SetTime(h, m, 0);
}
}
// 系统时钟配置 (72MHz HSE)
void SystemClock_Config(void) {
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
FLASH->ACR |= FLASH_ACR_LATENCY_2;
RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC;
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
RCC->CFGR |= RCC_CFGR_SW_PLL;
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
// GPIO配置
void GPIO_Configuration(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
// 蜂鸣器(PA0)
GPIOA->CRL &= ~(0x0F << (0*4));
GPIOA->CRL |= 0x02 << (0*4); // 推挽输出
// OLED SPI引脚配置(省略)
// 步进电机引脚配置(省略)
}
// 中断配置
void NVIC_Configuration(void) {
// 串口1中断(语音模块)
NVIC_EnableIRQ(USART1_IRQn);
NVIC_SetPriority(USART1_IRQn, 0);
// 串口2中断(ESP8266)
NVIC_EnableIRQ(USART2_IRQn);
NVIC_SetPriority(USART2_IRQn, 1);
}
// 串口1中断服务函数
void USART1_IRQHandler(void) {
if(USART1->SR & USART_SR_RXNE) {
VOICE_ReceiveHandler(USART1->DR);
}
}
// 串口2中断服务函数
void USART2_IRQHandler(void) {
if(USART2->SR & USART_SR_RXNE) {
ESP8266_ReceiveHandler(USART2->DR);
}
}
关键功能说明:
- 定时喂食:通过RTC实现08:00和18:00自动触发
- 余粮检测:HX711读取压力传感器数据,低于阈值触发蜂鸣器报警
- 语音控制:海凌科V20通过串口发送"FEED"指令触发喂食
- 动态喂食量:
Update_Feed_Amount
函数实现基础量调整(需扩展ML算法) - 华为云通信:
- 上传喂食记录:JSON格式数据
- 接收远程命令:支持"FEED"和"SET_TIME"指令
- 状态显示:OLED实时显示时间、余粮量和报警状态
总结
本设计实现了一个基于STM32F103C8T6主控芯片的智能宠物喂食系统,通过集成多模块硬件与软件,全面满足了定时喂食、远程控制、粮量监测等核心需求。系统利用28BYJ-48步进电机和ULN2003驱动板实现精确投喂动作,同时结合HX711模块和压力传感器实时检测剩余粮量,在粮量不足时触发高电平蜂鸣器报警,确保宠物不会断粮。时间控制基于RTC实时时钟,支持预设定时喂食计划,并通过ESP8266模块连接华为云平台,采用MQTT协议实现数据云端同步,保障了系统的可靠性和远程可访问性。
系统还融入了智能化功能,如通过海凌科 V20离线语音模块支持APP语音控制投喂指令下发,并能基于宠物进食习惯自动调整喂食量,提升了用户体验的便捷性和个性化。本地状态显示通过0.96寸OLED显示屏(SPI接口)实现,为用户提供实时反馈,而Qt for Android开发的APP和Qt5 + C++实现的上位机软件则提供了全面的远程配置与数据查看能力,包括喂食记录和系统设置。
总体而言,该设计通过硬件模块的协同工作与软件平台的优化,实现了高效、智能的宠物喂食管理。它不仅解决了日常喂食的自动化问题,还通过云端同步和语音交互增强了远程监控的灵活性,为宠物主人提供了一套安全、可靠且用户友好的解决方案。
- 点赞
- 收藏
- 关注作者
评论(0)