feat(buzzer): 台架调试模式把 CAN 掉线警告音换成循环旋律

台架调试时 CAN 设备(尤其 Pitch)掉线会按 legacy 语义每 2s 响 n 下,连续
滴滴声很吵且影响听其它声音,故加一个开关:

  robot_param.h -> 台架调试开关
  #define DEBUG_BUZZER_MELODY  1   // 1=警告音换旋律;0=legacy 报警(比赛用)

实现分三处:
- robot_param.h: 新增开关,与 DEBUG_SHOOT_WITHOUT_REFEREE 放在同一分区
- modules/BUZZER: 新增 buzzer_play_melody(step) —— 按固定 100ms/步 推进,
  内部对旋律总步数取模自动循环;旋律表 buzzer_melody[] 用"上行分解和弦 +
  回落"共 14 步(1.4s),空拍 BUZZER_P 作断音,选音限定中音3~高音2 避免刺耳。
  驱动层本身不判断开关,保持纯外设职责,只是多了一个音符序列接口。
- monitor_task.c: CAN 掉线分支按开关二选一。旋律模式下步进用本任务自身的
  100ms 节拍(与文件里已有的遥控器连接音效同一写法),不用 HAL_GetTick
  采样,避免周期抖动漏掉或重复音符。

设计取舍: 只替换"声音",不替换"灯语" —— 红灯常亮、遥控器掉线红灯双闪、
BMI088 失败绿灯双闪等 LED 语义完全不变,因此调试时仍能一眼看出是哪台
设备掉线;linkcheck_first_offline() 也保留调用,方便在调试器里直接看结果。
比赛前把 DEBUG_BUZZER_MELODY 改回 0 即恢复 legacy 报警。

两个工程同步修改,内容保持一致。
This commit is contained in:
2026-09-12 11:19:59 +08:00
parent 3e1bae6b98
commit 72bf925f47
8 changed files with 102 additions and 6 deletions
+20 -3
View File
@@ -8,6 +8,8 @@
* 连接音效 = 遥控器上线瞬间两声上扬(M3->H3)
* CAN 掉线蜂鸣(legacy 语义): 按设备序号 n 响 n 下,2s 一轮,每次只报
* 最先掉线的设备,设备序号表见 linkcheck_first_offline()
* 调试模式(DEBUG_BUZZER_MELODY=1,见 robot_param.h): 上述蜂鸣改为循环
* 播放旋律,避免台架调试时连续滴滴声;红灯常亮等灯语不受影响
* 看门狗: IWDG 约 2.5s;上电 5s 宽限期无条件喂,之后仅当全部任务心跳正常
* 才喂——任何任务卡死都会复位,不会整车失控
* ========================================================================== */
@@ -170,10 +172,24 @@ void LED_Task(void const * argument)
if (can_alarm)
{
led_set_red(1);
int8_t id = linkcheck_first_offline();
if (id >= 0)
/* 掉线设备序号(0 起)。旋律模式下不用它的返回值,仍保留调用:
* 一是调试时可直接在调试器里看 linkcheck 结果,二是避免该静态
* 函数在 DEBUG_BUZZER_MELODY=1 时被判为未使用而报警告 */
int8_t first_offline = linkcheck_first_offline();
#if DEBUG_BUZZER_MELODY
/* 调试模式:警告音替换为循环旋律(见 modules/BUZZER/buzzer.h)。
* 红灯常亮与其它灯语不变,"哪台设备掉线"这一信息不会丢。
* 步进用本任务自身的 100ms 节拍,不靠 HAL_GetTick 采样,避免周期
* 抖动漏掉或重复某个音符 */
static uint16_t melody_step = 0;
(void)first_offline;
buzzer_play_melody(melody_step++);
#else
if (first_offline >= 0)
{
uint8_t n = (uint8_t)(id + 1);
uint8_t n = (uint8_t)(first_offline + 1);
uint8_t w = counter % 20; // 2s 窗口
/* 第 j 声:占 w=[2j,2j+1],响 100ms 停 100ms */
if ((w / 2) < n && (w % 2) == 0)
@@ -183,6 +199,7 @@ void LED_Task(void const * argument)
}
else
buzzer_off();
#endif
}
else
{
+5
View File
@@ -125,6 +125,11 @@
#define DEBUG_SHOOT_WITHOUT_REFEREE 1 // 1=无裁判系统时也允许开摩擦轮(台架调试用),比赛请改 0
#define GIMBAL_RAMMER_INSTALLED 0 // 1=拨弹 M2006 已安装;0=暂缺,不参与掉线判定
/* 1=调试模式:把 CAN 掉线警告音替换成循环播放的旋律(台架调试时避免连续滴滴声
* 干扰)。红灯常亮与其它灯语完全不变,仍能看出是哪台设备掉线;比赛请改 0。
* 旋律音符表见 modules/BUZZER/buzzer.c 的 buzzer_melody[] */
#define DEBUG_BUZZER_MELODY 1
/* ============================ 掉线检测 ============================ */
#define DEVICE_OFFLINE_TIME_MS 100 // CAN 设备/裁判系统掉线判定时间
#define CTOC_OFFLINE_TIME_MS 100 // 板间通讯掉线判定时间
+20
View File
@@ -42,3 +42,23 @@ void buzzer_off(void)
{
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
}
/* ==========================================================================
* 调试用旋律(见 buzzer.h):每步 100ms,空拍 BUZZER_P 为静音。
* 无源蜂鸣器只有单音,这里用"上行分解和弦 + 回落"拼成一句短旋律;选音限定
* 在中音 3 ~ 高音 2,避免刺耳。循环播放不会漏掉"有设备掉线"这一事实,
* 因为红灯常亮由 monitor_task 独立控制,与该旋律无关。
* 改旋律:直接增删这里的音符即可,长度会自动生效。
* ========================================================================== */
static const buzzer_tone_e buzzer_melody[] = {
BUZZER_M3, BUZZER_M5, BUZZER_M6, BUZZER_H1, BUZZER_P,
BUZZER_M6, BUZZER_H1, BUZZER_H2, BUZZER_P,
BUZZER_H1, BUZZER_M6, BUZZER_M5, BUZZER_M3, BUZZER_P,
};
void buzzer_play_melody(uint16_t step)
{
const uint16_t steps =
(uint16_t)(sizeof(buzzer_melody) / sizeof(buzzer_melody[0]));
buzzer_on(buzzer_melody[step % steps]);
}
+6
View File
@@ -16,4 +16,10 @@ typedef enum
extern void buzzer_init(void);
extern void buzzer_on(buzzer_tone_e tone);
extern void buzzer_off(void);
/* ---- 调试用旋律 ----
* 按固定 100ms/步 推进的短旋律(音符表见 buzzer.c),用于把掉线警告音换成
* 音乐。step 由调用方每 100ms 递增 1,内部对旋律总步数取模自动循环;
* 旋律中的空拍 BUZZER_P 由 buzzer_on() 解释为静音,用来断音。 */
extern void buzzer_play_melody(uint16_t step);
#endif