Linux-MDK can电机带导轨 C++封装

news2024/11/16 9:38:49

我使用的是MKS的52D can电机带导轨,现在我要根据电机说明书将运动指令封装,有一个限位开关, 闭合时高电平

滑块需要运动在限位开关左侧,所以限位归零的方向为顺时针

根据说明书,我要设置的命令应该是:

cansend can0 001#900100004001D3

将滑块运动到适当位置,执行限位归零命令 :

cansend can0 001#9192

滑块就会回到限位开关的位置了

但是限位归零后,再给电机发送命令它就没有反应了;原因是我设置的归零方向是顺时针,所以电机只能向逆时针方向运动了...这应该是电机问题了,先放一边

我直接用按照脉冲数相对运动封装运动控制

采用C++编写代码

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>

// Function to convert integer to a zero-padded hexadecimal string
std::string intToHex(int value, int width) {
    std::stringstream stream;
    stream << std::setfill('0') << std::setw(width) << std::hex << value;
    return stream.str().substr(0, width); // Ensure the string is of the correct width
}

// Function to calculate checksum
std::string calculateChecksum(const std::string &command) {
    int sum = 1; // Starting with the value of byte 1 (01)
    for (int i = 0; i < command.length(); i += 2) {
        std::string byteString = command.substr(i, 2);
        sum += std::stoi(byteString, nullptr, 16);
    }
    return intToHex(sum % 256, 2);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " <number of rotations>\n";
        return 1;
    }

    const int stepsPerRotation = 16; // Assuming 16 steps per rotation

    // Convert rotations to steps and then to hexadecimal
    int rotations = std::stoi(argv[1]);
    int steps = rotations * stepsPerRotation;
    std::string stepsHex = intToHex(steps, 4); // Convert steps to 4-character hexadecimal

    // Construct the CAN command
    std::string command = "FD014002" + stepsHex + "00"; // Assuming the steps need to be placed in the middle

    // Calculate checksum
    std::string checksum = calculateChecksum(command);

    // Complete CAN command
    std::string canCommand = "cansend can0 001#" + command + checksum;

    // Print and execute the CAN command
    std::cout << "Executing command: " << canCommand << std::endl;
    system(canCommand.c_str());

    return 0;
}

执行为可编译文件

g++ test.cpp -o thefirst

代码分析

//其功能是将一个整数(int)转换成它的十六进制(hex)字符串表示,并确保字符串的宽度(长度)为指定的宽度。
std::string intToHex(int value, int width) {

    //创建一个stringstream对象stream。stringstream是C++中一种方便的流类,用于字符串的格式化            操作
    std::stringstream stream;

    //std::setfill('0')设置填充字符为'0',std::setw(width)设置字段宽度为width,std::hex设置流的格式为十六进制,最后value是要转换的整数值。
    stream << std::setfill('0') << std::setw(width) << std::hex << value;

    //stream.str()将流内容转换为字符串。然后,substr(0, width)函数从这个字符串的开头开始截取长度为width的子字符串。这是为了确保即使生成的字符串长度超过了width,也只返回长度为width的部分。
    return stream.str().substr(0, width);
}
//它的功能是计算输入字符串的校验和,具体实现方法是将字符串中的每两个字符视为一个16进制数,然后求和,最后将和转换为两个字符的16进制数。
std::string calculateChecksum(const std::string &command) {

    int sum = 1;    //在指令中001就是电机的ID,不会变

    for (int i = 0; i < command.length(); i += 2) {
        
        //使用substr方法从command中提取两个字符(从索引i开始)。这两个字符被视为一个16进制的字节,并存储在byteString字符串中。
        std::string byteString = command.substr(i, 2);

        //将byteString从16进制转换为整数(使用std::stoi函数),并加到sum上。std::stoi函数的第三个参数指定了基数,这里是16,表示输入字符串是16进制的。
        sum += std::stoi(byteString, nullptr, 16);
    }
    return intToHex(sum % 256, 2);
}
    
int main(int argc, char *argv[]) {
    
    //检查命令行参数的数量。如果不等于2(argc是参数总数,包括程序名),则输出使用说明并返回1,表示错误。
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " <number of rotations>\n";
        return 1;
    }
    
    //定义细分步数为16
    const int stepsPerRotation  16;
    
    //将命令行中的第二个参数(旋转次数)转换为整数。
    int rotations = std::atoi(argv[1]);

    //计算总步骤数,即旋转次数乘以每次旋转的步骤数。
    int steps = rotations * stepsPerRotation;

    //将步骤数转换为4字符长的16进制数。
    std::string stepsHex = inToHex(steps, 4);
    
    //其中FD014002和00是固定的命令部分,stepsHex是可变的部分,表示步骤数
    std::string command = "FD014002" + stepsHex + "00";

    //计算检验和
    std::string checksum = calculateChecksum(command);

    //组合can命令
    std::string canCommand = "cansend can0 001#" + command + checksum;

    std::cout << "Executing command: " << canCommand << std::endl;

    //使用system函数执行命令。canCommand.c_str()将C++字符串转换为C风格的字符串。
    system(canCommand.c_str());

    return 0;
}

