本文共 1271 字,大约阅读时间需要 4 分钟。
计算机图形学中绘制直线的Bresenham算法原本是用在绘图仪上控制X轴方向和Y轴方向的两部电机的,最近遇到一个十分类似的步进电机控制问题,用Bresenham算法恰好能解决。
问题描述:有左右两个相同的步进电机,用8051单片机控制L297 + L298芯片驱动,需要它们同时转动(同时启动,同时停止),但转速不同。例如左侧电机正转180步,同时右侧电机反转97步。这就好比从原点出发画一条到点(180, -97)的直线。
与电机的接口已抽象为四个函数:
void MotorLeftShrink(); // 左侧电机收紧绳索void MotorLeftLoose(); // 左侧电机放松绳索void MotorRightShrink(); // 右侧电机收紧绳索void MotorRightLoose(); // 右侧电机放松绳索
另外有两个辅助函数,分别控制左右电机:
void MotorLeftStep(int direct){ if (direct == 1) MotorLeftLoose(); else if (direct == -1) MotorLeftShrink();}
void MotorRightStep(int direct){ if (direct == 1) MotorRightLoose(); else if (direct == -1) MotorRightShrink();}
现在的任务是写一个函数MoveMotor(),有四个参数,分别为两个电机转的步数和方向,让它控制这两部电机同时运转。我用的是整数版本的直线Bresenham算法,取自《计算机图形学的算法基础》一书。
// 参数:absDL、absDR 分别是左右电机转动的步数
// sDL、sDR 分别是左右电机转动的方向 void MoveMotor3(int absDL, int absDR, int sDL, int sDR){ int steps = max(absDL, absDR); int eL = 2*absDL - steps; // 误差累积项 int eR = 2*absDR - steps; // 误差累积项 int cntL = 0; int cntR = 0; for (int i = 0; i < steps; ++i) { // 以转动步数较多的为主,进行循环 while (eL > 0) { ++cntL; MotorLeftStep(sDL); eL -= 2*steps; } eL += 2*absDL;while (eR > 0) {
++cntR; MotorRightStep(sDR); eR -= 2*steps; } eR += 2*absDR; wait_ms(15); // 等待 } assert(cntL == absDL); assert(cntR == absDR);}程序稍作修改后在KEIL C51上编译通过,电机运转情况良好:)
转载地址:http://fhvpi.baihongyu.com/