最近用到了低壓大功率有刷直流電機, 需要調速控制, 時間緊急,來不及加速度反饋, 直接使用PWM開環控制了。 根據功率估算了電流大概在10A左右,沒時間畫電路板,於是淘寶 找了下集成驅動模塊, 發現也就BTS7960 板橋芯片的模塊合適,於是買了3個, 模塊每個有2個 BTS7960, 組成一個H橋, 驅動一路電機, 需要2路。 由於之前沒有實際驅動過H橋, 看來下幾種驅動方式, 決定使用單橋臂 PWM調製 方法, 另一橋臂作爲方向使用, 這種情況下只有一路橋臂需要PWM引腳,實際分配引腳方便些, 但是有個問題,控制方向的橋臂驅動高電平時, pwm 橋臂側最小時 輸出低電平的話,其實是最大輸出, 想到2種辦法,一是更改輸出極性, 二是 使用最大PWM值減去計算的pwm值作爲 PWM輸出, 不想再初始化定時器,於是採用 減pwm的方法寫的。 H橋簡圖
考慮 方向橋臂有可能使用 繼電器 或 接觸器代替, 切換方向時 關閉使能了一段時間,避免驅動電機過程中切換方向,引起電弧,產生浪涌電壓,損壞器件。 另外需要注意 大功率電機 需要添加加減速控制邏輯, 加速過程會避免大電流衝擊, 減速過程能再生制動。 代碼如下:
typedef enum DIR_ENUM // 方向枚舉
{
DirForward = 0,
DirBackward = 1
}DirEnum;
/ 定義了個 最小PWM: BASE_PWM_VAL, pwm 映射到 百分比: BASE_PWM_PERC ~ 100
// 0 不要映射, 做 停止PWM用
u16 percConv(u32 pwm)
{
if(0 == pwm) return 0;
else return BASE_PWM_VAL + (pwm * (100 - BASE_PWM_PERC)) / 100;
}
// PCout(6)
// RUN_MOTR_EN PAout(8)
// 最少10mS 調用一次, 換向時 30mS內 無pwm輸出
void setLRPwm(u16 reaPwmL, u16 reaPwmR, DirEnum dirL, DirEnum dirR)
{
static DirEnum lastDirL, lastDirR;
static u8 reinL, reinR; // static u16 lastPwmL, lastPwmR;
reaPwmL = percConv(reaPwmL);
reaPwmR = percConv(reaPwmR);
// check max pwm
if(reaPwmL > MAX_PWM_VAL) reaPwmL = MAX_PWM_VAL;
if(reaPwmR > MAX_PWM_VAL) reaPwmR = MAX_PWM_VAL;
// 左或右 換向時, 重置 時間計數, 多少次內無PWM輸出
if(lastDirL != dirL)
{
reinL = 0;
lastDirL = dirL;
}
if(lastDirR != dirR)
{
reinR = 0;
lastDirR = dirR;
}
DIR_L = dirL;
DIR_R = dirR;
if(reinL < 4)
RUN_MOTL_EN = 0;
else
{
if(DirForward == dirL)
{
TIM_SetCompare3(TIM4, reaPwmL);
}else
TIM_SetCompare3(TIM4, FULL_PWM_VAL - reaPwmL);
if(0 == reaPwmL) RUN_MOTL_EN = 0;
else RUN_MOTL_EN = 1;
}
if(reinR < 3)
RUN_MOTR_EN = 0;
else
{
if(DirForward == dirR)
{
TIM_SetCompare4(TIM4, reaPwmR);
}else
TIM_SetCompare4(TIM4, FULL_PWM_VAL - reaPwmR);
if(0 == reaPwmR) RUN_MOTR_EN = 0;
else RUN_MOTR_EN = 1;
} // lastPwmL = reaPwmL; lastPwmR = reaPwmR;
reinL++; reinR++;
if(reinL > 200) reinL = 200;
if(reinR > 200) reinR = 200;
}