第 8 章 电机测速(自学二刷笔记)

news2025/1/17 1:41:15

重要参考:

课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ

讲义链接:Introduction · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

 

8.3.3 电机测速01_理论

测速实现是调速实现的前提,本节主要介绍AB相增量式编码器测速原理。

1.概念

百度百科关于编码器介绍如下:

编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。按照读出方式编码器可以分为接触式和非接触式两种;按照工作原理编码器可分为增量式和绝对式两类。增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。

2.测速原理

关于编码器相关概念简单了解即可,在此需要着重介绍的是 AB相增量式编码器测速原理:
AB相编码器主要构成为A相与B相,每一相每转过单位的角度就发出一个脉冲信号(一圈可以发出N个脉冲信号),A相、B相为相互延迟1/4周期的脉冲输出,根据延迟关系可以区别正反转,而且通过取A相、B相的上升和下降沿可以进行单频或2倍频或4倍频测速。

3.测速举例

假设编码器旋转1圈输出11个脉冲,减速比为 90。伪代码如下:

单频计数:

//设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){
    count++;
}else {
    count--;
}
//....
//速度=单位时间内统计的脉冲的个数 / (11*90) / 单位时间

2倍频计数:

//设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){
    count++;
}else {
    count--;
}
//当A为下降沿时
if(B为低电平){
    count++;
}else {
    count--;
}

//....
//速度=单位时间内统计的脉冲的个数 / (11*2*90) / 单位时间

4倍频计数:

//设置一个计数器
int count = 0;
//当A为上升沿时
if(B为高电平){
    count++;
}else {
    count--;
}
//当A为下降沿时
if(B为低电平){
    count++;
}else {
    count--;
}
//当B为上升沿时
if(A为低电平){
    count++;
} else {
    count--;
}
//当B为下降沿时
if(A为高电平){
    count++;
} else {
    count--;
}
//....
//速度=单位时间内统计的脉冲的个数 / (11*4*90) / 单位时间

8.3.4 电机测速02_实现

需求:统计并输出电机转速。

思路:先统计单位时间内以单频或2倍频或4倍频的方式统计脉冲数,再除以一圈对应的脉冲数,最后再除以时间所得即为电机转速。

核心:计数时,需要在A相或B相的上升沿或下降沿触发时,实现计数,在此需要使用中断引脚与中断函数。

Arduino Mega 2560 的中断引脚:2 (interrupt 0), 3 (interrupt 1),18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), 21 (interrupt 2)

实现流程:

  1. 编写Arduino程序先实现脉冲数统计;
  2. 编写Arduino程序再实现转速计算相关实现;
  3. 上传到Arduino并测试。
1.编码实现脉冲统计

核心知识点:attachInterrupt()函数(请参考 8.2.2 介绍)。

代码:

/*
 * 测速实现:
 *  阶段1:脉冲数统计
 *  阶段2:速度计算
 * 
 * 阶段1:
 *  1.定义所使用的中断引脚,以及计数器(使用 volatile 修饰)
 *  2.setup 中设置波特率,将引脚设置为输入模式
 *  3.使用 attachInterupt() 函数为引脚添加中断出发时机以及中断函数
 *  4.中断函数编写计算算法,并打印
 *    A.单频统计只需要统计单相上升沿或下降沿
 *    B.2倍频统计需要统计单相的上升沿和下降沿
 *    C.4倍频统计需要统计两相的上升沿和下降沿
 *  5.上传并查看结果
 *  
 * 
 */
int motor_A = 21;//中端口是2
int motor_B = 20;//中断口是3
volatile int count = 0;//如果是正转,那么每计数一次自增1,如果是反转,那么每计数一次自减1 


void count_A(){
  //单频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比
  /*if(digitalRead(motor_A) == HIGH){

    if(digitalRead(motor_B) == LOW){//A 高 B 低
      count++;  
    } else {//A 高 B 高
      count--;  
    }


  }*/

  //2倍频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2
  if(digitalRead(motor_A) == HIGH){

    if(digitalRead(motor_B) == HIGH){//A 高 B 高
      count++;  
    } else {//A 高 B 低
      count--;  
    }


  } else {

    if(digitalRead(motor_B) == LOW){//A 低 B 低
      count++;  
    } else {//A 低 B 高
      count--;  
    }  

  }

}

//与A实现类似
//4倍频计数实现
//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 4
void count_B(){
  if(digitalRead(motor_B) == HIGH){

    if(digitalRead(motor_A) == LOW){//B 高 A 低
      count++;
    } else {//B 高 A 高
      count--;
    }


  } else {

    if(digitalRead(motor_A) == HIGH){//B 低 A 高
      count++;
    } else {//B 低 A 低
      count--;
    }

  }

}

void setup() {
  Serial.begin(57600);//设置波特率  
  pinMode(motor_A,INPUT);
  pinMode(motor_B,INPUT);
  attachInterrupt(2,count_A,CHANGE);//当电平发生改变时触发中断函数
  //四倍频统计需要为B相也添加中断
  attachInterrupt(3,count_B,CHANGE);
}


