在过程贴中,成功驱动OLED、INA219模块,能够实时的显示电机的电压、电流、功率等电气参数,在此基础上,添加电机的自锁、打嗝功能。自锁模式能够在电机过流后自动关闭电机;打嗝模式则是在电机产生过流后,关闭电机一段时间,再重新启动电机。
// 过流阈值,单位mA volatile float OVERCURRENT_THRESHOLD = 90.0f; // 控制模式,0:自锁模式,1:打嗝模式 volatile uint8_t control_mode = 0; // 过流标志 volatile float overcurrent_flag = 0;
设定volatile修饰变量,防止编译器优化变量,每次访问时都从内存读取其最新值。
// 中位值平均滤波电流
float Med_Avg_Filter_Current(void)
{
unsigned int count, i, j, temp;
float value_buff[N]; // 存储电流采样值
float current_sum = 0;
// 采样N次电流
for (count = 0; count < N; count++)
{
value_buff[count] = INA219_ReadCurrent(); // 读取电流
delay_ms(2);
}
// 冒泡排序升序排列
for (j = 0; j < N - 1; j++)
{
for (i = 0; i < N - j - 1; i++)
{
if (value_buff[i] > value_buff[i + 1])
{
temp = value_buff[i];
value_buff[i] = value_buff[i + 1];
value_buff[i + 1] = temp;
}
}
}
// 排除最大和最小值,求中间项和
for (count = 1; count < N - 1; count++) // 过滤掉最大值和最小值
{
current_sum += value_buff[count];
}
// 返回滤波后的电流值
return (current_sum / (N - 2));
}采用中位值平均滤波电流,平滑电流显示,避免电流读数跳动太大。
编写一个过流检测函数,并将这个函数放到定时器中断函数里面,每100ms执行一次。继电器的PIN脚连接到LD2,这样可以通过LED直观的展示继电器通断状态。
/**
* @brief 过流检测
*
*/
void Overcurrent_Protection(void)
{
// 读取当前电流
float current = Med_Avg_Filter_Current();
// 判断是否超过阈值
if (current > OVERCURRENT_THRESHOLD)
{
if (!overcurrent_flag) // 如果当前没有触发过流
{
overcurrent_flag = 1; // 设置过流标志
LD2_OFF(); // 断开电机
}
}
else
{
if (overcurrent_flag) // 如果电流回落并且处于过流状态
{
if (control_mode == 0) // 自锁模式
{
LD2_OFF();
}
else if (control_mode == 1) // 打嗝模式
{
overcurrent_flag = 0;
}
}
}
}OLED设置了两个页面,采用中断按键的方式,大幅提高按键的灵敏度。
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line13) != RESET) // 确保是否产生了EXTI Line中断
{
// 按键按下,切换页面
if (current_page == 0)
{
OLED_Clear();
current_page = 1; // 更新为设置页
}
else
{
OLED_Clear();
current_page = 0; // 更新为首页
}
delay_ms(20);
EXTI_ClearITPendingBit(EXTI_Line13); // 清除中断标志位
}
}串口使用的USART2,但是在串口软件接收到的是乱码,大佬们可以看一下程序代码,指出其中的问题。
演示视频:
https://www.bilibili.com/video/BV16zN4zuEJ2/
程序放置于此,请结合上述使用:
我要赚赏金
