1. 直线插补基础实现

任务目标

实现二维平面内从起点 (x0, y0) 到终点 (x1, y1) 的直线插补,输出X轴与Y轴各自的步进脉冲序列。采用逐点比较法,每步仅沿单轴运动一个脉冲当量,保证合成轨迹逼近理想直线。

核心原理与算法

逐点比较法每步执行四个环节:偏差判别 → 坐标进给 → 偏差计算 → 终点判别。设直线起点在原点,终点为 (xe, ye),当前动点为 (xi, yi),偏差 F = xi·ye − yi·xe。第一象限内:F ≥ 0 时向 +X 进给,F' = F − ye;F < 0 时向 +Y 进给,F' = F + xe。总步数 N = |xe| + |ye|,每步递减,至零结束。

实现代码

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int x0, y0;      // 起点
    int x1, y1;      // 终点
    int pulse_x[1000]; // X轴脉冲序列: 1=正向, -1=反向, 0=无
    int pulse_y[1000]; // Y轴脉冲序列
    int step_count;    // 总步数
} LineInterp;

// 初始化插补器,计算总步数
void line_init(LineInterp *li, int x0, int y0, int x1, int y1) {
    li->x0 = x0; li->y0 = y0;
    li->x1 = x1; li->y1 = y1;
    li->step_count = abs(x1 - x0) + abs(y1 - y0);
}

// 执行直线插补,生成脉冲序列
void line_interpolate(LineInterp *li) {
    int dx = abs(li->x1 - li->x0);
    int dy = abs(li->y1 - li->y0);
    int sx = (li->x1 > li->x0) ? 1 : -1;  // X方向
    int sy = (li->y1 > li->y0) ? 1 : -1;  // Y方向
    
    int x = li->x0, y = li->y0;
    int F = 0;          // 偏差
    int n = li->step_count;
    int idx = 0;
    
    // 将终点平移到第一象限处理
    int xe = dx, ye = dy;
    
    while (n > 0) {
        if (F >= 0) {
            // 向X方向进给
            x += sx;
            F -= ye;
            li->pulse_x[idx] = sx;
            li->pulse_y[idx] = 0;
        } else {
            // 向Y方向进给
            y += sy;
            F += xe;
            li->pulse_x[idx] = 0;
            li->pulse_y[idx] = sy;
        }
        idx++;
        n--;
    }
    li->step_count = idx;
}

// 打印脉冲序列
void line_print(const LineInterp *li) {
    printf("步号\tX脉冲\tY脉冲\t当前位置\n");
    int x = li->x0, y = li->y0;
    for (int i = 0; i < li->step_count; i++) {
        x += li->pulse_x[i];
        y += li->pulse_y[i];
        printf("%d\t%+d\t%+d\t(%d, %d)\n", 
               i+1, li->pulse_x[i], li->pulse_y[i], x, y);
    }
    printf("终点: (%d, %d)\n", x, y);
}

int main() {
    LineInterp li;
    // 从(0,0)到(4,2)的直线
    line_init(&li, 0, 0, 4, 2);
    line_interpolate(&li);
    line_print(&li);
    return 0;
}

编译与运行

gcc -o line_interp line_interp.c
./line_interp

验证方法

运行程序后观察输出:

  • 总步数应为 dx + dy = 4 + 2 = 6 步;
  • 每一步仅有一个轴产生脉冲(另一个为0),符合逐点比较法单轴进给特性;
  • 最终打印位置必须精确等于终点 (4, 2);
  • 中间轨迹点应逐步逼近理想直线 y = 0.5x,偏差不超过一个脉冲当量。

预期输出(前3行示例):

步号    X脉冲   Y脉冲   当前位置
1       +1      0       (1, 0)
2       +1      0       (2, 0)
3       0       +1       (2, 1)

关键说明

本实现支持任意象限直线(通过 sx/sy 方向控制),但偏差计算统一按第一象限处理。实际工程中,每产生一个脉冲即触发一次步进电机驱动(如通过定时器中断或GPIO翻转),本代码聚焦插补算法本身,脉冲输出接口需根据具体硬件平台接入。数组长度1000足以覆盖常规插补步数,若需更长轨迹可改用动态分配。