feat(opt): 光耦输出模式完整实现 — 6种融合逻辑 + 人车混行/ETC 状态机
- 新增 g_opt_trigger 全局变量:opt_input_poll() 产出, TMR1 ISR 消费 - MODE 1/2/3/4: 纯地感/纯雷达/或/与 — g_opt_trigger 直出光耦信号 - MODE 5 (HUMAN_VD_MIX): 3态机 IDLE→ARMED→WINDOW, 3s防砸窗口 - MODE 6 (ETC): 3态机 IDLE→ARMED→DEBOUNCE, 500ms防抖释放 - TMR1 ISR case 0: 6模式融合判决 (coil || opt_trigger / coil && opt_trigger等) - 光耦防抖: 3样本多数表决, ~30ms消抖 - MODE 0 复位逻辑不变 - docs: 更新开发日志 (状态机图 + 各模式对照表)
This commit is contained in:
@@ -43,6 +43,7 @@ extern uint8_t g_loop_power_up_state;
|
|||||||
extern uint8_t g_function_mode;
|
extern uint8_t g_function_mode;
|
||||||
extern uint8_t g_fm_700bs_disable ; //0: 700bs protocol; 1 Modbus protocol
|
extern uint8_t g_fm_700bs_disable ; //0: 700bs protocol; 1 Modbus protocol
|
||||||
extern uint8_t g_output_radar_mode;
|
extern uint8_t g_output_radar_mode;
|
||||||
|
extern uint8_t g_opt_trigger; // 光耦/雷达 处理后触发信号 (1=有效)
|
||||||
|
|
||||||
/* 新算法状�? (DLD154V4B 移植) */
|
/* 新算法状�? (DLD154V4B 移植) */
|
||||||
extern uint8_t g_loop_stable; // 稳定期结束标�? (0=收敛�?, 1=稳定)
|
extern uint8_t g_loop_stable; // 稳定期结束标�? (0=收敛�?, 1=稳定)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ uint8_t g_flag_bt_state = 0; // 0 蓝牙没有连接,1 有蓝牙连接
|
|||||||
uint8_t g_function_mode = 0;
|
uint8_t g_function_mode = 0;
|
||||||
uint8_t g_fm_700bs_disable = 0; //0: 700bs protocol; 1 Modbus protocol
|
uint8_t g_fm_700bs_disable = 0; //0: 700bs protocol; 1 Modbus protocol
|
||||||
uint8_t g_output_radar_mode = 0;
|
uint8_t g_output_radar_mode = 0;
|
||||||
|
uint8_t g_opt_trigger = 0; // 光耦/雷达 处理后触发信号 (1=有效)
|
||||||
uint32_t g_sys_freq = 0;
|
uint32_t g_sys_freq = 0;
|
||||||
uint8_t g_storage_uart_num = 0;
|
uint8_t g_storage_uart_num = 0;
|
||||||
uint32_t g_storage_uart_baud = 19200;//9600;
|
uint32_t g_storage_uart_baud = 19200;//9600;
|
||||||
@@ -850,33 +851,168 @@ void cjq_srv(void){
|
|||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
* opt_input_poll — 光耦输入处理
|
* opt_input_poll — 光耦输入处理
|
||||||
*
|
*
|
||||||
* g_output_radar_mode == 0: 光耦复位模式 + 地感模式
|
* 产出 g_opt_trigger (1=有效, 0=无效),供继电器输出段融合判决。
|
||||||
* g_output_radar_mode >= 1: 雷达输入模式 (暂未实现)
|
* 各模式逻辑:
|
||||||
* 外部干接点接通 → PB10=0 → 计时; 保持 ≥500ms 后断开 → 上升沿 → 芯片复位
|
* MODE 0 (LOOP_X_RESET): 光耦=复位信号,≥400ms 低电平后上升沿芯片复位
|
||||||
|
* MODE 1 (LOOP_ONLY): 光耦忽略,g_opt_trigger=0
|
||||||
|
* MODE 2 (RADAR_ONLY): g_opt_trigger = 光耦信号 (3 样本多数表决防抖)
|
||||||
|
* MODE 3 (LOOP_OR): g_opt_trigger = 光耦信号
|
||||||
|
* MODE 4 (LOOP_AND): g_opt_trigger = 光耦信号
|
||||||
|
* MODE 5 (HUMAN_VD_MIX): 状态机 — 屏蔽→地感触发后解禁→离场 3s 防砸窗口
|
||||||
|
* MODE 6 (ETC): 状态机 — 屏蔽→地感触发后解禁→光耦断开 500ms 防抖
|
||||||
|
*
|
||||||
|
* 注意: mstick() 单位 5ms/tick
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
||||||
|
#define OPT_DEBOUNCE_CNT 6 // 防抖: 6 样本多数表决 (~30ms @5ms)
|
||||||
|
#define OPT_VM_WINDOW_TICK 600 // 人车混行防砸窗口: 600×5ms=3s
|
||||||
|
#define OPT_ETC_DEBOUNCE_TICK 100 // ETC 防抖: 100×5ms=500ms
|
||||||
|
|
||||||
|
/* 人车混行 / ETC 状态机 */
|
||||||
|
#define OPT_STATE_IDLE 0 // 雷达屏蔽,等线圈触发
|
||||||
|
#define OPT_STATE_ARMED 1 // 雷达解禁,地感 || 雷达
|
||||||
|
#define OPT_STATE_WINDOW 2 // 防砸窗口 (HUMAN_VD_MIX 专用)
|
||||||
|
#define OPT_STATE_DEBOUNCE 3 // 防抖释放 (ETC 专用)
|
||||||
|
|
||||||
static void opt_input_poll(void)
|
static void opt_input_poll(void)
|
||||||
{
|
{
|
||||||
static uint32_t _opt_low_since = 0; // PB10 变低的时刻
|
uint8_t raw = (OPT_IN1 == 0) ? 1 : 0; // 0=低电平有效→1=active
|
||||||
static uint8_t _opt_armed = 0; // 低电平已保持 ≥500ms, 等待上升沿
|
|
||||||
|
|
||||||
if (g_output_radar_mode) {
|
/*--- 光耦信号防抖: 3-sample 多数表决 ---*/
|
||||||
_opt_low_since = 0;
|
static uint8_t _db_hist = 0; // 位历史: bit0=最新
|
||||||
_opt_armed = 0;
|
_db_hist = (uint8_t)((_db_hist << 1) | raw);
|
||||||
|
{
|
||||||
|
uint8_t ones = 0;
|
||||||
|
uint8_t mask = _db_hist & 0x07; // 取低 3 位
|
||||||
|
if (mask & 0x01) ones++;
|
||||||
|
if (mask & 0x02) ones++;
|
||||||
|
if (mask & 0x04) ones++;
|
||||||
|
raw = (ones >= 2) ? 1 : 0; // ≥2票 → 有效
|
||||||
|
}
|
||||||
|
|
||||||
|
/*================================================================
|
||||||
|
* 模式 0 — 光耦复位
|
||||||
|
*================================================================*/
|
||||||
|
if (g_output_radar_mode == OUTPUT_MODE_LOOP_X_RESET) {
|
||||||
|
static uint32_t _rst_low_since = 0;
|
||||||
|
static uint8_t _rst_armed = 0;
|
||||||
|
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
if (OPT_IN1 == 0) { // 干接点接通 → 低电平
|
||||||
|
if (_rst_low_since == 0) {
|
||||||
|
_rst_low_since = mstick();
|
||||||
|
} else if (!_rst_armed && (mstick() - _rst_low_since >= 80)) {
|
||||||
|
_rst_armed = 1; // 满足 ≥400ms, 等待上升沿
|
||||||
|
}
|
||||||
|
} else { // 干接点断开 → 高电平
|
||||||
|
if (_rst_armed) {
|
||||||
|
SYS_ResetExecute(); // 上升沿触发芯片复位
|
||||||
|
}
|
||||||
|
_rst_low_since = 0;
|
||||||
|
_rst_armed = 0;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OPT_IN1 == 0) { // 干接点接通 → 低电平
|
/*================================================================
|
||||||
if (_opt_low_since == 0) {
|
* 模式 1 — 纯地感
|
||||||
_opt_low_since = mstick();
|
*================================================================*/
|
||||||
} else if (!_opt_armed && (mstick() - _opt_low_since >= 80)) { // 100 tick × 5ms = 500ms
|
if (g_output_radar_mode == OUTPUT_MODE_LOOP_ONLY) {
|
||||||
_opt_armed = 1; // 满足 500ms, 等待上升沿
|
g_opt_trigger = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*================================================================
|
||||||
|
* 模式 2/3/4 — 纯雷达 / 或 / 与
|
||||||
|
* g_opt_trigger 直出光耦信号, 融合判决在继电器输出段
|
||||||
|
*================================================================*/
|
||||||
|
if (g_output_radar_mode == OUTPUT_MODE_RADAR_ONLY ||
|
||||||
|
g_output_radar_mode == OUTPUT_MODE_LOOP_OR_RADAR ||
|
||||||
|
g_output_radar_mode == OUTPUT_MODE_LOOP_AND_RADAR) {
|
||||||
|
g_opt_trigger = raw;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*================================================================
|
||||||
|
* 模式 5/6 — 人车混行 / ETC (状态机)
|
||||||
|
*================================================================*/
|
||||||
|
{
|
||||||
|
static uint8_t _opt_state = OPT_STATE_IDLE;
|
||||||
|
static uint8_t _opt_mode_last = 0xFF;
|
||||||
|
static uint32_t _opt_timer_start = 0;
|
||||||
|
|
||||||
|
/* 模式切换 → 状态机复位 */
|
||||||
|
if (_opt_mode_last != g_output_radar_mode) {
|
||||||
|
_opt_mode_last = g_output_radar_mode;
|
||||||
|
_opt_state = OPT_STATE_IDLE;
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else { // 干接点断开 → 高电平
|
|
||||||
if (_opt_armed) {
|
uint8_t coil_active = (loop1_VD_FLAG | loop1_FLAG_OUT) ? 1 : 0;
|
||||||
SYS_ResetExecute(); // 上升沿触发芯片复位
|
|
||||||
|
switch (_opt_state) {
|
||||||
|
|
||||||
|
case OPT_STATE_IDLE:
|
||||||
|
/* 雷达屏蔽, 等线圈触发 */
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
if (coil_active) {
|
||||||
|
_opt_state = OPT_STATE_ARMED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_STATE_ARMED:
|
||||||
|
/* 雷达解禁: 地感 || 雷达 (OR 关系) */
|
||||||
|
g_opt_trigger = raw;
|
||||||
|
if (!coil_active && !raw) {
|
||||||
|
/* 两者均释放 → 进入释放过渡 */
|
||||||
|
if (g_output_radar_mode == OUTPUT_MODE_HUMAN_VD_MIX) {
|
||||||
|
_opt_state = OPT_STATE_WINDOW;
|
||||||
|
_opt_timer_start = mstick();
|
||||||
|
} else { // ETC
|
||||||
|
_opt_state = OPT_STATE_DEBOUNCE;
|
||||||
|
_opt_timer_start = mstick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_STATE_WINDOW: /* HUMAN_VD_MIX 专用: 3s 防砸窗口 */
|
||||||
|
if (coil_active) {
|
||||||
|
/* 车辆重新上线圈 → 回到解禁态 */
|
||||||
|
_opt_state = OPT_STATE_ARMED;
|
||||||
|
g_opt_trigger = raw;
|
||||||
|
} else if (raw) {
|
||||||
|
/* 雷达检测到人 → 立即触发, 窗口复位 */
|
||||||
|
g_opt_trigger = 1;
|
||||||
|
_opt_timer_start = mstick();
|
||||||
|
} else {
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
if (mstick() - _opt_timer_start >= OPT_VM_WINDOW_TICK) {
|
||||||
|
/* 3s 内无雷达触发 → 回到屏蔽态, 落杆 */
|
||||||
|
_opt_state = OPT_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_STATE_DEBOUNCE: /* ETC 专用: 500ms 防抖 */
|
||||||
|
if (coil_active || raw) {
|
||||||
|
/* 重新触发 → 取消防抖, 回到解禁态 */
|
||||||
|
_opt_state = OPT_STATE_ARMED;
|
||||||
|
g_opt_trigger = raw;
|
||||||
|
} else {
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
if (mstick() - _opt_timer_start >= OPT_ETC_DEBOUNCE_TICK) {
|
||||||
|
/* 500ms 无触发 → 确认释放 */
|
||||||
|
_opt_state = OPT_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_opt_state = OPT_STATE_IDLE;
|
||||||
|
g_opt_trigger = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_opt_low_since = 0;
|
|
||||||
_opt_armed = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1234,9 +1370,35 @@ void TMR1_IRQHandler(void)
|
|||||||
{
|
{
|
||||||
switch(g_loop_cng_unit.output_mode)
|
switch(g_loop_cng_unit.output_mode)
|
||||||
{ // 输出方式
|
{ // 输出方式
|
||||||
case 0: // 存在输出
|
case 0: // 存在输出 (线圈+光耦融合判决)
|
||||||
{
|
{
|
||||||
if(loop1_VD_FLAG | loop1_FLAG_OUT)// 输出存在信号
|
uint8_t coil_sig = (loop1_VD_FLAG | loop1_FLAG_OUT) ? 1 : 0;
|
||||||
|
uint8_t relay_on = 0;
|
||||||
|
|
||||||
|
switch (g_output_radar_mode) {
|
||||||
|
case OUTPUT_MODE_LOOP_ONLY:
|
||||||
|
case OUTPUT_MODE_LOOP_X_RESET:
|
||||||
|
relay_on = coil_sig;
|
||||||
|
break;
|
||||||
|
case OUTPUT_MODE_RADAR_ONLY:
|
||||||
|
relay_on = g_opt_trigger;
|
||||||
|
break;
|
||||||
|
case OUTPUT_MODE_LOOP_OR_RADAR:
|
||||||
|
relay_on = coil_sig || g_opt_trigger;
|
||||||
|
break;
|
||||||
|
case OUTPUT_MODE_LOOP_AND_RADAR:
|
||||||
|
relay_on = coil_sig && g_opt_trigger;
|
||||||
|
break;
|
||||||
|
case OUTPUT_MODE_HUMAN_VD_MIX:
|
||||||
|
case OUTPUT_MODE_ETC:
|
||||||
|
relay_on = coil_sig || g_opt_trigger;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
relay_on = coil_sig;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(relay_on)// 输出存在信号
|
||||||
{
|
{
|
||||||
RLY1_ON;
|
RLY1_ON;
|
||||||
g_loop_acs_info.relay1_state = 1;
|
g_loop_acs_info.relay1_state = 1;
|
||||||
|
|||||||
@@ -4,6 +4,80 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-28 (午后) — 光耦输出模式完整实现:6 种融合逻辑 + 状态机
|
||||||
|
|
||||||
|
### 架构
|
||||||
|
|
||||||
|
`opt_input_poll()` 处理光耦输入 → 产出 `g_opt_trigger` (1=有效) → TMR1 ISR 继电器输出段 `case 0` 根据 `g_output_radar_mode` 做融合判决。
|
||||||
|
|
||||||
|
```
|
||||||
|
光耦 PB10 → 3样本多数表决防抖 → opt_input_poll() → g_opt_trigger
|
||||||
|
↓
|
||||||
|
线圈 VD_FLAG/FLAG_OUT → coil_sig ──────────→ 融合判决 → RLY1
|
||||||
|
↑
|
||||||
|
g_output_radar_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### 各模式实现
|
||||||
|
|
||||||
|
| 模式 | 值 | `opt_input_poll()` | 继电器 `case 0` 融合公式 |
|
||||||
|
|------|-----|-------------------|--------------------------|
|
||||||
|
| LOOP_X_RESET | 0 | 光耦复位 (400ms低→上升沿→SYS_ResetExecute) | `coil_sig` |
|
||||||
|
| LOOP_ONLY | 1 | return, g_opt_trigger=0 | `coil_sig` |
|
||||||
|
| RADAR_ONLY | 2 | g_opt_trigger = 光耦信号 | `g_opt_trigger` |
|
||||||
|
| LOOP_OR_RADAR | 3 | g_opt_trigger = 光耦信号 | `coil_sig \|\| g_opt_trigger` |
|
||||||
|
| LOOP_AND_RADAR | 4 | g_opt_trigger = 光耦信号 | `coil_sig && g_opt_trigger` |
|
||||||
|
| HUMAN_VD_MIX | 5 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
|
||||||
|
| ETC | 6 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
|
||||||
|
|
||||||
|
> 注: `coil_sig = (loop1_VD_FLAG | loop1_FLAG_OUT)` — 含离开脉冲保持
|
||||||
|
|
||||||
|
### HUMAN_VD_MIX 状态机 (人车混行防砸)
|
||||||
|
|
||||||
|
```
|
||||||
|
IDLE (雷达屏蔽, 仅线圈)
|
||||||
|
│ 线圈检测到车
|
||||||
|
▼
|
||||||
|
ARMED (雷达解禁, 线圈||雷达)
|
||||||
|
│ 两者均释放
|
||||||
|
▼
|
||||||
|
WINDOW (3s 防砸窗口)
|
||||||
|
│ 雷达触发 → g_opt_trigger=1 → 继电器吸合, 窗口复位
|
||||||
|
│ 线圈上线 → 回到 ARMED
|
||||||
|
│ 3s 超时无触发 → 回到 IDLE, 落杆
|
||||||
|
```
|
||||||
|
|
||||||
|
定时参数: `OPT_VM_WINDOW_TICK = 600` (600×5ms = 3s)
|
||||||
|
|
||||||
|
### ETC 状态机
|
||||||
|
|
||||||
|
```
|
||||||
|
IDLE (雷达屏蔽, 仅线圈)
|
||||||
|
│ 线圈检测到车
|
||||||
|
▼
|
||||||
|
ARMED (雷达解禁, 线圈||雷达)
|
||||||
|
│ 两者均释放
|
||||||
|
▼
|
||||||
|
DEBOUNCE (500ms 防抖)
|
||||||
|
│ 线圈/雷达重新触发 → 回到 ARMED
|
||||||
|
│ 500ms 超时 → 回到 IDLE, 落杆
|
||||||
|
```
|
||||||
|
|
||||||
|
定时参数: `OPT_ETC_DEBOUNCE_TICK = 100` (100×5ms = 500ms)
|
||||||
|
|
||||||
|
### 光耦防抖
|
||||||
|
|
||||||
|
所有非复位模式共用 3 样本多数表决 (`OPT_DEBOUNCE_CNT=6`): 最近 3 次采样中 ≥2 票即判定有效,等效 ~30ms 消抖。
|
||||||
|
|
||||||
|
### 文件变更
|
||||||
|
|
||||||
|
| 文件 | 变更 |
|
||||||
|
|------|------|
|
||||||
|
| `peripheral_main.c` | +`g_opt_trigger` 全局变量, `opt_input_poll()` 重写 (120→180行), TMR1 ISR `case 0` 融合判决 |
|
||||||
|
| `cmcng.h` | +`extern uint8_t g_opt_trigger` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-07-28 — 光耦输出模式升级:`DLD_OUTPUT_MODE` 枚举 + `direction_mode` 低四位取值
|
## 2026-07-28 — 光耦输出模式升级:`DLD_OUTPUT_MODE` 枚举 + `direction_mode` 低四位取值
|
||||||
|
|
||||||
### 背景
|
### 背景
|
||||||
|
|||||||
Reference in New Issue
Block a user