前言

今年的电赛(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 coordinatestypedef struct {float x_angle;  // X-axis angle positionfloat 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 calculationfloat 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 sequentiallyPoint 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 trajectoryuint8 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 sequencefor (uint8 i = 0; i < point_count; i++) {// Ensure target angles stay within allowed rangefloat 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 targetfloat move_x = target_x - current_x;float move_y = target_y - current_y;// Update current position to target coordinatescurrent_x = target_x;current_y = target_y;// Send movement command to both axesd36a_set_angle_both(move_x, move_y, MOVE_SPEED);// Pause 300ms after reaching each pointsystem_delay_ms(300);}// Pause 2 seconds after completing the squaresystem_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 coordinatestypedef struct {float x_angle;  // X-axis angle positionfloat 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 circlefor (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 pathcircle_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 pointcircle_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 sequencefor (uint8 i = 0; i <= point_count; i++) {// Ensure target angles stay within allowed rangefloat 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 targetfloat move_x = target_x - current_x;float move_y = target_y - current_y;// Update current position to targetcurrent_x = target_x;current_y = target_y;// Send movement command to both axesd36a_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 circlefloat target_x = 0;float target_y = 0;// Calculate movement from last circle point to originfloat move_x = target_x - current_x;float move_y = target_y - current_y;// Update current position to origincurrent_x = target_x;current_y = target_y;// Send final movement command to return to origind36a_set_angle_both(move_x, move_y, MOVE_SPEED);// Pause for 2 seconds after completing the circlesystem_delay_ms(2000);  
}

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

  1. 弧度计算(将圆周等分为指定数量的点)
    rad=2×π×ipoint_count\text{rad} = 2 \times \pi \times \frac{i}{\text{point\_count}} rad=2×π×point_counti
    其中,iii 为当前点的索引(0 到 point_count-1),point_count\text{point\_count}point_count 为圆周上的总点数,rad\text{rad}rad 为对应角度的弧度值。
  2. X轴坐标计算
    x_angle=r×cos⁡(rad)x\_angle = r \times \cos(\text{rad}) x_angle=r×cos(rad)
    其中,rrr 为圆的半径,cos⁡(rad)\cos(\text{rad})cos(rad) 为弧度对应的余弦值。
  3. Y轴坐标计算
    y_angle=r×sin⁡(rad)y\_angle = r \times \sin(\text{rad}) y_angle=r×sin(rad)
    其中,sin⁡(rad)\sin(\text{rad})sin(rad) 为弧度对应的正弦值。

四、总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91375.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91375.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/91375.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

借助 Wisdom SSH 的 AI 助手构建 Linux 开发环境

借助Wisdom SSH的AI助手构建Linux开发环境 在Linux系统的开发场景中&#xff0c;快速、准确地搭建开发环境至关重要。Wisdom SSH凭借其强大的AI助手&#xff0c;能极大简化这一过程&#xff0c;其官网为ssh.wisdomheart.cn。以下以在Ubuntu 22.04服务器上构建Python开发环境&am…

Python 程序设计讲义(44):组合数据类型——集合类型:创建集合

Python 程序设计讲义&#xff08;44&#xff09;&#xff1a;组合数据类型——集合类型&#xff1a;创建集合 目录Python 程序设计讲义&#xff08;44&#xff09;&#xff1a;组合数据类型——集合类型&#xff1a;创建集合一、集合的特征二、创建集合&#xff1a;使用set()函…

10 - 大语言模型 —Transformer 搭骨架,BERT 装 “双筒镜”|解密双向理解的核心

目录 1、为什么 BERT 能 “懂” 语言&#xff1f;先看它的 “出身” 2、核心逻辑 2.1、“自学阶段”—— 预训练&#xff0c;像婴儿学说话一样积累语感 2.1.1、简述 2.1.2、核心本事&#xff1a;“双向注意力”&#xff0c;像人一样 “聚焦重点” 2.2、“专项复习”—— …

【Spring Boot 快速入门】四、MyBatis

目录MyBatis&#xff08;一&#xff09;入门简介MyBatis 入门LombokMyBatis 基础操作数据准备删除预编译新增更新查询XML 映射文件MyBatis&#xff08;一&#xff09;入门 简介 MyBatis 是一款 优秀的持久层框架&#xff0c;它支持 自定义 SQL、存储过程以及高级映射&#xf…

Spring IOC 基于Cglib实现含构造函数的类实例化策略

作者&#xff1a;小凯 分享、让自己和他人都能有所收获&#xff01; 一、前言 技术成长&#xff0c;是对场景设计细节不断的雕刻&#xff01; 你觉得自己的技术什么时候得到了快速的提高&#xff0c;是CRUD写的多了以后吗&#xff1f;想都不要想&#xff0c;绝对不可能&#xf…

composer 常用命令

### 设置镜像源全局设置composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/当个项目设置composer config repo.packagist composer https://mirrors.aliyun.com/composer/恢复官方源composer config -g --unset repos.packagist### 常用源阿里云…

【python】Python爬虫入门教程:使用requests库

Python爬虫入门教程&#xff1a;使用requests库 爬虫是数据获取的重要手段&#xff0c;下面我将通过一个完整的示例&#xff0c;教你如何使用Python的requests库编写一个简单的爬虫。我们将以爬取豆瓣电影Top250为例。 【python】网络爬虫教程 - 教你用python爬取豆瓣电影 Top…

OpenCV图像缩放:resize

图像缩放是图像处理中的基础操作之一。无论是图像预处理、数据增强还是图像金字塔构建&#xff0c;cv::resize 都是我们最常用的函数之一。但你是否注意到&#xff0c;在 OpenCV 中同时还存在一个名为 cv::Mat::resize 的方法&#xff1f;这两个函数虽然名字类似&#xff0c;但…

汽车、航空航天、适用工业虚拟装配解决方案

一、现状在制造业数字化转型浪潮中&#xff0c;传统装配过程仍面临诸多挑战&#xff1a;物理样机试错成本高、装配周期冗长、工艺优化依赖经验、跨部门协作效率低下……如何打破“试错-返工”的恶性循环&#xff1f;目前总装工艺通过DELMIA、NX、Creo等工程软件进行工艺装配验证…

页面跳转和前端路由的区别

传统方式&#xff1a;通过改变浏览器地址栏的 URL 来实现window.location.href /new-page<a href"/new-page">跳转到新页面</a>会导致整个页面重新加载会触发浏览器向服务器发送新的请求页面状态不会保留&#xff0c;所有资源重新加载可以避免新上线的内…

C/C++核心知识点详解

C/C核心知识点详解 1. 变量的声明与定义&#xff1a;内存分配的本质区别 核心概念 在C/C中&#xff0c;变量的声明和定义是两个完全不同的概念&#xff1a; 声明&#xff08;Declaration&#xff09;&#xff1a;告诉编译器变量的名称和类型&#xff0c;但不分配内存空间定义&a…

物联网发展:从概念到应用的演变历程

物联网的发展历程是一部技术革新与社会需求共同驱动的进化史&#xff0c;其演变可划分为概念萌芽、技术积累、应用拓展和智能融合四个阶段&#xff0c;每个阶段均以关键技术突破或社会需求变革为标志&#xff0c;最终形成万物互联的智能生态。以下是具体演变历程&#xff1a;一…

一个人开发一个App(数据库)

后端要保存数据&#xff0c;我还是选择了关系型数据库Mysql, 因为其它的不熟悉。 flutter端这次我选择的是ObjectBox&#xff0c;以前都是直接用的sqlite3&#xff0c;看对比ObjectBox效率比sqlite3高许多&#xff0c;这次前端为了用户体验&#xff0c;我需要缓存数据&#xff…

天铭科技×蓝卓 | “1+2+N”打造AI驱动的汽车零部件行业智能工厂

7月24日&#xff0c;杭州天铭科技股份有限公司&#xff08;简称 “天铭科技”&#xff09;与蓝卓数字科技有限公司&#xff08;简称 “蓝卓”&#xff09;签订全面战略合作协议。天铭科技董事长张松、副总经理艾鸿冰&#xff0c;蓝卓副董事长谭彰等领导出席签约仪式&#xff0c…

技术复盘报告:Vue表格中多行文本字段数据保存丢失问题

1. 问题背景 在一个基于 Vue 2.0 和 ElementUI 的复杂数据维护页面中&#xff0c;用户报告了一个偶发但严重的问题&#xff1a;在表格中编辑一个多行文本&#xff08;textarea&#xff09;字段时&#xff0c;输入的内容有时会在点击“保存”后丢失。 具体表现&#xff1a; 前端…

#C语言——学习攻略:深挖指针路线(四)--字符指针变量,数组指针变量,二维数组传参的本质,函数指针变量,函数指针数组

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言学习》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"暴力解法是上帝给的&#xff0c;优化解法是魔鬼教的。" 目录 1. 字符指针变量 1.1 使…

SpringBoot收尾+myBatis plus

一、数据传递返回值为:字符串package com.apesource.springboot_web_04.controller;import com.apesource.springboot_web_04.pojo.Emp; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;/*** 返回值为:字符…

基于 Spring Boot 实现动态路由加载:从数据库到前端菜单的完整方案

在后台管理系统中&#xff0c;不同用户角色往往拥有不同的操作权限&#xff0c;对应的菜单展示也需动态调整。动态路由加载正是解决这一问题的核心方案 —— 根据登录用户的权限&#xff0c;从数据库查询其可访问的菜单&#xff0c;封装成前端所需的路由结构并返回。本文将详细…

VitePress学习-自定义主题

VitePress-自定义主题 代码仓库 基础了解 初始化项目的时候选择 custom theme 运行后会发现页面挺丑的。 如果想要用默认主题怎么办呢&#xff0c;修改Layout。 使用默认主题的Layout <script setup lang"ts"> import { useData } from vitepress; impo…

【GEO从入门到精通】生成式引擎与其他 AI 技术的关系

2.1.3 生成式引擎与其他 AI 技术的关系生成式引擎作为人工智能领域的创新力量&#xff0c;与其他 AI 技术紧密相连&#xff0c;相互促进&#xff0c;共同推动 生成式引擎优化&#xff08;GEO&#xff09; 的发展。这些技术使生成式引擎能够为消费者提供更加个性化和精准的内容。…