最近用到了低压大功率有刷直流电机, 需要调速控制, 时间紧急,来不及加速度反馈, 直接使用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; } |