void loop() {
  //测试计数器输出
  delay(2000);
  Serial.println(count);

}
2.转速计算

思路:需要定义一个开始时间(用于记录每个测速周期的开始时刻),还需要定义一个时间区间(比如50毫秒),时时获取当前时刻,当当前时刻 - 上传结束时刻 >= 时间区间时,就获取当前计数并根据测速公式计算时时速度,计算完毕,计数器归零,重置开始时间

核心知识点:当使用中断函数中的变量时,需要先禁止中断noInterrupts(),调用完毕,再重启中断interrupts()(关于noInterrupts与interrupts请参考 8.2.2 介绍)。

代码(核心):

2中代码除了 loop 实现,无需修改。

int reducation = 90;//减速比,根据电机参数设置,比如 15 | 30 | 60
int pulse = 11; //编码器旋转一圈产生的脉冲数该值需要参考商家电机参数
int per_round = pulse * reducation * 4;//车轮旋转一圈产生的脉冲数 
long start_time = millis();//一个计算周期的开始时刻,初始值为 millis();
long interval_time = 50;//一个计算周期 50ms
double current_vel;

//获取当前转速的函数
void get_current_vel(){
  long right_now = millis();  
  long past_time = right_now - start_time;//计算逝去的时间
  if(past_time >= interval_time){//如果逝去时间大于等于一个计算周期
    //1.禁止中断
    noInterrupts();
    //2.计算转速 转速单位可以是秒,也可以是分钟... 自定义即可
    current_vel = (double)count / per_round / past_time * 1000 * 60;
    //3.重置计数器
    count = 0;
    //4.重置开始时间
    start_time = right_now;
    //5.重启中断
    interrupts();

    Serial.println(current_vel);

  }
}

void loop() {

  delay(10);
  get_current_vel();

}
3.测试

将代码上传至Arduino,打开出口监视器,手动旋转电机,可以查看到转速信息。

 

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

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

相关文章

faad2交叉编译——aac解码为pcm,解决faad单通道转双通道问题

FAAD是比较成熟高效的开源AAC解码库,这里用于解码AAC生成PCM数据,用于音频播放。这里因为faad库,会将单通道转化为双通道踩了些坑,所以记录一下。 我使用的是2.11.0版本,貌似往前的版本没有使用CMake,需要c…

如何在电脑中使用微信?pc版微信和手机版有什么区别

微信简介 微信是一个社交和商业强国,自成立以来一直在持续增长。该应用程序在2023年拥有13亿月活跃用户,尽管在某些国家对其使用存在一些阻力。 使用微信网页版可以获得的好处 尽管微信为iOS和Android智能手机提供了出色的应用程序,但仍有时…

面向初学者:什么是图数据库

当数据成为关键生产要素,许多企业开始面临利用海量数据辅助企业复杂决策的现实难题。而在数据爆发式增长,关联复杂度激增的趋势下,图数据库成为企业加工关联数据、挖掘隐藏价值、智能决策升级的关键技术之一,在全球范围内开始被使…

sql优化思路

sql的优化经验 这里解释一下SQL语句的优化的原理 1.指明字段名称,可以尽量使用覆盖索引,避免回表查询,因此可以提高效率 2.字面意思,无需过多赘述。索引就是为了提高查询效率的。 3.图中两条sql直接可以使用union all 或者 uni…

一文盘点 Partisia Blockchain 生态 4 月市场进展

Partisia Blockchain 是一个以高迸发、隐私、高度可互操作性、可拓展为特性的 Layer1 网络。通过将 MPC 技术方案引入到区块链系统中,以零知识证明(ZK)技术和多方计算(MPC)为基础,共同保障在不影响网络完整…

万字长文详解Typora+PicGo+Github/Gitee的配置教程

文章目录 1.前言1.1 Typora简介1.2 引入1.2.1 移动本地图片位置导致图片加载失败问题解决方案反思: 1.2.2 CSDN导入图片转存失败1.2.3 思考 1.3 图床工具1.4 使用原因1.5 总结 2.安装教程2.1 Typora安装教程2.1.1 下载安装包方式1:百度网盘方式2&#xf…

【Python爬虫】使用request和xpath爬取高清美女图片

📝个人主页:哈__ 期待您的关注 目录 🎈 urlib.request 🔥具体的方法 ✈ lxml 🔥xpath的基本语法 1. 基本路径 2. 选择节点 3. 谓语(Predicates) 4. 通配符 5. 选择多个路径 6. 函数 …

鸿蒙内核源码分析(工作模式篇) | CPU的七种工作模式

本篇说清楚CPU的工作模式 工作模式(Working mode) 也叫操作模式(Operating mode)又叫处理器模式(Processor mode),是 CPU 运行的重要参数,决定着处理器的工作方式,比如如何裁决特权级别和报告异…

