RT-Thread Hoist_Motor PID
本节介绍的是一个举升电机,顾名思义,通过转轴控制物体升降,为双通道磁性译码器,利用电调进行操控,具体驱动类似于大学期间最大众的SG180°舵机,在一定的频率下,通过调制脉宽进行控制。

设备介绍
-
具体实控
例如在50Hz情况下,即周期为20ms
①驱动信号区间: 区间一(0.5ms-1.5ms )和区间二(1.5ms-2.5ms ) (注意都是开区间且存在死区)
②其中区间一和区间二分别表示不同的方向运动,例区间一表示正方向,则区间二表示反方向。
③旋转速度呈现为“ V ” 字形,即0.5ms和2.5ms分别表示为正反方向的最快速度,1.5ms左右分别表示正反方向的最慢速度。其中小于等于0.5ms时、1.5ms时和大于等于2.5ms时电机都保持停转状态。 -
电调引线
再看电调引线,可注意 分别有7根线,如上图,其中粗线有四根,红黑两根线为电源线,这里接24V,还有两根黄蓝接电机,控制电机不同转向;细线有三根,分别是红黑白,其中红黑为电源线,输出5V,可选择是否需要给MCU供电,黑线接地,白色线为PWM信号输入线,接收MCU发过来的信号进而控制电机转动。 -
电机引线
如上图,电机有6根线,跟大众使用的编码器电机无差别,两根电机引线+两根编码器电源线+AB相 -
PID
由于前几节中已介绍pwm的基本使用,这里就不再介绍,下面我直接介绍我的PID设计
①首先在主函数中对PID进行初始化,即设置目标数、比例积分微分常数、输出限幅、积分限幅。
②在定时器中断中对旋转产生的脉冲进行采样,然后进行PID运算,将输出信号传入电调。
③在P、I、D参数调节中,我习惯先调I,将P和D置0,从小–>大调,观察电机变化,这里我使用的是一个上位机软件VOFA,串口协议,通过上传指定数据,可以很好的观察波形变化,可发现 它呈现出一个缓慢上升的波形,这时可以对I进行放大,加快上升速度,我的调节是:调至I能很好的达到目标点,且在第一次达到目标点时,可以让它超出适量值,再对比左右部分数值,发现这个点的I值达到目标点的速度更快,则这个点就是我要的I值。然后再对P进行调节,也可以选择从小–>大调,P可以很好的反馈出控制器对电机的控制速度,即加大对目标值的反应,具体调节方法同I。最后在对D进行调节(对于一般的控制,PI两个参数足以满足需求,如果最后完美,可再选择D),D表现为误差变化率的变化,可以抑制电机的超调等,对于D,你可以用某物体人为的阻挡电机转动,观察电机变化,例如你提供足够大的阻力,电机肯定会直接拉满,这时观察电机再次回到目标点的时间。
软件设计
- 1. 设备初始化
/************************** Uart ************************************/
void Uart_Init(void)
{char str[] = "hello RT-Thread!\r\n";/* step1:查找串口设备 */serial = rt_device_find(SAMPLE_UART_NAME);/* step2:修改串口配置参数 */config.baud_rate = BAUD_RATE_115200; //修改波特率为 115200config.data_bits = DATA_BITS_8; //数据位 8config.stop_bits = STOP_BITS_1; //停止位 1config.bufsz = 128; //修改缓冲区 buff size 为 128config.parity = PARITY_NONE; //无奇偶校验位/* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);/* step4:打开串口设备。以中断接收及轮询发送模式打开串口设备 */rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
}/************************** Timer ************************************/
void Timer_Init(void)
{rt_hwtimer_mode_t mode; /* 定时器模式 */rt_hwtimerval_t timeout_s; /* 定时器超时值 */rt_uint32_t freq = 1000000; /* 计数频率 */// 使用前必须先手动打开时钟__HAL_RCC_TIM3_CLK_ENABLE();/* 查找定时器设备 */hw_dev = rt_device_find(HWTIMER_DEV_NAME);if (hw_dev == RT_NULL){rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);}/* 以读写方式打开设备 */rt_err_t ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);if (ret != RT_EOK){rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);}/* 设置超时回调函数 */rt_device_set_rx_indicate(hw_dev, Timer3_Out);/* 设置计数频率(若未设置该项,默认为1Mhz 或 支持的最小计数频率) */rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);/* 设置模式为周期性定时器(若未设置,默认是HWTIMER_MODE_ONESHOT)*/mode = HWTIMER_MODE_PERIOD;ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);if (ret != RT_EOK){rt_kprintf("set mode failed! ret is :%d\n", ret);}/* 设置定时器超时值为2s并启动定时器 */timeout_s.sec = 0; /* 秒 */timeout_s.usec = 40000; /* 微秒 */if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s)){rt_kprintf("set timeout value failed\n");}
}/************************** PWM ************************************/
void PWM_Init(void)
{/* 查找设备 */pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);if (pwm_dev == RT_NULL){rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);}/* 使能设备 */rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL1);/* 设置PWM周期和脉冲宽度 */rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL1, period, pulse);
}/************************** Encoder ************************************/
void Encoder_Init(void)
{/* 查找脉冲编码器设备 */pulse_encoder_dev = rt_device_find(PULSE_ENCODER_DEV_NAME);if (pulse_encoder_dev == RT_NULL){rt_kprintf("pulse encoder sample run failed! can't find %s device!\n", PULSE_ENCODER_DEV_NAME);}/* 以只读方式打开设备 */rt_err_t ret = rt_device_open(pulse_encoder_dev, RT_DEVICE_OFLAG_RDONLY);if (ret != RT_EOK){rt_kprintf("open %s device failed!\n", PULSE_ENCODER_DEV_NAME);}
}
- 2. 以下为位置式PID计算,可供参考
PID_VAR_TYPE Position_PID_Cal(PID * s_PID,PID_VAR_TYPE now_point)
{s_PID->LastResult = s_PID->Result; // 简单赋值运算//误差计算s_PID->Error = s_PID->SetPoint - now_point;s_PID->SumError += s_PID->Error; //积分误差累加//积分限幅PID_VAR_TYPE IOutValue = s_PID->SumError * s_PID->Integral;if(IOutValue > s_PID->IntegralMax)IOutValue = s_PID->IntegralMax;else if(IOutValue < s_PID->IntegralMin)IOutValue = s_PID->IntegralMin;//PID计算s_PID->Result = s_PID->Proportion * s_PID->Error // 比例项+ IOutValue // 积分项+ s_PID->Derivative * (s_PID->Error - s_PID->LastError); // 微分项s_PID->PrevError = s_PID->LastError; // 简单赋值运算s_PID->LastError = s_PID->Error; // 简单赋值运算//输出限幅if(s_PID->Result > s_PID->OutMax)s_PID->Result = s_PID->OutMax;else if(s_PID->Result < s_PID->OutMin)s_PID->Result = s_PID->OutMin;return s_PID->Result;
}
- 3. VOFA
正如上面所介绍的一个上位机软件,可观察PID波形变化,协助开发,具体协议如下所示:
void SendDatatoVoFA(rt_uint8_t byte[],float v_real)
{rt_uint8_t t_test=0;//四位发送rt_uint8_t send_date[4]={0};//发送数据Float_to_Byte(v_real,byte); //类型转换for(t_test=0;t_test<4;t_test++){rt_device_write(serial, 0, &byte[t_test], 1);}send_date[0]=0X00;send_date[1]=0X00;send_date[2]=0X80;send_date[3]=0X7f;for(t_test=0;t_test<4;t_test++){rt_device_write(serial, 0, &send_date[t_test], 1);}
}
- 4. 在定时器中断不断进行PID计算,并输出PWM信号
static rt_err_t Timer3_Out(rt_device_t dev, rt_size_t size)
{ rt_device_read(pulse_encoder_dev, 0, &count, 1); /* 读取脉冲编码器计数值 */rt_int32_t out=Position_PID_Cal(&pid1,count);rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL1, period, out);rt_kprintf("%d - %d\n",count,out);SendDatatoVoFA(byte,count); //发送到vofa上位机,查看波形rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_CLEAR_COUNT, RT_NULL);/* 清空脉冲编码器计数值 */return 0;
}
相关文章:
RT-Thread Hoist_Motor PID
本节介绍的是一个举升电机,顾名思义,通过转轴控制物体升降,为双通道磁性译码器,利用电调进行操控,具体驱动类似于大学期间最大众的SG180舵机,在一定的频率下,通过调制脉宽进行控制。 设备介绍…...
css 实现文字流光效果
经过调研发现大多滑块验证码中,有一些文字流光效果,因此在这里简单实现一下。 实现主要利用background 渐变背景以及backgorund-clip:text实现。具体代码如下 css部分 .slide {width: 300px;height: 40px;border: 1px solid #ccc;border-radius: 8px;…...
3D格式转换工具
这里记录下自己之前做3D模型格式转换,包括做CAD模型格式转换辅助的一些开源仓库和工具 (一)转换成gltf工具 gltf作为3D界的jpg标准,如今已经有很多引擎对其进行了支持,这里单独把它列出来 1. obj转glft工具 git仓库…...
seismicunix基础-声波波动方程推导
seismicunix基础-声波波动方程推导 接触波动方程的研究人员都绕不开这个公式,这是在一维状态下波动方程 但是对于这个方程是怎样来的很少有人能说清楚,其中涉及到牛顿第二运动定律,物体的加速度与受到的力有关。 假设一维弦是大量紧密连接的质…...
2024电脑录屏软件排行第一Camtasia喀秋莎
真的要被录屏软件给搞疯了,本来公司说要给新人做个培训视频,想着把视频录屏一下,然后简单的剪辑一下就可以了。可谁知道录屏软件坑这么多,弄来弄去头都秃了,不过在头秃了几天之后,终于让我发现了一个值得“…...
MQTT通信协议使用说明
目录 1 MQTT连接属性1.1 服务器URL(Broker Address)1.2 客户端标识(clientID)1.3 用户名称 & 密码(User Name & Password)1.4 连接超时(Connection Timerout)1.5 心跳间隔 (KeepAlivelnterval)1.6 清除会话(cleanSession) 2 主题&消息2.1 主题2.1.1 订阅主题(SUBSC…...
mysql底层是如何存放数据的
总览 首先总的来说,分为四个层级,行页区段。行就是数据库里的一行数据。 但一次从磁盘读进内存的数据量是一页(页是读写的单位,默认16KB一页),页分很多种类,例如数据页、溢出页、undo日志页。 …...
【代码随想录】刷题笔记Day33
前言 Day33虽说是一个月,但是从第一篇开始实际上已经过了8个月了,得抓紧啊 46. 全排列 - 力扣(LeetCode) 前面组合就强调过差别了,这道题是排序,因此每次要从头到尾扫,结合used数组 class So…...
AD从原理图到PCB超详细教程
AD超详细教程 前言一、建立一个工程模板二、原理图1.设计原理图。2.使用AD自带库和网上开源原理图库3.画原理图库4.编译原理图 三、PCB1.确定元器件尺寸大小2.绘制PCB Library①使用元器件向导绘制元件库②原理图与PCB的映射 3.绘制PCB①更新PCB②调整元件位置③布线④漏线检查…...
2023.11.20使用flask做一个简单图片浏览器
2023.11.20使用flask做一个简单图片浏览器 功能: (1)输入指定路径,打开文件夹 (2)判断文件格式为图片 (3)在前端进行预览 (4)使用bootstrap进行简单美化 ma…...
https和http的区别和优势
大家好,我是咕噜-凯撒,HTTP(超文本传输协议)和HTTPS(安全超文本传输协议)是用于在网络上传输数据的协议,HTTPS相比HTTP在数据传输过程中更加安全可靠,适合对数据安全性要求较高的场景…...
Docker 启动alpine镜像中可执行程序文件遇到 not found
## 1. 问题: docker alpine镜像中遇到 sh: xxx: not found 例如: 在容器内/app/目录下放置了可执行文件abc,启动时提示not found /app/startup.sh: line 5: ./abc : not found ## 2. 原因 由于alpine镜像使用的是musl libc而不是gnu libc&am…...
.net对接阿里云CSB服务
public Response<string> Main(MonthPlanRequest request){string apiName "MonthPlan", postData request.ToJson(); var result ConnectCSB(apiName, postData);return InvokeResult.Fail<string>("访问成功");}/// <summary>///…...
Json数据格式
json比较可读,通过键值对返回。实现通常有两种方式:一种是自己来构造,也就是用一个对象存储数据,在最后输出时将其json字符串化;第二种是使用 RestController 注解实现json数据返回。 第一种 导入依赖坐标: <depe…...
Kafka-Producer
1、生产者 从编程的角度而言,生产者是一个消息的生产者,它负责创建消息并发送到Kafka集群中的一个或多个topic中。 1.1、客户端开发 一个正常的生产逻辑需要具备以下几个步骤: 配置生产者客户端参数及创建相应的生产者实例构建待发送的消…...
Ubuntu20上离线安装samba
如果联网,一条 sudo apt-get install samba就可能解决问题,但是没有网,那么只能一个一个的解决问题: 我以为装了samba-common就可以了,发现smbd.serverice not found,于是开始了漫长的下载依赖包,安装&…...
【开源】基于Vue.js的教学过程管理系统
项目编号: S 054 ,文末获取源码。 \color{red}{项目编号:S054,文末获取源码。} 项目编号:S054,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 教师端2.2 学生端2.3 微信小程序端2…...
【C++】泛型编程 ⑪ ( 类模板的运算符重载 - 函数实现 写在类外部的不同的 .h 头文件和 .cpp 代码中 )
文章目录 一、类模板的运算符重载 - 函数实现 写在类外部的不同的 .h 头文件和 .cpp 代码中1、分离代码 后的 友元函数报错信息 - 错误示例Student.h 头文件内容Student.cpp 代码文件内容Test.cpp 代码文件内容执行报错信息 2、问题分析 二、代码示例 - 函数实现 写在类外部的不…...
动手学深度学习——循环神经网络的简洁实现(代码详解)
文章目录 循环神经网络的简洁实现1. 定义模型2. 训练与预测 循环神经网络的简洁实现 # 使用深度学习框架的高级API提供的函数更有效地实现相同的语言模型 import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, …...
19.删除链表的倒数第 N 个节点
题目来源: leetcode题目,网址:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode) 解题思路: 使用双指针找到倒数第 N1 个节点后删除链表的第 N 个节点即可。注意当 N 为链表长度时,倒数第 N1 …...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
