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

我使用的是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;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript实现简单的表单验证

关键代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

13|连接数据库:通过链和代理查询鲜花信息

新的数据库查询范式 提出问题&#xff1a;用户用自然语言提出一个问题&#xff0c;例如“去年的总销售额是多少&#xff1f;”。LLM 理解并转译&#xff1a;LLM 首先会解析这个问题&#xff0c;理解其背后的意图和所需的信息。接着&#xff0c;模型会根据解析的内容&#xff0c…

蓝桥杯---代分数

import java.util.Scanner;public class top4 {//全排列分数的那个题目//首先进行n个数的全排列//然后将这n个数字拆分为3个数字&#xff0c;即插入两个板子//然后判断等式是否成立&#xff08;判断条件就是在if里面去进行相关的判断是吗&#xff1f;&#xff1f;&#xff09;s…

一文搞懂机器学习

一、引言 在当今的数字时代&#xff0c;一个概念不断出现在科技前沿的讨论中 —— 机器学习。作为人工智能领域的一个重要分支&#xff0c;机器学习已经从理论研究走向实际应用&#xff0c;深刻地改变着我们的工作和生活方式。 机器学习的核心思想是让机器通过数据学习并做出…

【教学类-44-08】20240319 “(幼儿用)数字练习簿1.0”(A4版)

背景需求&#xff1a; 我一直想把 “&#xff08;幼儿用&#xff09;数字练习簿”的内容复刻出来——这里面的字体始终找不到&#xff0c;是一种已经做成图片的手写数字字体 素材准备&#xff1a; 1、买了一本&#xff08;幼儿用&#xff09;数字练习簿&#xff0c;把每一页扫…

蓝桥杯--基础(哈夫曼)

import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner;public class BASIC28 {//哈夫曼书public static void main(String[] args) {Scanner Scannernew Scanner(System.in);int nScanner.nextInt();List<Integer&…

Visual Studio 2013 - 调试模式下查看监视窗口

Visual Studio 2013 - 调试模式下查看监视窗口 1. 监视窗口References 1. 监视窗口 Ctrl Alt W&#xff0c;1-4&#xff1a;监视窗口 (数字键不能使用小键盘) or 调试 -> 窗口 -> 监视 -> 监视 1-4 调试状态下使用&#xff1a; 在窗口中点击空白行&#xff0c;…

Java项目打包成Docker镜像

将项目打包成Docker镜像 将项目打包成Docker镜像的原因是可以在一台电脑的环境下模拟多台不同性能电脑响应高并发请求时候的表现。这里我们模拟半个CPU、一个CPU还有两个CPU的情况 在pom.xml文件中添加jib插件&#xff08;前提电脑安装了maven和Java 的 JDK才能成功完成编译&…

学习笔记 | 微信小程序项目day04

今日学习内容 热门推荐下转页面 热门推荐下转页面 1、定义类型 import type { PageResult, GoodsItem } from ./global/** 热门推荐 */ export type HotResult {/** id信息 */id: string/** 活动图片 */bannerPicture: string/** 活动标题 */title: string/** 子类选项 */…

STM32—控制蜂鸣器(定时器)

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c tim_irq.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 定时器中断是利用定时器的计数功能&#xff08;向上计数或向下计…

Java 多线程(抢CPU)

哈哈哈 什么是多线程&#xff1a;可以让程序同时做多件事情。 多线程的作用&#xff1a;提高效率。 多线程的应用场景&#xff1a;想让多个事情同时运行。 并发&#xff08;多个指令在单个CPU交替执行&#xff09;和并行&#xff08;多个指令在多个CPU交替执行&#xff09; …

《UE5_C++多人TPS完整教程》学习笔记28 ——《P29 Mixamo 动画(Mixamo Animations)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P29 Mixamo动画&#xff08;Mixamo Animations&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译者…

MySQL数据自动同步到Es

Logstash 测试数据准备 DROP DATABASE IF EXISTS es;CREATE DATABASE es DEFAULT CHARACTER SET utf8;USE es;CREATE TABLE book (id INT NOT NULL,title VARCHAR(20),author VARCHAR(20),price DECIMAL(6,2),PRIMARY KEY(id) );DROP PROCEDURE IF EXISTS batchInsertBook;DELI…

飞桨AI应用@riscv OpenKylin

在riscv编译安装飞桨PaddlePaddle参见&#xff1a; 算能RISC-V通用云编译飞桨paddlepaddleopenKylin留档_在riscv下进行paddlelite源码编译-CSDN博客 安装好飞桨&#xff0c;就可以用飞桨进行推理了。刚开始计划用ONNX推理&#xff0c;但是在算能云没有装上&#xff0c;所以最…

第六篇:视频广告格式上传指南(上) - IAB视频广告标准《数字视频和有线电视广告格式指南》

第六篇&#xff1a; 视频广告格式和上传指南&#xff08;上&#xff09; --- 我为什么要翻译介绍美国人工智能科技公司IAB系列技术标准&#xff08;2&#xff09; 流媒体数字视频的广告格式分为线性和非线性两大类。任何一个广告都可以与显示在视频播放器外部的伴随横幅一起提…

教你读懂cert-manager官网并且使用letsencrypt(一)。

这一篇文章主要讲如果通过cert-manager letsencrypt的方式 自动管理你的证书。 一、怎么装&#xff1f; Installation - cert-manager Documentation 选个符合你环境的&#xff0c;推荐helm来管理你的应用。 二、怎么用&#xff1f; 官网说的&#xff1a; 意思就是你安装了…

Positive Technologies 专家发现的漏洞已在 ABB 控制器中得到修复

&#x1f31f; 我们的同事一如既往地表现出色&#xff1a;应用分析专家 Natalia Tlyapova 和 Denis Goryushev 因发现 Freelance AC 900F 和 AC 700F 控制器中的两个漏洞而受到 ABB 的表彰。 这些设备用于自动化大规模连续循环生产设施和构建企业配送控制系统。利用这些漏洞的…

java算法第28天 | 93.复原IP地址 78.子集 90.子集II

93.复原IP地址 思路&#xff1a; 这里startIndex为插入‘.’的位置&#xff0c;使用回溯法遍历所有插入的位置&#xff0c;直接在原始字符串上操作。要注意的是开闭区间的规定&#xff08;这里我规定的是左闭右闭区间&#xff09;。还要明确什么时候能return。 class Solution…

应用案例多且广 八轴测径仪凭什么备受轧钢客户青睐?

在当今高速发展的工业领域&#xff0c;高效、精准的在线测量设备已经成为了企业提高生产效率和产品质量的重要保障。八轴测径仪&#xff0c;作为一款高精度、高效率的在线测量设备&#xff0c;广泛应用于钢铁、冶金、机械制造等行业。 它采用了先进的光学测量技术和智能算法&am…

前端 - 基础 表单标签 -- 表单元素( input - type属性) 文本框和密码框

表单元素 &#xff1a; 在表单域中可以定义各种表单元素&#xff0c;这些表单元素就是允许用户在表单中输入或选择 的内容控件。 表单元素的外观也各不一样&#xff0c;有小圆圈&#xff0c;有正方形&#xff0c;也有方框&#xff0c;乱七八糟的&#xff0c;各种各样&#xf…