From 7cc4b38232e21cb774e2a8ac5b780bca5d544864 Mon Sep 17 00:00:00 2001 From: stark1898y <1658608470@qq.com> Date: Thu, 22 May 2025 14:08:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=B4=E6=BD=BC=E5=AE=9E=E9=AA=8C=E5=AE=A4?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mrs/launch.json | 12 ++-- APP/peripheral.c | 40 +++++++++++++ bsp/inc/bsp_valve.h | 24 +++++++- bsp/src/bsp_bmp390.c | 125 ++++++++++++++++++++++++++++++++++++++++ bsp/src/bsp_key.c | 6 +- bsp/src/bsp_valve.c | 132 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 327 insertions(+), 12 deletions(-) diff --git a/.mrs/launch.json b/.mrs/launch.json index 9cb812b..a24afd0 100644 --- a/.mrs/launch.json +++ b/.mrs/launch.json @@ -5,12 +5,12 @@ "type": "mrs-debugger", "request": "launch", "name": "IoT_SCV_CH584M1", - "cwd": "c:\\Users\\123\\Desktop\\自闭阀项目\\CDZBF\\iot_-scv_-ch584-m", + "cwd": "c:\\Users\\16586\\Desktop\\iot_-scv_-ch584-m(1)", "openOCDCfg": { "useLocalOpenOCD": true, - "executable": "d:/MounRiverV2/MounRiver_Studio2/resources/app/resources/win32/components/WCH/OpenOCD/OpenOCD/bin/openocd.exe", + "executable": "c:/MounRiver/MounRiver_Studio2/resources/app/resources/win32/components/WCH/OpenOCD/OpenOCD/bin/openocd.exe", "configOptions": [ - "-f \"d:/MounRiverV2/MounRiver_Studio2/resources/app/resources/win32/components/WCH/OpenOCD/OpenOCD/bin/wch-riscv.cfg\" -c \"chip_id CH32L10x\"" + "-f \"c:/MounRiver/MounRiver_Studio2/resources/app/resources/win32/components/WCH/OpenOCD/OpenOCD/bin/wch-riscv.cfg\" -c \"chip_id CH32L10x\"" ], "gdbport": 3333, "telnetport": 4444, @@ -22,7 +22,7 @@ "enableNoZeroWaitingAreaFlash": false }, "gdbCfg": { - "executable": "d:/MounRiverV2/MounRiver_Studio2/resources/app/resources/win32/components/WCH/Toolchain/RISC-V Embedded GCC12/bin/riscv-wch-elf-gdb.exe", + "executable": "c:/MounRiver/MounRiver_Studio2/resources/app/resources/win32/components/WCH/Toolchain/RISC-V Embedded GCC12/bin/riscv-wch-elf-gdb.exe", "commands": [ "set mem inaccessible-by-default off", "set architecture riscv:rv32", @@ -39,8 +39,8 @@ "additionalCommands": [] }, "loadedFiles": { - "executableFile": "c:\\Users\\123\\Desktop\\自闭阀项目\\CDZBF\\iot_-scv_-ch584-m\\obj\\IoT_SCV_CH584M1.elf", - "symbolFile": "c:\\Users\\123\\Desktop\\自闭阀项目\\CDZBF\\iot_-scv_-ch584-m\\obj\\IoT_SCV_CH584M1.elf", + "executableFile": "c:\\Users\\16586\\Desktop\\iot_-scv_-ch584-m(1)\\obj\\IoT_SCV_CH584M1.elf", + "symbolFile": "c:\\Users\\16586\\Desktop\\iot_-scv_-ch584-m(1)\\obj\\IoT_SCV_CH584M1.elf", "executableFileOffset": 0, "symbolFileOffset": 0 }, diff --git a/APP/peripheral.c b/APP/peripheral.c index 6dbec35..466a661 100644 --- a/APP/peripheral.c +++ b/APP/peripheral.c @@ -868,3 +868,43 @@ void BLE_ConnectEventCB(uint32_t timeUs) /********************************************************************* *********************************************************************/ + +// ڴ˴handleTimerCloseReqӶʱطĴ +static void handleTimerCloseReq(uint16_t time_min) +{ + // öʱط + BSP_VALVE_StartTimerClose(time_min); + + // ظóɹ + uint8_t buf[3]; + buf[0] = 0x01; // ɹ־ + buf[1] = (time_min >> 8) & 0xFF; // ֽ + buf[2] = time_min & 0xFF; // ֽ + + // ºͻ˷ͻظ + // sendTimerCloseRsp(buf, sizeof(buf)); + + logInfo("Set timer close: %d minutes", time_min); +} + +// ڴBLEĵطӴʱطĴ +// ´ĺӶԶʱطĴ +/* +static void processBleCommand(uint8_t cmd, uint8_t *data, uint16_t len) +{ + switch(cmd) + { + // ...  + + case CMD_TIMER_CLOSE: // һʱط + if (len >= 2) + { + uint16_t time_min = (data[0] << 8) | data[1]; + handleTimerCloseReq(time_min); + } + break; + + // ...  + } +} +*/ diff --git a/bsp/inc/bsp_valve.h b/bsp/inc/bsp_valve.h index 61604d7..04152fb 100644 --- a/bsp/inc/bsp_valve.h +++ b/bsp/inc/bsp_valve.h @@ -32,11 +32,18 @@ extern tmosTaskID vavle_task_id; #define VAVLE_LOOP_DECT_EVT (0x0001 << 8) // 循环检测 #define VAVLE_LOW_VBAT_LED_OFF_EVT (0x0001 << 10) // 低电压LED关闭事件 + +// 定时关阀相关事件 +#define VAVLE_TIMER_CLOSE_EVT (0x0001 << 11) // 定时关阀事件 +#define VAVLE_TIMER_CLOSE_START_EVT (0x0001 << 12) // 定时关阀开始事件 + #define VALVE_LOW_VBAT_ALARM_PERIOD_MS (1600 * 60 * 10) +#define VALVE_DECT_PERIOD_MS (1600 * 60 * 10) -#define VALVE_DECT_PERIOD_MS (1600 * 60 * 10) - - +// 定时关阀默认时间(单位:分钟),可以根据需求调整 +#define VALVE_TIMER_CLOSE_DEFAULT_MIN 30 +// 定时关阀最大时间(单位:分钟) +#define VALVE_TIMER_CLOSE_MAX_MIN 360 #define CHARGE_TIME_MS (1500) @@ -57,6 +64,7 @@ typedef enum kCmdCloseVavle, kCmdOpenVavle, kCmdData, + kCmdTimerCloseVavle, // 新增定时关阀命令 } TeFrameCmd; typedef struct __attribute__((packed)) @@ -105,6 +113,11 @@ typedef struct __attribute__((packed)) uint8_t bat; // 1B 电池电压 30=3V,18=1.8V uint8_t humi; // 1B 阀门湿度 %RH int8_t rssi; + + // 定时关阀状态变量 + uint8_t timer_close_enabled; // 定时关阀是否启用 + uint16_t timer_close_min; // 定时关阀时间(分钟) + uint32_t timer_close_start_time; // 定时关阀开始时间 } TsValveData; extern TsValveData gValveData; @@ -121,4 +134,9 @@ void BSP_VALVE_Generate_ValveResponse(TsRawFrameData *pRawData, TeFrameCmd cmd, void BSP_VALVE_Generate_UploadData(TsRawFrameData *pRawData); +// 定时关阀相关函数 +void BSP_VALVE_StartTimerClose(uint16_t close_min); +void BSP_VALVE_StopTimerClose(void); +uint16_t BSP_VALVE_GetTimerCloseRemainMin(void); + #endif // ! __BSP_VALVE_H__ diff --git a/bsp/src/bsp_bmp390.c b/bsp/src/bsp_bmp390.c index 523910d..508c685 100644 --- a/bsp/src/bsp_bmp390.c +++ b/bsp/src/bsp_bmp390.c @@ -12,6 +12,31 @@ uint8_t flag; uint8_t keydown_flag = 0; uint8_t keydown_time = 0; uint8_t volatile fault_state = 0; + +// ȫֵͳһ +#define SAFETY_AUTO_OPEN_THRESHOLD 3 // Զֵ +#define SAFETY_MICRO_LEAK_THRESHOLD 5 // ΢й©ֵ +#define SAFETY_MICRO_LEAK_PRESS_DIFF 15 // ΢й©ѹֵ(Pa)ӦԼ0.3L/min +#define SAFETY_OVER_TEMP_THRESHOLD 65 // ֵ() +#define SAFETY_GAS_REQUEST_PRESS_DIFF 50 // ѹֵ(Pa) + +// ȫ״̬ṹ +typedef struct { + // Զ + uint8_t auto_open_count; // Զ + uint8_t auto_open_flag; // Զ־ + + // ΢й© + uint8_t micro_leak_count; // ΢й© + uint8_t micro_leak_flag; // ΢й©־ + + // + uint8_t over_temp_flag; // ±־ +} TsValveSafetyStatus; + +// ȫ״̬ȫֱ +TsValveSafetyStatus valve_safety = {0}; + extern uint8_t motor_flag; extern Shell shell; @@ -775,6 +800,94 @@ uint16_t Check_ProcessEvent(uint8_t task_id, uint16_t events) logDebug("Over current status !"); } } + + // ¹طܣ¶ȳֵ + if(!valve_safety.over_temp_flag && gValveData.switch_status == kOpened) + { + // 㳬ֵĴ + uint8_t over_temp_count = 0; + + // ¶Ƿ񳬹ֵ + if(T[0] > SAFETY_OVER_TEMP_THRESHOLD) over_temp_count++; + if(T[1] > SAFETY_OVER_TEMP_THRESHOLD) over_temp_count++; + if(T[2] > SAFETY_OVER_TEMP_THRESHOLD) over_temp_count++; + + // ֵط + if(over_temp_count >= 2) + { + logDebug("Over temperature detected! T1=%d, T2=%d, T3=%d", T[0], T[1], T[2]); + valve_safety.over_temp_flag = 1; + motor_flag = 2; // ط + } + } + + // 𿪷ܣȼ򿪵Źرյ + // Źرʱ + if(gValveData.switch_status == kClosed) + { + // ѹȴѹһֵʾ + // P[1]ΪѹP[2]Ϊѹ + if(P[2] > P[1] && (P[2] - P[1] >= SAFETY_GAS_REQUEST_PRESS_DIFF)) + { + valve_safety.auto_open_count++; + logDebug("Auto open detect: %d", valve_safety.auto_open_count); + + // μ⵽󣬴 + if(valve_safety.auto_open_count >= SAFETY_AUTO_OPEN_THRESHOLD && !valve_safety.auto_open_flag) + { + logDebug("Auto opening valve due to gas usage detected!"); + valve_safety.auto_open_flag = 1; + // motor_flagΪ1 + motor_flag = 1; + } + } + else + { + // ü + valve_safety.auto_open_count = 0; + } + } + else + { + // ſ״̬üͱ־ + valve_safety.auto_open_count = 0; + valve_safety.auto_open_flag = 0; + } + + // ΢й©طܣ΢СԶرշ + // Ŵʱ΢й© + if(gValveData.switch_status == kOpened) + { + // ΢й©ںͳѹdzСڳС + // P[0]ΪѹP[1]Ϊѹ + // ѹΧ0ȷСֵʾ0.3L/min + if(P[0] > P[1] && (P[0] - P[1] > 0) && (P[0] - P[1] < SAFETY_MICRO_LEAK_PRESS_DIFF)) + { + valve_safety.micro_leak_count++; + logDebug("Micro leak detect: %d, pressure diff: %d", valve_safety.micro_leak_count, P[0] - P[1]); + + // μ⵽΢й©ط + if(valve_safety.micro_leak_count >= SAFETY_MICRO_LEAK_THRESHOLD && !valve_safety.micro_leak_flag) + { + logDebug("Auto closing valve due to micro leak detected!"); + valve_safety.micro_leak_flag = 1; + // motor_flagΪ2ط + motor_flag = 2; + } + } + else + { + // ΢й©ü + valve_safety.micro_leak_count = 0; + } + } + else + { + // Źر״̬üͱ־ + valve_safety.micro_leak_count = 0; + valve_safety.micro_leak_flag = 0; + } + //ػ ^PСʱر //^pѹ } @@ -797,6 +910,18 @@ uint16_t Check_ProcessEvent(uint8_t task_id, uint16_t events) LED_VALVE_CLOSE; VALVE_CLOSE(); fault_state = 4; + // ΢й©طñ־ + if(valve_safety.micro_leak_flag) + { + valve_safety.micro_leak_flag = 0; + logDebug("Micro leak protection activated"); + } + // ¹طñ־ + if(valve_safety.over_temp_flag) + { + valve_safety.over_temp_flag = 0; + logDebug("Over temperature protection activated"); + } logDebug("motor/LED close!!!"); tmos_start_task(check_task_id, MOTOR_STOP_EVT, MS1_TO_SYSTEM_TIME(CHARGE_TIME_MS)); } diff --git a/bsp/src/bsp_key.c b/bsp/src/bsp_key.c index 69a87b3..3438dc6 100644 --- a/bsp/src/bsp_key.c +++ b/bsp/src/bsp_key.c @@ -338,9 +338,9 @@ void KEY_ProcessLoop(void) logDebug("motor_flag_start = %d",motor_flag); tmos_start_task(key_task_id, KEY_IDLE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(KEY_IDLE_TIMEOUT_MS)); } - else if (press_count >= 2) + else if (press_count == 2) { - tmos_start_task(key_task_id, KEY_IDLE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(KEY_IDLE_TIMEOUT_MS)); + // tmos_start_task(key_task_id, KEY_IDLE_TIMEOUT_EVT, MS1_TO_SYSTEM_TIME(KEY_IDLE_TIMEOUT_MS)); if(gValveData.switch_status == kClosed) { motor_flag = 1; @@ -360,7 +360,7 @@ void KEY_ProcessLoop(void) // motor_flag = 2; // logDebug("motor close"); // } - // press_count = 0; + press_count = 0; } tmos_set_event(key_task_id, KEY_SCAN_EVT); diff --git a/bsp/src/bsp_valve.c b/bsp/src/bsp_valve.c index bea2e6d..f029cc4 100644 --- a/bsp/src/bsp_valve.c +++ b/bsp/src/bsp_valve.c @@ -196,6 +196,17 @@ static void VAVLE_Task_ProcessTmosMsg(uint8_t *p_rev_msg) // 处理TMOS消息函 logDebug("kCmdOpenVavle"); tmos_set_event(vavle_task_id, VAVLE_OPEN_START_EVT); break; + case kCmdTimerCloseVavle: // 定时关阀命令 + logDebug("kCmdTimerCloseVavle"); + if (HostFrameData->len >= 2) { + // 定时参数在data中,前2字节表示定时时间(分钟) + uint16_t close_min = (HostFrameData->data[0] << 8) | HostFrameData->data[1]; + BSP_VALVE_StartTimerClose(close_min); + } else { + // 使用默认时间 + BSP_VALVE_StartTimerClose(VALVE_TIMER_CLOSE_DEFAULT_MIN); + } + break; default: logError("Invalid command"); break; @@ -348,6 +359,27 @@ static uint16_t VAVLE_Task_ProcessEvent(uint8_t task_id, uint16_t events) // 阀 { tmos_set_event(vavle_task_id, VAVLE_LOW_VBAT_ALARM_EVT); } + + // 检查定时关阀是否到时间 + if (gValveData.timer_close_enabled && gValveData.switch_status == kOpened) + { + uint32_t current_time = BSP_Get_Tick(); + uint32_t elapsed_ms = current_time - gValveData.timer_close_start_time; + uint32_t timer_ms = (uint32_t)gValveData.timer_close_min * 60 * 1000; + + if (elapsed_ms >= timer_ms) + { + // 时间到,触发关阀事件 + tmos_set_event(vavle_task_id, VAVLE_TIMER_CLOSE_EVT); + } + else + { + // 剩余时间(分钟) + uint16_t remain_min = (timer_ms - elapsed_ms) / (60 * 1000); + logDebug("Timer close remaining: %d minutes", remain_min); + } + } + tmos_start_task(vavle_task_id, VAVLE_LOOP_DECT_EVT, MS1_TO_SYSTEM_TIME(VALVE_DECT_PERIOD_MS)); return (events ^ VAVLE_LOOP_DECT_EVT); @@ -382,6 +414,50 @@ static uint16_t VAVLE_Task_ProcessEvent(uint8_t task_id, uint16_t events) // 阀 return (events ^ VAVLE_LOW_VBAT_LED_OFF_EVT); } + // 定时关阀事件处理 + if (events & VAVLE_TIMER_CLOSE_EVT) + { + logDebug("VAVLE_TIMER_CLOSE_EVT"); + + // 关闭定时器 + BSP_VALVE_StopTimerClose(); + + // 如果阀门当前是打开状态,则触发关闭 + if (gValveData.switch_status == kOpened) + { + // 触发关阀事件 + tmos_set_event(vavle_task_id, VAVLE_CLOSE_START_EVT); + } + + return (events ^ VAVLE_TIMER_CLOSE_EVT); + } + + // 定时关阀开始事件处理 + if (events & VAVLE_TIMER_CLOSE_START_EVT) + { + logDebug("VAVLE_TIMER_CLOSE_START_EVT"); + + // 记录开始时间 + gValveData.timer_close_start_time = BSP_Get_Tick(); + gValveData.timer_close_enabled = 1; + + logDebug("Timer close started: %d minutes", gValveData.timer_close_min); + + // 闪烁LED提示用户定时已设置(可选) + LED_VALVE_CLOSE; + DelayMs(200); + if (gValveData.switch_status == kOpened) + { + LED_VALVE_OPEN; + } + else + { + LED_VALVE_CLOSE; + } + + return (events ^ VAVLE_TIMER_CLOSE_START_EVT); + } + return 0; } @@ -397,6 +473,11 @@ void BSP_VAVLE_Init(void) // 阀门初始化函数 gValveData.type = kTyq; // 设置阀门类型 gValveData.bat = BSP_ReadVbat(); // 读取电池电压 + + // 初始化定时关阀状态变量 + gValveData.timer_close_enabled = 0; + gValveData.timer_close_min = 0; + gValveData.timer_close_start_time = 0; BSP_MOTOR_Init(); // 初始化电机 @@ -404,3 +485,54 @@ void BSP_VAVLE_Init(void) // 阀门初始化函数 logInfo("BSP_Valve_Init"); } + +void BSP_VALVE_StartTimerClose(uint16_t close_min) +{ + if (close_min == 0) + { + // 关闭定时器 + BSP_VALVE_StopTimerClose(); + return; + } + + // 限制最大定时时间 + if (close_min > VALVE_TIMER_CLOSE_MAX_MIN) + { + close_min = VALVE_TIMER_CLOSE_MAX_MIN; + } + + // 设置定时参数 + gValveData.timer_close_min = close_min; + + // 触发定时开始事件 + tmos_set_event(vavle_task_id, VAVLE_TIMER_CLOSE_START_EVT); + + logDebug("BSP_VALVE_StartTimerClose: %d minutes", close_min); +} + +void BSP_VALVE_StopTimerClose(void) +{ + gValveData.timer_close_enabled = 0; + gValveData.timer_close_min = 0; + + logDebug("BSP_VALVE_StopTimerClose"); +} + +uint16_t BSP_VALVE_GetTimerCloseRemainMin(void) +{ + if (!gValveData.timer_close_enabled) + { + return 0; + } + + uint32_t current_time = BSP_Get_Tick(); + uint32_t elapsed_ms = current_time - gValveData.timer_close_start_time; + uint32_t timer_ms = (uint32_t)gValveData.timer_close_min * 60 * 1000; + + if (elapsed_ms >= timer_ms) + { + return 0; + } + + return (timer_ms - elapsed_ms) / (60 * 1000); +}