自锁我的理解就是过流保护负载,电流恢复重新运行。
打嗝模式的话,我的理解就是出现临时性过载情况(如电机启动时的浪涌电流)允许短暂重试的应用场景需要保持系统运行而不是完全停机的情况。所以每当检测到过流时,系统会关闭电机并进入打嗝模式每隔 2秒尝试重启一次电机每次重启后检查电流,如果仍然过高则再次关闭。
这里我用的是滴答定时器实现非阻塞延时。与Flash内部的电流阈值进行比较。
源码如下
#include "Motor_Lock.h" #include "sFlash.h" static uint8_t overcurrent_flag = 0; // 过流标志 static uint32_t hiccup_start_time = 0; // 打嗝模式开始时间 static uint8_t hiccup_attempts = 0; // 重试次数计数器 #define HICCUP_INTERVAL 2000 // 重试间隔(ms) #define MAX_HICCUP_ATTEMPTS 5 // 最大重试次数 void Motor_Current_Check(void) { static uint32_t lasttime = 0; // 每10ms执行一次完整检查 if(HAL_GetTick() - lasttime >= 10) { lasttime = HAL_GetTick(); Analysis_data(); // 正常运行状态检测过流 if(!overcurrent_flag) { if(data.Current > SFData.currentThreshold) { overcurrent_flag = 1; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 关闭电机 // 初始化打嗝模式 hiccup_start_time = HAL_GetTick(); hiccup_attempts = 0; } } // 打嗝模式处理 else { // 检查是否启用打嗝模式 if(SFData.enableHiccupMode) { // 计算重试间隔 if(HAL_GetTick() - hiccup_start_time >= HICCUP_INTERVAL) { hiccup_start_time = HAL_GetTick(); hiccup_attempts++; // 尝试重启电机 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 给电机一点时间启动,然后检查电流 HAL_Delay(50); // 短暂延时,实际应用中可能需要更优雅的实现 Analysis_data(); // 如果电流仍然过高,再次关闭电机 if(data.Current > SFData.currentThreshold) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 达到最大重试次数后进入永久锁定 if(hiccup_attempts >= MAX_HICCUP_ATTEMPTS) { SFData.enableHiccupMode = 0; // 禁用打嗝模式,进入永久锁定 } } else { // 电流正常,退出打嗝模式 overcurrent_flag = 0; hiccup_attempts = 0; } } } } } } // 蓝牙触发自锁功能 void ManualMotorLockout(void) { overcurrent_flag = 1; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); SFData.enableHiccupMode = 0; // 禁用打嗝模式 } // 复位函数,启动打嗝 void ResetOvercurrentProtection(void) { overcurrent_flag = 0; hiccup_attempts = 0; SFData.enableHiccupMode = 1; // 重新启用打嗝模式 if(data.Current <= SFData.currentThreshold) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); } }
2.Motor_Lock.h
源码如下
#ifndef __Motor_Lock_H_ #define __Motor_Lock_H_ #include "main.h" void ManualMotorLockout(void); void Motor_Current_Check(void); void ResetOvercurrentProtection(void); #endif
3.蓝牙手动触发代码如下
void HandleCommand(CommandType type) { switch (type) { case CMD_THRESHOLD: { char *param = (char *)BLE_data.receivedata + 17; int threshold = atoi(param); printf("Set current threshold to %d mA\r\n", threshold); SetCurrentThreshold(threshold); } break; case CMD_RECOVERY: EnableRecoveryControl(); break; case CMD_CAN_RUN: StartMotor(); break; case CMD_STOP_RUN: StopMotor(); break; case CMD_MODE1: SwitchToMode1(); break; case CMD_MODE2: SwitchToMode2(); break; default: break; } } int Current_Param_Project=0; void SetCurrentThreshold(uint32_t data) { Flash_WriteCurrentThreshold(data); } void EnableRecoveryControl(void) { } void StartMotor(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); } void StopMotor(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); } void SwitchToMode1(void) { ManualMotorLockout(); } void SwitchToMode2(void) { ResetOvercurrentProtection(); }