文献速递:深度学习医学影像心脏疾病检测与诊断--基于深度学习的低剂量SPECT心肌灌注图像去噪:定量评估与临床表现

Title 题目 Deep learning–based denoising of low‑dose SPECT myocardialperfusion images: quantitative assessment and clinical performance 基于深度学习的低剂量SPECT心肌灌注图像去噪:定量评估与临床表现 01 文献速递介绍 单光子发射计算机断层扫描&a…

Options API:选项式 API改成Composition API:组合式 API的留言板

让我欢喜让我忧 改成Composition API:组合式 API的代码&#xff0c; <template><!-- start --><span class"span_checkbox">操作<input type"checkbox" v-model"showInput" value"操作" /></span><…

Learning Continuous Image Representation with Local Implicit Image Function

CVPR2021https://github.com/yinboc/liif 问题引入 图像普遍都是使用像素来表示的&#xff0c;而现实世界是连续的&#xff0c;所以本文借鉴3D中neural implicit representation的思想&#xff0c;以连续的方式表示图像&#xff1b;模型输入坐标值和坐标附近的特征&#xff0…

区块链 | NFT 水印:Review on Watermarking Techniques(二)

&#x1f34d;原文&#xff1a;Review on Watermarking Techniques Aiming Authentication of Digital Image Artistic Works Minted as NFTs into Blockchains 1 半脆弱和可逆水印 鲁棒性好的水印技术通常会产生非常低透明度。正如前面所述&#xff0c;由于透明度在处理数字…

OpenGL 入门(四)—— 贴纸与美颜滤镜

本篇我们来介绍贴纸效果与美颜滤镜的实现。 1、贴纸效果 贴纸实际上是一个图片&#xff0c;用 Bitmap 加载图片后用 OpenGL 渲染到指定的位置上。我们举例添加一个耳朵贴纸&#xff1a; 1.1 获取人脸位置 上一篇我们在讲大眼滤镜时&#xff0c;在 Native 层除了获取到人脸 5…

【数据库表的约束(下)】

文章目录 一、自增长主键二、唯一键约束三、外键约束总结 一、自增长主键 这个约束的功能是&#xff1a; 你不用管我&#xff0c;也不需要插入我这一列的数据&#xff0c;我会保证自己与其他数据不冲突&#xff0c;并且是连续的。 创建一个表&#xff0c;表格内容如下&#x…

Tkinter组件:Checkbutton

Tkinter组件&#xff1a;Checkbutton Checkbutton&#xff08;多选按钮&#xff09;组件用于实现确定是否选择的按钮。Checkbutton 组件可以包含文本或图像&#xff0c;你可以将一个 Python 的函数或方法与之相关联&#xff0c;当按钮被按下时&#xff0c;对应的函数或方法将被…

保护公司机密:避免员工带着数据说拜拜

公司的核心资产之一就是数据。无论是客户信息、研发代码、内部决议、财务报告、商业合同、设计图纸等都是公司的重要资产。如果这些数据在员工离职时被带走&#xff0c;或在员工在职期间不当行为导致数据泄露&#xff0c;将给公司带来重大损失。 然而&#xff0c;保护这些数据…

大模型微调之 在亚马逊AWS上实战LlaMA案例(四)

大模型微调之 在亚马逊AWS上实战LlaMA案例&#xff08;四&#xff09; 在 Amazon SageMaker JumpStart 上微调 Llama 2 以生成文本 Meta 能够使用Amazon SageMaker JumpStart微调 Llama 2 模型。 Llama 2 系列大型语言模型 (LLM) 是预先训练和微调的生成文本模型的集合&#x…

漏洞伴随App无时不在,该怎么办?

漏洞攻击、加密被破坏以及数据泄露是App面临的三大重要安全风险&#xff0c;无论开发者如何防范&#xff0c;攻击者往往会找到新的方法&#xff0c;并依靠最新的工具来破坏App安全性。 统计数据表明&#xff0c;大约82&#xff05;的漏洞是在App程序代码中发现的。如果尽快发现…

百度百科怎么修改词条

百度百科是一个由网民编辑内容的网络百科全书&#xff0c;支持用户添加或修改词条。以下是关于如何修改百度百科词条的详细步骤和注意事项。 1. 登录百度百科账户 首先&#xff0c;你需要登录到百度百科账户。如果你还没有百度账号&#xff0c;你需要先注册一个。注册完成后&a…

【vue+el-upload】当action=“#“,代表不使用默认上传,使用自定义上传,http-request获取文件流

el-upload有多种上传行为&#xff1a; 1、立即上传&#xff1a; 当 action 属性被赋予一个有效的 URL 时&#xff0c;一旦用户选择了文件&#xff0c;el-upload 组件会立即自动将文件上传到指定的服务器地址。 2、不立即上传&#xff08;自定义触发&#xff09;&#xff1a; 如…