受远在太平洋的拉尼娜现象影响,今年入夏困难,已经五月天气依然凉爽。风扇基本用不上,如果实在想用最好限制一下转速,免得凉意更浓。
增加几个功能模式,实现对电机转速控制与电流监测形成完整闭环。
一、电子开关控制风扇转速
使用电子开关可以控制风扇的转速,也可以称电子开关为PWM调节电子开关控制板或大功率MOS管模块

特点:
采用双MOS并联有源输出,内阻低,电流打,功率强,常温下15A,400W,宽电压,支持PWM,工作电压:DC5V-36V
触发信号源:数字量高低电平(DC3.3V-20V),可以接单片机IO口,PLC接口、直流电源等,可以接PWM信号,信号频率0-20khz。
输出能力:直流DC5V-36V,常温下15A,400W,辅助散热条件下,最大电流可达30A
二、旋转编码器改变PWM占空比
电子开关的PWM信号由单片机提供,PWM的占空比决定了电子开关输出功率。
为了控制PWM占空比,再添加一个旋转编码器

三、整理一下示意图

1、旋转编码器调节电子开关PWM信号的占空比
2、电子开关在PWM信号作用下,开关,调速控制电机(风扇)旋转
3、INA219测量电压电流功率,如果电流超过电流阈值,启动过流保护(自锁或打嗝)
4、OLED显示相关信息
实物:
电子开关

旋转编码器

风扇

取电5V

四、软件部分
1、电子开关使用TIM1

频率:32MHZ/(31+1)/(49+1)=200KHZ
占空比:25/50=50%
改变占空比函数,通过这个函数可以控制风扇转速:
void TIM_SetTIM1Compare2(uint32_t compare)
{
if(compare<0||compare>50) return;
__HAL_TIM_SET_COMPARE(htimPwm, TIM_CHANNEL_2, compare); // compare为新的占空比值
}TIM1配置函数,启动PWM。
void pwm_config(TIM_HandleTypeDef *htim)
{
htimPwm=htim;
if (HAL_TIM_PWM_Start(htimPwm, TIM_CHANNEL_2) != HAL_OK)
{
/* PWM Generation Error */
Error_Handler();
}
}2、旋转编码器使用TIM3

GPIO使用:

