云计算百科
云计算领域专业知识百科平台

MSPM0开发学习笔记:二维云台画图(2025电赛 附源代码及引脚配置)

前言

今年的电赛(2025),很多题都与云台相关,因此为备战电赛,博主这边也是准备了一个由两个42步进电机驱动的云台并提前进行调试,避免赛题出来之后手忙脚乱的,这边的两个42步进电机采用同一个驱动模块进行驱动(D36A),主控肯定采用MSPM0G3507。然后3D打印了一个二维云台的结构并进行组装。本章博客主要是讲这个云台进行绘图的思路以及代码。激光还没有安装上去,目前只是云台的循迹代码


如果无法很好的复现博客里的代码,可以私信作者博取源代码,电赛期间都在线

一、硬件选择

主控:MSPM0G3507 驱动:D36A双路步进电机驱动 电机:42步进电机*2

二、硬件连线

硬件连线部分在上一篇博客里面已经说过了,可以直接去上一篇里面看,这边附上链接 MSPM0开发学习笔记:D36A驱动的42步进电机二维云台(2025电赛 附源代码及引脚配置)

三、软件代码

软件部分采用C语言实现,IDE采用keil,基于逐飞库进行编写 这边先进行一下简单的参数说明,便于理解后面的思路

参数含义以及作用
current_x 目前的X坐标
current_y 目前的Y坐标
target_x 需要移动到的X坐标
target_y 需要移动到的Y坐标
move_x 需要移动的X距离
move_y 需要移动的Y距离
point_count 绘制圆形时候的点数

驱动—电机

代码实现如下:

函数一:限幅函数

#define MAX_ANGLE_X 1000.0f
#define MIN_ANGLE_X 1000.0f
#define MAX_ANGLE_Y 1000.0f
#define MIN_ANGLE_Y 1000.0f

float limit_angle(float angle, float min, float max) {
if (angle < min) return min;
if (angle > max) return max;
return angle;
}

函数二:激光云台绘制正方形

// Function to draw a square trajectory
// Parameters:
// x_len – length of the square's X-axis dimension
// y_len – length of the square's Y-axis dimension
// MOVE_SPEED – speed of movement between points
void draw_square(int x_len, int y_len, int MOVE_SPEED) {

// Structure to store X and Y angle coordinates
typedef struct {
float x_angle; // X-axis angle position
float y_angle; // Y-axis angle position
} Point;

// Invert Y-axis length (likely for coordinate system adjustment)
y_len = y_len * 1;

// Calculate half-lengths for easier coordinate calculation
float x_len_2 = x_len / 2;
float y_len_2 = y_len / 2;

// Define square vertices relative to origin (0,0)
// Coordinates form a square shape when connected sequentially
Point square_points[] = {
{1 * x_len_2, y_len_2}, // Top-left corner
{x_len_2, y_len_2}, // Top-right corner
{x_len_2, 1 * y_len_2}, // Bottom-right corner
{1 * x_len_2, 1 * y_len_2},// Bottom-left corner
{1 * x_len_2, y_len_2}, // Back to top-left to close the square
{0.0f, 0.0f} // Final point: return to origin
};

// Calculate total number of points in the square trajectory
uint8 point_count = sizeof(square_points) / sizeof(Point);

// Initialize current position at origin (0,0)
float current_x = 0;
float current_y = 0;

// Move to each defined point in sequence
for (uint8 i = 0; i < point_count; i++) {
// Ensure target angles stay within allowed range
float target_x = limit_angle(square_points[i].x_angle, MIN_ANGLE_X, MAX_ANGLE_X);
float target_y = limit_angle(square_points[i].y_angle, MIN_ANGLE_Y, MAX_ANGLE_Y);

// Calculate relative movement from current position to target
float move_x = target_x current_x;
float move_y = target_y current_y;

// Update current position to target coordinates
current_x = target_x;
current_y = target_y;

// Send movement command to both axes
d36a_set_angle_both(move_x, move_y, MOVE_SPEED);

// Pause 300ms after reaching each point
system_delay_ms(300);
}

// Pause 2 seconds after completing the square
system_delay_ms(2000);
}

一、函数定义:draw_square函数接收三个参数,分别是正方形的 X 轴长度(x_len)、Y 轴长度(y_len)和移动速度(MOVE_SPEED)。 二、数据结构:定义了Point结构体用于存储坐标点的 X 和 Y 角度值。 三、坐标处理: 1、将 Y 轴长度取负值(为了调整坐标系方向) 2、计算半长(x_len_2, y_len_2),用于确定正方形顶点坐标 3、坐标定义:定义了正方形的 4 个顶点坐标和原点(0,0)坐标以中心点为原点,通过半长计算得出四个顶点位置 4、最后回到一个点 (0,0) 用于回到起点 四、绘制逻辑: 1、遍历所有定义的坐标点 2、对每个目标点进行角度限制(通过limit_angle函数确保在有效范围内) 3、计算当前位置到目标点的移动量 4、调用d36a_set_angle_both函数移动到目标点(同时设置 X 和 Y 方向角度) 5、每个点移动后延迟 300 毫秒,绘制完成后延迟 2000 毫秒