上面的程序只有旋转次数是可变的,现在修改代码使得速度,加速度,位置都是可变的

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>

// Function to convert integer to a zero-padded hexadecimal string
std::string intToHex(int value, int width) {
    std::stringstream stream;
    stream << std::setfill('0') << std::setw(width) << std::hex << value;
    return stream.str();
}

// Function to calculate checksum
std::string calculateChecksum(const std::vector<int> &bytes_values) {
    int sum = 0x01 + 0xFD; // Starting sum with the motor ID (01) and function code (FD)
    for (int value : bytes_values) {
        sum += value;
    }
    return intToHex(sum % 256, 2);
}

int main(int argc, char *argv[]) {
    if (argc != 5) {
        std::cout << "Usage: " << argv[0] << " <direction (0 for CCW, 1 for CW)> <speed (0-3000)> <acceleration (0-255)> <number of rotations>\n";
        return 1;
    }

    int direction = std::stoi(argv[1]);
    int speed = std::stoi(argv[2]);
    int acceleration = std::stoi(argv[3]);
    int rotations = std::stoi(argv[4]);

    // Total pulses calculation modified as per the new requirement
    int totalPulses = rotations * 3200;

    // Constructing the CAN command
    int speedHigh = (speed >> 8) & 0x0F; // Extract high 4 bits of speed
    if (direction == 0) {
        speedHigh |= 0x80; // Set high bit for CCW direction
    }
    int speedLow = speed & 0xFF;  // Low part of the speed
    std::vector<int> bytes_values = {speedHigh, speedLow, acceleration, (totalPulses >> 16) & 0xFF, (totalPulses >> 8) & 0xFF, totalPulses & 0xFF};
    std::string checksum = calculateChecksum(bytes_values);

    // Combine all parts into the final CAN command with motor ID and function code
    std::string canCommand = "cansend can0 001#FD";
    for (size_t i = 0; i < bytes_values.size(); ++i) {
        canCommand += intToHex(bytes_values[i], 2);
    }
    canCommand += checksum;

    // Print and execute the CAN command
    std::cout << "Executing command: " << canCommand << std::endl;
    system(canCommand.c_str());

    return 0;
}

上面的代码可以实现用户输入方向,速度,加速度,和旋转次数

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【复现】【免费】基于多时间尺度滚动优化的多能源微网双层调度模型

目录 主要内容 部分代码 结果一览 1.原文结果 2.程序运行结果 下载链接 主要内容 该模型参考《Collaborative Autonomous Optimization of Interconnected Multi-Energy Systems with Two-Stage Transactive Control Framework》&#xff0c;主要解决的是一个…

蓝桥杯练习题——贡献法(隔板法)

1.孤独的照片 思路 孤独的区间一定有一头孤独的牛&#xff0c;考虑每头牛对区间的贡献是多少 #include<iostream> using namespace std; const int N 5e5 10; int n; string s;int main(){cin>>n>>s;long long res 0;for(int i 0; i < n; i){int l…

Matlab|面向低碳经济运行目标的多微网能量互联优化调度

目录 主要内容 优化流程 部分程序 结果一览 下载链接 主要内容 该程序为多微网协同优化调度模型&#xff0c;系统在保障综合效益的基础上&#xff0c;调度时优先协调微网与微网之间的能量流动&#xff0c;将与大电网的互联交互作为备用&#xff0c;降低微网与大电…

C语言 数组的应用————扫雷

前言 在上一篇博客中我们实现了简单的三子棋小游戏&#xff0c;初步运用了二维数组&#xff0c;今天还是用二维数组来实现另一个小游戏——扫雷的基础版本&#xff0c;写这两个小游戏的目的主要是理解并运用数组&#xff0c;同时巩固前面学习的知识比如循环和函数等等&#xf…

分享一个不错的three.js开源项目

项目将three.js相关内容封装为相应库 很值得学习&#xff0c;可以模仿项目学习three.js vue-vite-three.js threejs-park: 基于vue3&#xff0c;threeJS智慧园区 threejs-park