void encoder_config(TIM_HandleTypeDef *htim)
{
htimEncoder=htim;
__HAL_TIM_GET_COUNTER(htimEncoder) = 40; //计数器值置位
HAL_TIM_Encoder_Start(htimEncoder, TIM_CHANNEL_ALL);
}
void encoder_process(void)
{
CaptureNumber=get_encoder_value();
if(CaptureNumber<0){
CaptureNumber=0;
__HAL_TIM_GET_COUNTER(htimEncoder) = 0;
}
if(CaptureNumber>50){
CaptureNumber=50;
__HAL_TIM_GET_COUNTER(htimEncoder) = 50;
}
printf("电子开关PWM占空比:%d%%\r\n",CaptureNumber*2);
TIM_SetTIM1Compare2(CaptureNumber);
//}
}设置编码器起始值40(最大50,40对应TIM180%占空比)
调节编码器数值在0-50之间,对应TIM1(0%-100%占空比)
通过get_encoder_value获得当期编码器数值:
int16_t get_encoder_value() {
return (int16_t)TIM3->CNT; // 返回当前编码器计数值(带方向)
}通过__HAL_TIM_GET_COUNTER(htimEncoder) 设置编码器数值。
通过TIM_SetTIM1Compare2(CaptureNumber)以CaptureNumber为参数设置电子开关占空比。
3、INA219过流处理
#define cur_threshold 190 //过流阈值190毫安
uint8_t overcur_flag=0; //过流自锁生效标志
uint8_t hiccup_flag=0; //过流打嗝生效标志
volatile uint8_t wait_flag=0; //过流自锁后等待标志
#define Self_Locking_Mode 0 //自锁模式
#define Hiccup_Mode 1 //打嗝模式
static uint8_t CTR_Mode=Self_Locking_Mode; //当期过流模式选择:缺省自锁
用USER BUTTON(PC13)外部中断方式切换过流处理模式:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == B1_Pin) { // 检查是哪个引脚触发的中断
if(CTR_Mode==Self_Locking_Mode){
CTR_Mode=Hiccup_Mode;
printf("Change mode to Hiccup_Mode\r\n");
}else
{
CTR_Mode=Self_Locking_Mode;
printf("Change mode to Self_Locking_Mode\r\n");
}
}
}处理INA219传感器数据并显示:
void INA219_process(void)
{
static uint32_t Hiccup_Time;
static uint32_t lastDisplayUpdate = 0;
const uint32_t DISPLAY_UPDATE_INTERVAL = 250; // 显示更新间隔(ms)
// 读取传感器数据
float busVoltage = INA219_ReadBusVoltage();
float shuntVoltage = INA219_ReadShuntVoltage();
float current = INA219_ReadCurrent();
float power = busVoltage * current;
// 调试信息输出
printf("Bus Voltage: %.2f V\n", busVoltage);
printf("Shunt Voltage: %.2f mV\n", shuntVoltage * 1000);
printf("Current: %.2f mA\n", current * 1000);
printf("Power: %.2f mW\n", power * 1000);
printf("\r\n");
// Hiccup模式处理
if((HAL_GetTick() - Hiccup_Time) >= 3000 && hiccup_flag == 1 && CTR_Mode == Hiccup_Mode)
{
hiccup_flag = 0;
Hiccup_Time = HAL_GetTick();
__HAL_TIM_SET_COUNTER(htimEncoder, 40);
TIM_SetTIM1Compare2(40);
}
// 过流处理
if(current * 1000 > cur_threshold)
{
if(CTR_Mode == Self_Locking_Mode)
{
overcur_flag = 1;
}
else if(CTR_Mode == Hiccup_Mode)
{
hiccup_flag = 1;
}
__HAL_TIM_SET_COUNTER(htimEncoder, 0);
TIM_SetTIM1Compare2(0);
}
// 显示处理
if(wait_flag == 1)
{
App_Show_Clock_Info();
HAL_Delay(200);
}
if(CaptureNumber > 0 && wait_flag == 1)
{
wait_flag = 0;
overcur_flag = 0;
OLED_ShowChineseString16(0, 0, (uint8_t*)"DIY功率监测与控制", 1);
}
if(wait_flag != 1)
{
if(overcur_flag == 1 || hiccup_flag == 1)
{
App_Show_Clock_Info();
HAL_Delay(500);
wait_flag = 1;
}
else
{
// 仅在需要更新时刷新显示
if(HAL_GetTick() - lastDisplayUpdate >= DISPLAY_UPDATE_INTERVAL)
{
lastDisplayUpdate = HAL_GetTick();
char buff[20] = {0};
// 显示电流、电压、功率
sprintf(buff, "电流:%5.2fmA ", current * 1000);
OLED_ShowChineseString16(0, 16, (uint8_t*)buff, 1);
sprintf(buff, "电压:%5.2fV ", busVoltage);
OLED_ShowChineseString16(0, 32, (uint8_t*)buff, 1);
sprintf(buff, "功率:%5.2fmW ", power * 1000);
OLED_ShowChineseString16(0, 48, (uint8_t*)buff, 1);
// 绘制条形图边框
OLED_DrawRectangle(117, 16, 127, 63);
// 更新垂直条形图(高度根据CaptureNumber计算)
OLED_DrawVerticalBar(117, 16, 10, 47, 2 * CaptureNumber);
// 根据控制模式显示不同图标
if(CTR_Mode == Self_Locking_Mode)
{
OLED_DrawFillRectangle(111, 17, 115, 40);
OLED_DrawFillRectangleClear(111, 41, 115, 63);
}
else if(CTR_Mode == Hiccup_Mode)
{
OLED_DrawFillRectangle(111, 41, 115, 63);
OLED_DrawFillRectangleClear(111, 17, 115, 40);
}
// 优化后的滚动效果
for(uint8_t i = 0; i < 4; i++)
{
OLED_ShiftTwoRowsLeft(0, 3);
HAL_Delay(DISPLAY_UPDATE_INTERVAL);
}
OLED_Refresh();
}
}
}
}4、OLED显示相关
在第一行显示过流状态:
void App_Show_Clock_Info(void)
{
static uint8_t i=0;
if(CTR_Mode==Self_Locking_Mode)
{
OLED_ShowChineseString16(0,0,(uint8_t*)"过流状态:Locking ",i);
}else
OLED_ShowChineseString16(0,0,(uint8_t*)"过流状态:Hiccup ",i);
OLED_Refresh();
i=~i;
}分段显示Bmp:从上到下分四段显示bmp1,最后显示Title
void App_Show_Title_Info(void)
{
OLED_Clear();
OLED_Copy_Bmp(0,0,128,16,bmp1,0,0);
OLED_Refresh();
HAL_Delay(100);
OLED_Copy_Bmp(0,16,128,16,bmp1,0,16);
OLED_Refresh();
HAL_Delay(100);
OLED_Copy_Bmp(0,32,128,16,bmp1,0,32);
OLED_Refresh();
HAL_Delay(100);
OLED_Copy_Bmp(0,48,128,16,bmp1,0,48);
OLED_Refresh();
HAL_Delay(100);
OLED_Clear();
OLED_Clear_Buffer();
OLED_ShowChineseString16(0,0,(uint8_t*)"DIY功率监测与控制",1);
OLED_Refresh();
}
绘制垂直百分比条形图函数,用来绘制TIM1占空比示意
/**
* @brief 绘制垂直百分比条形图
* @param x: 条形图左上角x坐标
* @param y: 条形图左上角y坐标
* @param width: 条形图宽度
* @param height: 条形图总高度(100%对应的高度)
* @param percent: 要显示的百分比(0-100)
* @param filled: 是否填充(1=填充,0=空心)
* @retval 无
*/
void OLED_DrawVerticalBar(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t percent)
{
// 计算实际填充高度
uint8_t bar_height = (height * percent) / 100;
// 确保不超过最大高度
if(bar_height > height) {
bar_height = height;
}
// 计算条形图底部y坐标
uint8_t bar_bottom = y + height - 1;
// 计算填充部分的顶部y坐标
uint8_t fill_top = bar_bottom - bar_height + 1;
OLED_DrawFillRectangleClear(x,y,x+width,bar_bottom-bar_height);
// 绘制填充条形图
OLED_DrawFillRectangle(x, fill_top, x + width - 1, bar_bottom);
}
五、运行效果
1、自锁

2、打嗝

3、调节电子开关输入信号占空比

4、切换过流模式

我要赚赏金