函数三:激光云台绘制圆形

// Function to draw a circle trajectory
// Parameters:
// r – radius of the circle
// MOVE_SPEED – speed of movement between points
// point_count – number of points to use for drawing the circle (more = smoother)
void draw_circle(int r, int MOVE_SPEED, const uint8 point_count) {

// Structure to store X and Y angle coordinates
typedef struct {
float x_angle; // X-axis angle position
float y_angle; // Y-axis angle position
} Point;

// Array to store circle points (extra element to close the loop)
Point circle_points[point_count + 1];

// Calculate coordinates for each point on the circle
for (uint8 i = 0; i < point_count; i++) {
// Convert angle from degrees to radians (full circle = 2π radians)
float rad = 2 * 3.1415926f * i / point_count;

// Calculate X and Y positions using trigonometric functions
// cosine for X-axis, sine for Y-axis to form circular path
circle_points[i].x_angle = r * cosf(rad);
circle_points[i].y_angle = r * sinf(rad);
}
// Close the circle by duplicating the first point as the last point
circle_points[point_count] = circle_points[0];

// Initialize current position at origin (0,0)
float current_x = 0.0f;
float current_y = 0.0f;

// Move to each calculated point in sequence
for (uint8 i = 0; i <= point_count; i++) {
// Ensure target angles stay within allowed range
float target_x = limit_angle(circle_points[i].x_angle, MIN_ANGLE_X, MAX_ANGLE_X);
float target_y = limit_angle(circle_points[i].y_angle, MIN_ANGLE_Y, MAX_ANGLE_Y);

// Calculate relative movement from current position to target
float move_x = target_x current_x;
float move_y = target_y current_y;

// Update current position to target
current_x = target_x;
current_y = target_y;

// Send movement command to both axes
d36a_set_angle_both(move_x, move_y, MOVE_SPEED);

// Optional delay between point movements
// system_delay_ms(10);
}

// Return to origin (0,0) after completing the circle
float target_x = 0;
float target_y = 0;

// Calculate movement from last circle point to origin
float move_x = target_x current_x;
float move_y = target_y current_y;

// Update current position to origin
current_x = target_x;
current_y = target_y;

// Send final movement command to return to origin
d36a_set_angle_both(move_x, move_y, MOVE_SPEED);

// Pause for 2 seconds after completing the circle
system_delay_ms(2000);
}

通过三角函数(X 轴用余弦、Y 轴用正弦)计算圆周上指定数量的点的坐标,这些点基于圆周的等角度增量分布。函数会按顺序在这些点之间移动(带速度控制),同时确保角度在有效范围内;通过回到第一个点来闭合圆形轨迹,最后返回原点,结束时短暂暂停。点的数量越多,绘制的圆越平滑。 以下是函数中涉及的公式:

  • 弧度计算(将圆周等分为指定数量的点)

    rad

    =

    2

    ×

    π

    ×

    i

    point_count

    \\text{rad} = 2 \\times \\pi \\times \\frac{i}{\\text{point\\_count}}

    rad=2×π×point_counti 其中,

    i

    i

    i 为当前点的索引(0 到 point_count-1),

    point_count

    \\text{point\\_count}

    point_count 为圆周上的总点数,

    rad

    \\text{rad}

    rad 为对应角度的弧度值。

  • X轴坐标计算

    x

    _

    a

    n

    g

    l

    e

    =

    r

    ×

    cos

    (

    rad

    )

    x\\_angle = r \\times \\cos(\\text{rad})

    x_angle=r×cos(rad) 其中,

    r

    r

    r 为圆的半径,

    cos

    (

    rad

    )

    \\cos(\\text{rad})

    cos(rad) 为弧度对应的余弦值。

  • Y轴坐标计算

    y

    _

    a

    n

    g

    l

    e

    =

    r

    ×

    sin

    (

    rad

    )

    y\\_angle = r \\times \\sin(\\text{rad})

    y_angle=r×sin(rad) 其中,

    sin

    (

    rad

    )

    \\sin(\\text{rad})

    sin(rad) 为弧度对应的正弦值。

  • 四、总结

    这边给的都是一些简单图形的绘制代码,但是思路都是通用的,复杂图形也可以复用这一套逻辑。大家参考参考就好

    如果无法很好的复现博客里的代码,可以私信作者博取源代码,电赛期间都在线

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » MSPM0开发学习笔记:二维云台画图(2025电赛 附源代码及引脚配置)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!