YOLOv9改进策略:注意力机制 | 用于微小目标检测的上下文增强和特征细化网络ContextAggregation,助力小目标检测,暴力涨点

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;用于微小目标检测的上下文增强和特征细化网络ContextAggregation&#xff0c;助力小目标检测 yolov9-c-ContextAggregation summary: 971 layers, 51002153 parameters, 51002121 gradients, 238.9 GFLOPs 改…

ChatGPT登陆提示:“Please unblock challenges.cloudflare.com to proceed…”

ChatGPT登陆时提示&#xff1a;“Please unblock challenges.cloudflare.com to proceed”&#xff0c; 说明&#xff1a;请解除对challenges.cloudflare.com的屏蔽以继续 原因及解决方法&#xff1a; 1、出现这个问题&#xff0c;一般都是网络和本地环境问题&#xff0c;可以…

使用Nginx配置实现请求的限流操作

概述 限流&#xff08;Rate Limitting&#xff09;是服务降级的一种方式&#xff0c;通过限制系统的输入和输出流量以达到保护系统的目的。 比如我们的网站暴露在公网环境中&#xff0c;除了用户的正常访问&#xff0c;网络爬虫、恶意攻击或者大促等突发流量都可能都会对系统造…

Kotlin进阶之协程从上车到起飞

公众号「稀有猿诉」 原文链接 Kotlin进阶之协程从上车到起飞 通过前面的一篇文章我们理解了协程的基本概念&#xff0c;学会协程的基本使用方法&#xff0c;算是正式入门了&#xff0c;接下来就是要深入的学习技术细节和高级使用方法&#xff0c;以期完全掌握Kotlin协程…

【推荐系统】NCF神经协同过滤

NCF框架 NCF框架是本文要实现的3个模型的主体结构。 首先是输入层&#xff0c;分别包含两个特征向量 v u v_u vu​和 v i v_i vi​&#xff0c;描述了用户u和物品i。输入仅由一个用户向量和一个物品向量构成&#xff0c;它们分别是以one-hot编码的二值化稀疏向量。 接着是Em…

若依 ruoyi-cloud [网关异常处理]请求路径:/system/user/getInfo,异常信息:404

这里遇到的情况是因为nacos中的配置文件与项目启动时的编码不一样&#xff0c;若配置文件中有中文注释&#xff0c;那么用idea启动项目的时候&#xff0c;在参数中加上 -Dfile.encodingutf-8 &#xff0c;保持编码一致&#xff0c;&#xff08;用中文注释的配置文件&#xff0c…

SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程…

备战蓝桥杯Day31 - 真题-管道

题目描述 解题思路 这个问题可以视为一个水波在管道中传播的问题&#xff0c;其中水波以单位速度传播。阀门在 S 时刻打开&#xff0c;水流以单位速度流向管道的右侧&#xff0c;每个传感器位于每段管道的中心。对于位于 Li 的阀门&#xff0c;在 Ti 时刻打开时&#xff0c;水…

Stripe Android 购买集成

图片丢了来这里看&#xff1a;https://juejin.cn/post/7347220605610541091 1. 准备事项 Stripe 账号域名以及配套的网站Stripe 账号付款信息公钥和私钥配置产品以及价格 这些步骤可以看这篇&#xff1a;Stripe Web 购买集成 3. 分析一下流程 客户端集成和 Web 端集成有挺…

使用Python进行数据库连接与操作SQLite和MySQL【第144篇—SQLite和MySQL】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Python进行数据库连接与操作&#xff1a;SQLite和MySQL 在现代应用程序开发中&#xf…

8年测试总结,自动化测试必要注意点+自动化测试框架(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、开始自动化测试…

win修改图标自定义QQ桌面图标

当安装了TIM后&#xff0c;想把图标改成QQ 图标见顶部&#xff0c;或通过网盘下载 提取码&#xff1a;9Ayc 操作步骤&#xff1a; 1.桌面右键图标&#xff0c;点击属性 2.选择快捷方式-更改图标 3.浏览选择下载的ico图标即可

2024最新阿里云幻兽帕鲁搭建服务器_Palworld联机多人游戏

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…

Python装饰器:如何访问和设置私有属性?

大家好&#xff0c;今天我和大家聊一聊如何使用装饰器来访问和设置私有属性。 你有没有遇到过这样的场景&#xff1a;你有一个对象&#xff0c;它的属性是私有的&#xff0c;你想要在不影响原有代码的情况下&#xff0c;对这些私有属性进行操作。这时候&#xff0c;装饰器就派…

【JAVA】Servlet开发

目录 HttpServlet HttpServletRequest HttpServletResponse 错误页面 设置网页自动刷新时间 构造重定向相应 js发起http请求 服务器端对js发起的http请求进行处理 前端获取后端数据&#xff0c;添加到当前页面的末尾&#xff0c;代码示例&#xff1a; 前后端交互&…