## 主要修改
### 1. MQTT setMode命令处理修复 - 添加Set_System_Mode函数extern声明,解决编译错误 - 将setMode处理逻辑移到control主题,符合小程序规范 - 完善Set_System_Mode函数,添加音频播放功能 ### 2. 按键4手动补水功能 - 实现key4_single_click_handler函数,添加手动补水逻辑 - 与按键2喂食逻辑保持一致:相同的模式检查和错误处理 - 提供完整的本地手动控制功能 ### 3. 系统优化 - 统一本地和远程控制逻辑 - 完善错误处理和用户反馈 - 优化代码结构和日志记录 ## 影响 - 系统现在支持完整的双重控制方式(本地按键+远程MQTT) - 所有按键功能完善:模式切换、手动喂食、页面切换、手动补水 - 编译无错误,代码结构清晰,便于维护
This commit is contained in:
@@ -19,10 +19,9 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "main.h"
|
||||
#include "task.h"
|
||||
#include "main.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
@@ -110,48 +109,67 @@ static volatile Feed_Cmd_t feed_command = FEED_CMD_NONE; // 喂食命令标志
|
||||
static volatile uint16_t feed_angle = 90; // 喂食角度(默认90度)
|
||||
static volatile uint8_t feed_amount = 1; // 喂食份数
|
||||
|
||||
// 加水控制命令枚举
|
||||
typedef enum {
|
||||
WATER_CMD_NONE = 0, // 无命令
|
||||
WATER_CMD_MANUAL, // 手动加水
|
||||
WATER_CMD_AUTO, // 自动加水
|
||||
WATER_CMD_REMOTE // 远程加水
|
||||
} Water_Cmd_t;
|
||||
|
||||
// 加水控制相关全局变量
|
||||
static volatile Water_Cmd_t water_command = WATER_CMD_NONE; // 加水命令标志
|
||||
static volatile uint8_t watering_in_progress = 0; // 加水进行中标志
|
||||
|
||||
/* USER CODE END Variables */
|
||||
/* Definitions for defaultTask */
|
||||
osThreadId_t defaultTaskHandle;
|
||||
const osThreadAttr_t defaultTask_attributes = {
|
||||
.name = "defaultTask",
|
||||
.stack_size = 256 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh1,
|
||||
.name = "defaultTask",
|
||||
.stack_size = 256 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh1,
|
||||
};
|
||||
/* Definitions for wifi_mqtt */
|
||||
osThreadId_t wifi_mqttHandle;
|
||||
const osThreadAttr_t wifi_mqtt_attributes = {
|
||||
.name = "wifi_mqtt",
|
||||
.stack_size = 3000 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh,
|
||||
.name = "wifi_mqtt",
|
||||
.stack_size = 3000 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh,
|
||||
};
|
||||
/* Definitions for LCD_SHOW_Task */
|
||||
osThreadId_t LCD_SHOW_TaskHandle;
|
||||
const osThreadAttr_t LCD_SHOW_Task_attributes = {
|
||||
.name = "LCD_SHOW_Task",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh,
|
||||
.name = "LCD_SHOW_Task",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh,
|
||||
};
|
||||
/* Definitions for button */
|
||||
osThreadId_t buttonHandle;
|
||||
const osThreadAttr_t button_attributes = {
|
||||
.name = "button",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t)osPriorityRealtime2,
|
||||
.name = "button",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t) osPriorityRealtime2,
|
||||
};
|
||||
/* Definitions for sensor */
|
||||
osThreadId_t sensorHandle;
|
||||
const osThreadAttr_t sensor_attributes = {
|
||||
.name = "sensor",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t)osPriorityNormal,
|
||||
.name = "sensor",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
};
|
||||
/* Definitions for step_motor */
|
||||
osThreadId_t step_motorHandle;
|
||||
const osThreadAttr_t step_motor_attributes = {
|
||||
.name = "step_motor",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t)osPriorityNormal,
|
||||
.name = "step_motor",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
};
|
||||
/* Definitions for water_control */
|
||||
osThreadId_t water_controlHandle;
|
||||
const osThreadAttr_t water_control_attributes = {
|
||||
.name = "water_control",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
};
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
@@ -165,6 +183,16 @@ void LCD_UpdateSensorData(float temp, float humi, float weight, uint8_t water,
|
||||
Sensor_Data_t *LCD_GetSensorData(void);
|
||||
void user_button_init(void);
|
||||
void RTC_TimeUpdateCallback(void); // RTC时间更新回调函数
|
||||
uint8_t Build_Sensor_JSON(const Sensor_Data_t *data, char *buffer, uint16_t buffer_size);
|
||||
|
||||
|
||||
static void Execute_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) ;
|
||||
void Clear_Feed_Command(void);
|
||||
uint8_t Request_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount);
|
||||
|
||||
uint8_t Request_Water(Water_Cmd_t cmd);
|
||||
void Clear_Water_Command(void);
|
||||
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
void StartDefaultTask(void *argument);
|
||||
@@ -173,14 +201,15 @@ void LCD_Task(void *argument);
|
||||
void button_task(void *argument);
|
||||
void sensorTask(void *argument);
|
||||
void step_motor_task(void *argument);
|
||||
void water_controlTask(void *argument);
|
||||
|
||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||
|
||||
/**
|
||||
* @brief FreeRTOS initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
* @brief FreeRTOS initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE BEGIN Init */
|
||||
ST7735_Init(); // 初始化ST7735显示屏
|
||||
@@ -205,8 +234,7 @@ void MX_FREERTOS_Init(void) {
|
||||
|
||||
/* Create the thread(s) */
|
||||
/* creation of defaultTask */
|
||||
defaultTaskHandle =
|
||||
osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
|
||||
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
|
||||
|
||||
/* creation of wifi_mqtt */
|
||||
wifi_mqttHandle = osThreadNew(wifi_task_mqtt, NULL, &wifi_mqtt_attributes);
|
||||
@@ -223,6 +251,9 @@ void MX_FREERTOS_Init(void) {
|
||||
/* creation of step_motor */
|
||||
step_motorHandle = osThreadNew(step_motor_task, NULL, &step_motor_attributes);
|
||||
|
||||
/* creation of water_control */
|
||||
water_controlHandle = osThreadNew(water_controlTask, NULL, &water_control_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
/* USER CODE END RTOS_THREADS */
|
||||
@@ -230,6 +261,7 @@ void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE BEGIN RTOS_EVENTS */
|
||||
/* add events, ... */
|
||||
/* USER CODE END RTOS_EVENTS */
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_StartDefaultTask */
|
||||
@@ -239,7 +271,8 @@ void MX_FREERTOS_Init(void) {
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_StartDefaultTask */
|
||||
void StartDefaultTask(void *argument) {
|
||||
void StartDefaultTask(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN StartDefaultTask */
|
||||
// 1. 打开运行灯
|
||||
Device_Control(DEVICE_LED_RUN, 1);
|
||||
@@ -281,7 +314,8 @@ void StartDefaultTask(void *argument) {
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_LCD_Task */
|
||||
void LCD_Task(void *argument) {
|
||||
void LCD_Task(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN LCD_Task */
|
||||
|
||||
char display_str[32];
|
||||
@@ -503,7 +537,8 @@ void LCD_Task(void *argument) {
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_button_task */
|
||||
void button_task(void *argument) {
|
||||
void button_task(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN button_task */
|
||||
user_button_init();
|
||||
|
||||
@@ -522,7 +557,8 @@ void button_task(void *argument) {
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_sensorTask */
|
||||
void sensorTask(void *argument) {
|
||||
void sensorTask(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN sensorTask */
|
||||
elog_i(TAG, "启动传感器任务");
|
||||
|
||||
@@ -582,108 +618,35 @@ void sensorTask(void *argument) {
|
||||
sensor_data.food_weight= HX711_GetWeight(10); // 采样10次取平均
|
||||
elog_d(TAG, "当前重量:%.2f g", sensor_data.food_weight);
|
||||
|
||||
// ========== 发布传感器数据到MQTT ==========
|
||||
char json_buffer[128];
|
||||
if (Build_Sensor_JSON(&sensor_data, json_buffer, sizeof(json_buffer))) {
|
||||
if (WIFI_MQTT_Publish_Sensor(json_buffer)) {
|
||||
elog_i(TAG, "传感器数据发布成功: %s", json_buffer);
|
||||
} else {
|
||||
elog_e(TAG, "传感器数据发布失败");
|
||||
}
|
||||
} else {
|
||||
elog_e(TAG, "构建JSON数据失败");
|
||||
}
|
||||
// ========== 发布结束 ===============
|
||||
// 每2秒读取一次
|
||||
osDelay(2000);
|
||||
}
|
||||
/* USER CODE END sensorTask */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 请求喂食操作
|
||||
* @param cmd: 喂食命令类型
|
||||
* @param angle: 转动角度
|
||||
* @param amount: 喂食份数
|
||||
* @retval 1=请求成功, 0=请求失败(正在喂食中)
|
||||
*/
|
||||
uint8_t Request_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
if (feeding_in_progress) {
|
||||
elog_w("FEED", "喂食进行中,无法接受新命令");
|
||||
return 0;
|
||||
}
|
||||
|
||||
feed_command = cmd;
|
||||
feed_angle = angle;
|
||||
feed_amount = amount;
|
||||
|
||||
elog_i("FEED", "喂食请求已提交: cmd=%d, angle=%d, amount=%d", cmd, angle,
|
||||
amount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前喂食命令
|
||||
* @retval 当前喂食命令
|
||||
*/
|
||||
Feed_Cmd_t Get_Feed_Command(void) { return feed_command; }
|
||||
|
||||
/**
|
||||
* @brief 清除喂食命令
|
||||
*/
|
||||
void Clear_Feed_Command(void) { feed_command = FEED_CMD_NONE; }
|
||||
|
||||
/**
|
||||
* @brief 执行喂食操作
|
||||
* @param cmd: 喂食命令类型
|
||||
* @param angle: 转动角度
|
||||
* @param amount: 喂食份数
|
||||
*/
|
||||
static void Execute_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
if (feeding_in_progress) {
|
||||
return; // 防止重复执行
|
||||
}
|
||||
|
||||
feeding_in_progress = 1;
|
||||
|
||||
// 根据命令类型播放不同音频
|
||||
switch (cmd) {
|
||||
case FEED_CMD_MANUAL:
|
||||
MP3_Play(FEED_MANUAL_TRIGGER);
|
||||
elog_i("FEED", "执行手动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_AUTO:
|
||||
MP3_Play(FEED_AUTO_START);
|
||||
elog_i("FEED", "执行自动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_REMOTE:
|
||||
MP3_Play(REMOTE_CMD_RECEIVED);
|
||||
elog_i("FEED", "执行远程喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_TEST:
|
||||
elog_i("FEED", "执行测试喂食: 角度%d度", angle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 执行实际的喂食动作
|
||||
for (uint8_t i = 0; i < amount; i++) {
|
||||
Stepper_Motor_RotateAngle(angle, STEPPER_DIR_CW, 2, STEPPER_MODE_FULL_STEP);
|
||||
if (i < amount - 1) {
|
||||
osDelay(1000); // 多份之间间隔1秒
|
||||
}
|
||||
}
|
||||
|
||||
// 等待食物落下
|
||||
osDelay(3000);
|
||||
|
||||
// 停止电机
|
||||
Stepper_Motor_Stop();
|
||||
|
||||
// 播放完成音效
|
||||
MP3_Play(FEED_COMPLETE);
|
||||
elog_i("FEED", "喂食完成");
|
||||
|
||||
feeding_in_progress = 0;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_step_motor_task */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function implementing the step_motor thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_step_motor_task */
|
||||
void step_motor_task(void *argument) {
|
||||
void step_motor_task(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN step_motor_task */
|
||||
// 初始化步进电机
|
||||
Stepper_Motor_Init();
|
||||
@@ -708,6 +671,91 @@ void step_motor_task(void *argument) {
|
||||
/* USER CODE END step_motor_task */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_water_controlTask */
|
||||
/**
|
||||
* @brief Function implementing the water_control thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_water_controlTask */
|
||||
void water_controlTask(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN water_controlTask */
|
||||
elog_i("WATER", "启动加水控制任务");
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
// 检查是否有加水命令需要执行
|
||||
if (water_command != WATER_CMD_NONE && !watering_in_progress) {
|
||||
Water_Cmd_t current_cmd = water_command;
|
||||
|
||||
// 清除命令标志
|
||||
Clear_Water_Command();
|
||||
|
||||
// 执行加水
|
||||
watering_in_progress = 1;
|
||||
|
||||
// 根据命令类型播放不同音频
|
||||
switch (current_cmd) {
|
||||
case WATER_CMD_MANUAL:
|
||||
MP3_Play(WATER_REFILL_DONE);
|
||||
elog_i("WATER", "执行手动加水");
|
||||
break;
|
||||
case WATER_CMD_AUTO:
|
||||
MP3_Play(WATER_REFILL_DONE);
|
||||
elog_i("WATER", "执行自动加水");
|
||||
break;
|
||||
case WATER_CMD_REMOTE:
|
||||
MP3_Play(REMOTE_CMD_RECEIVED);
|
||||
elog_i("WATER", "执行远程加水");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 打开水泵继电器(假设DEVICE_RELAY控制水泵)
|
||||
Device_Control(DEVICE_RELAY, 1);
|
||||
elog_i("WATER", "水泵启动,等待水位传感器检测到有水");
|
||||
|
||||
// 加水超时保护(最大30秒)
|
||||
uint32_t start_time = osKernelGetTickCount();
|
||||
const uint32_t MAX_WATERING_TIME = 30000; // 30秒超时
|
||||
|
||||
// 循环检查水位传感器,直到检测到有水或超时
|
||||
while (1) {
|
||||
// 检查是否检测到有水
|
||||
if (sensor_data.water_level == 1) {
|
||||
elog_i("WATER", "水位传感器检测到有水,停止加水");
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查是否超时
|
||||
if (osKernelGetTickCount() - start_time > MAX_WATERING_TIME) {
|
||||
elog_w("WATER", "加水超时(30秒),强制停止");
|
||||
break;
|
||||
}
|
||||
|
||||
// 短暂延时,避免占用过多CPU
|
||||
osDelay(100);
|
||||
}
|
||||
|
||||
// 关闭水泵继电器
|
||||
Device_Control(DEVICE_RELAY, 0);
|
||||
elog_i("WATER", "水泵停止");
|
||||
|
||||
// 播放完成音效
|
||||
MP3_Play(WATER_REFILL_DONE);
|
||||
elog_i("WATER", "加水完成");
|
||||
|
||||
watering_in_progress = 0;
|
||||
}
|
||||
|
||||
osDelay(100); // 短暂延时,保持任务响应性
|
||||
}
|
||||
/* USER CODE END water_controlTask */
|
||||
}
|
||||
|
||||
/* Private application code --------------------------------------------------*/
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
@@ -795,7 +843,26 @@ void key3_single_click_handler(Button *btn) {
|
||||
LCD_NextPage();
|
||||
}
|
||||
|
||||
void key4_single_click_handler(Button *btn) { elog_i("KEY", "按键4单击"); }
|
||||
/**
|
||||
* @brief 按键4处理函数:手动补水(仅手动模式有效)
|
||||
* @param btn: 按键句柄
|
||||
*/
|
||||
void key4_single_click_handler(Button *btn) {
|
||||
// 检查是否为手动模式
|
||||
if (!system_mode) {
|
||||
// 手动模式下才允许手动补水
|
||||
if (Request_Water(WATER_CMD_MANUAL)) {
|
||||
elog_i("KEY", "按键4单击 - 手动补水请求已提交");
|
||||
} else {
|
||||
elog_w("KEY", "补水进行中,请稍后再试");
|
||||
MP3_Play(SYS_ERROR_ALARM);
|
||||
}
|
||||
} else {
|
||||
// 自动模式下按键无效
|
||||
elog_w("KEY", "当前为自动模式,按键4无效");
|
||||
MP3_Play(SYS_ERROR_ALARM);
|
||||
}
|
||||
}
|
||||
|
||||
void M3_long_press_start_handler(Button *btn) {
|
||||
elog_i("KEY", "M3水位传感器检测到有水(低电平)");
|
||||
@@ -856,6 +923,10 @@ void Set_System_Mode(uint8_t mode) {
|
||||
system_mode = mode;
|
||||
sensor_data.system_mode = mode;
|
||||
lcd_force_refresh = 1; // 强制刷新显示
|
||||
|
||||
// 播放模式切换音效(与按键1逻辑保持一致)
|
||||
MP3_Play(mode ? MODE_AUTO : MODE_MANUAL);
|
||||
|
||||
elog_i("SYSTEM", "系统模式设置为: %s", mode ? "自动" : "手动");
|
||||
}
|
||||
}
|
||||
@@ -950,6 +1021,153 @@ Sensor_Data_t *LCD_GetSensorData(void) { return &sensor_data; }
|
||||
*/
|
||||
void RTC_TimeUpdateCallback(void) { lcd_force_refresh = 1; }
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 构建传感器数据JSON字符串(符合小程序格式要求)
|
||||
* @param data 传感器数据结构体指针
|
||||
* @param buffer 输出缓冲区
|
||||
* @param buffer_size 缓冲区大小
|
||||
* @return 1表示成功,0表示失败(参数错误或缓冲区不足)
|
||||
*/
|
||||
uint8_t Build_Sensor_JSON(const Sensor_Data_t *data, char *buffer, uint16_t buffer_size) {
|
||||
// 参数检查
|
||||
if (!data || !buffer || buffer_size < 128) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 将float类型的湿度和重量转换为整数(小程序要求整数)
|
||||
int humidity_int = (int)data->humidity;
|
||||
int food_weight_int = (int)data->food_weight;
|
||||
|
||||
// 构建符合小程序要求的JSON字符串
|
||||
// 注意字段名:foodWeight(camelCase)而不是food_weight(snake_case)
|
||||
// waterLevel(camelCase)而不是water_level(snake_case)
|
||||
snprintf(buffer, buffer_size,
|
||||
"{\"temperature\":%.1f,\"humidity\":%d,\"foodWeight\":%d,\"waterLevel\":%d}",
|
||||
data->temperature, // 温度(保留1位小数)
|
||||
humidity_int, // 湿度(整数)
|
||||
food_weight_int, // 食物重量(整数)
|
||||
data->water_level); // 水位状态(0或1)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 请求喂食操作
|
||||
* @param cmd: 喂食命令类型
|
||||
* @param angle: 转动角度
|
||||
* @param amount: 喂食份数
|
||||
* @retval 1=请求成功, 0=请求失败(正在喂食中)
|
||||
*/
|
||||
uint8_t Request_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
if (feeding_in_progress) {
|
||||
elog_w("FEED", "喂食进行中,无法接受新命令");
|
||||
return 0;
|
||||
}
|
||||
|
||||
feed_command = cmd;
|
||||
feed_angle = angle;
|
||||
feed_amount = amount;
|
||||
|
||||
elog_i("FEED", "喂食请求已提交: cmd=%d, angle=%d, amount=%d", cmd, angle,
|
||||
amount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前喂食命令
|
||||
* @retval 当前喂食命令
|
||||
*/
|
||||
Feed_Cmd_t Get_Feed_Command(void) { return feed_command; }
|
||||
|
||||
/**
|
||||
* @brief 清除喂食命令
|
||||
*/
|
||||
void Clear_Feed_Command(void) { feed_command = FEED_CMD_NONE; }
|
||||
|
||||
/**
|
||||
* @brief 请求加水操作
|
||||
* @param cmd: 加水命令类型
|
||||
* @retval 1=请求成功, 0=请求失败(正在加水中)
|
||||
*/
|
||||
uint8_t Request_Water(Water_Cmd_t cmd) {
|
||||
if (watering_in_progress) {
|
||||
elog_w("WATER", "加水进行中,无法接受新命令");
|
||||
return 0;
|
||||
}
|
||||
|
||||
water_command = cmd;
|
||||
|
||||
elog_i("WATER", "加水请求已提交: cmd=%d", cmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除加水命令
|
||||
*/
|
||||
void Clear_Water_Command(void) { water_command = WATER_CMD_NONE; }
|
||||
|
||||
/**
|
||||
* @brief 执行喂食操作
|
||||
* @param cmd: 喂食命令类型
|
||||
* @param angle: 转动角度
|
||||
* @param amount: 喂食份数
|
||||
*/
|
||||
static void Execute_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
if (feeding_in_progress) {
|
||||
return; // 防止重复执行
|
||||
}
|
||||
|
||||
feeding_in_progress = 1;
|
||||
|
||||
// 根据命令类型播放不同音频
|
||||
switch (cmd) {
|
||||
case FEED_CMD_MANUAL:
|
||||
MP3_Play(FEED_MANUAL_TRIGGER);
|
||||
elog_i("FEED", "执行手动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_AUTO:
|
||||
MP3_Play(FEED_AUTO_START);
|
||||
elog_i("FEED", "执行自动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_REMOTE:
|
||||
MP3_Play(REMOTE_CMD_RECEIVED);
|
||||
elog_i("FEED", "执行远程喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_TEST:
|
||||
elog_i("FEED", "执行测试喂食: 角度%d度", angle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 执行实际的喂食动作
|
||||
for (uint8_t i = 0; i < amount; i++) {
|
||||
Stepper_Motor_RotateAngle(angle, STEPPER_DIR_CW, 2, STEPPER_MODE_FULL_STEP);
|
||||
if (i < amount - 1) {
|
||||
osDelay(1000); // 多份之间间隔1秒
|
||||
}
|
||||
}
|
||||
|
||||
// 等待食物落下
|
||||
osDelay(3000);
|
||||
|
||||
// 停止电机
|
||||
Stepper_Motor_Stop();
|
||||
|
||||
// 播放完成音效
|
||||
MP3_Play(FEED_COMPLETE);
|
||||
elog_i("FEED", "喂食完成");
|
||||
|
||||
feeding_in_progress = 0;
|
||||
}
|
||||
|
||||
|
||||
/* USER CODE END LCD_Page_Functions */
|
||||
|
||||
/* USER CODE END Application */
|
||||
/* USER CODE END Application */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user