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

重要参考:

课程链接: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倍频计数实现//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2if(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.mzph.cn/bicheng/8545.shtml

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

相关文章

可视化面板布局适配屏幕-基于 flexible.js + rem 智能大屏适配

可视化面板布局适配屏幕-基于 flexible.js rem 智能大屏适配 VScode 安装cssrem插件引入flexible.js在之后的开发都使用rem为单位,安装cssrem插件就是为了快捷将px转为rem我们的设计稿是1920px,设置最小宽度为1024px,最后,我们可…

县供电公司员工向媒体投稿发文章用亲身经历告诉你并不难

在县供电公司的日子里,我肩负着一项至关重要的使命——信息宣传工作。这不仅仅是一份职责,更是连接公司与外界的桥梁,通过新闻稿件传递我们的声音,展示我们的成果。然而,回忆起刚刚踏入这个领域的时光,那段经历至今让我感慨万千。 初涉投稿,步履维艰 刚接手这项工作时,我的投稿…

又发现一个ai生成音乐的网站-heymusic

网址 https://heymusic.ai/ 尴尬,不挂梯子能登录进来,但是谷歌账号注册不了,刷新了几遍也没注册上。 看了下价格,应该不是免费的,所以也没了试用的兴趣。 我也不想用别的邮箱注册了,所以只能简单的水一…

频谱分析:深入解析与全面介绍

频谱分析 一、引言 频谱分析,作为一种广泛应用于信号处理和波谱分析的方法,其在现代科技领域的重要性不言而喻。从基础的物理现象到复杂的通信系统,频谱分析都扮演着至关重要的角色。本文将对频谱分析进行深入的解析和全面的介绍&#xff0…

VxTerm使用教程:连接SSH服务端设备,什么是SSH

一、什么是SSH&#xff1f; <摘自百度> 安全外壳协议 SSH&#xff0c;即安全外壳协议&#xff08;Secure Shell&#xff09;&#xff0c;是一种网络协议&#xff0c;用于在计算机网络上提供安全的远程登录和命令执行功能。 SSH通过加密通信通道来保护数据传输&#xff0c…

电-热耦合市场联合出清!考虑均衡约束的综合能源系统电-热分配方法程序代码!

前言 随着现代城市面临环境问题&#xff0c;原来燃煤的水和空间供暖设备已逐渐被电锅炉和热泵等电气设备所取代。此外&#xff0c;集中生产热能并通过管网分配热能的区域供暖系统&#xff0c;由于其更高的效率&#xff0c;在冬季漫长寒冷的国家和地区越来越受欢迎。供暖设备的…

超级大转盘!(html+less+js)(结尾附代码)

超级大转盘&#xff01;&#xff08;结尾附代码&#xff09; 网上看到有人用转盘抽奖&#xff0c;怀疑是不是有问题&#xff0c;为什么每次都中不了&#xff0c;能不能整个转盘自己想中啥中啥&#xff0c;查阅了网上写得好的文章&#xff0c;果然实现了只中谢谢参与&#xff0…

JAVA栈相关习题3

1.将递归转化为循环 比如&#xff1a;逆序打印链表 // 递归方式void printList(Node head){if(null ! head){printList(head.next);System.out.print(head.val " ");}} // 循环方式void printList(Node head){if(nullhead){return;}Stack<Node> snew Stack<…

4.5_shell的执行流控制

##1.for语句## &#xff08;1&#xff09;for语句作用 为循环执行动作 &#xff08;2&#xff09;for语句结构 for 定义变量 do 使用变量&#xff0c;执行动作 done 结束标志 &#xff08;3&#xff09;for语句的基本格式 格式1 格式1&#xff1a;#!/b…

OpenHarmony实战开发——引入开源C/C++库之Har包里的NDK

Har 包 HAR&#xff08;Harmony Archive&#xff09;是静态共享包&#xff0c;可以包含代码、C 库、资源和配置文件。通过 HAR 可以实现多个模块或多个工程共享 ArkUI 组件、资源等相关代码。HAR 不同于 HAP&#xff0c;不能独立安装运行在设备上&#xff0c;只能作为应用模块…

ansible 深入介绍之 主机清单与playbook

目录​​​​​​​ 一 inventory 主机清单 1&#xff0c;主机清单 是什么 2&#xff0c;主机清单 定义方式 2.1 自定义主机端口 2.2 定义 范围ip 地址 2.3 定义 拥有相似的主机名 3&#xff0c; inventory 中的变量 3.1 常见 变量 3.2 主机变量 3.3 组变量 3.…

c语言练习5.8

1.分析代码 VS开发环境调试下面的代码&#xff0c;画图解释下面代码的问题 #include <stdio.h> int main() {int i 0;int arr[] {1,2,3,4,5,6,7,8,9,10};for(i0; i<12; i){arr[i] 0;printf("hello bit\n");}return 0; } 分析: 2.喝汽水问题 喝汽水&a…

嘉楠堪智 CanMV K230 进行 Linux、RT-smart 系统开发

本文记录学习、使用 K230 SDK 进行 Linux、RT-smart 系统的开发的一些关键步骤&#xff0c;如何获取系统源代码&#xff0c;如何配置环境&#xff0c;如何使用 Docker 进行编译&#xff0c;获得系统文件。 具体详细的教程&#xff0c;可以学习 CanMV K230 教程。 目录 一、S…

区间合并,CF 1102E Monotonic Renumeration

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1102E - Codeforces 二、解题报告 1、思路分析 我们不难发现对…

.net 6.0 框架集成ef实战,步骤详解

一、代码框架搭建 搭建如下代码架构: 重点含EntityFrameworkCore工程,该工程中包含AppDbContext.cs和数据表实体AggregateObject 1、AppDbContext 代码案例 //AppDbContext 代码案例using Microsoft.EntityFrameworkCore;namespace EntityFrameworkCore {public class Ap…

思通数科大模型在智能数据查询系统中的深度应用:销售数据分析的革新

在企业决策支持系统中&#xff0c;销售数据分析占据着举足轻重的地位。思通数科的大模型技术&#xff0c;结合自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff0c;为智能数据查询系统提供了强大的分析能力。本文将详细描述思通数科大模型在销售数据分析中的应用&am…

2024 GESP6级 编程第一题 游戏

题目描述 你有四个正整数 &#xff0c;并准备用它们玩一个简单的小游戏。 在一轮游戏操作中&#xff0c;你可以选择将 减去 &#xff0c;或是将 减去 。游戏将会进行多轮操作&#xff0c;直到当 时游戏结束。 你想知道游戏结束时有多少种不同的游戏操作序列。两种游戏操作…

科沃斯,「扫地茅」荣光恐难再现

作者 | 辰纹 来源 | 洞见新研社 科沃斯恐怕已经很难再回到被市场誉为“扫地茅”时的荣光了。 不久前&#xff0c;科沃斯发布2023年财报&#xff0c;报告期内营业收入155亿&#xff0c;同比仅增长1.16%&#xff0c;归母净利润6.12亿元&#xff0c;同比下降63.96%&#xff0c;直…

20240508请问GTX2080TI的300和300A核心的差异?

20240508请问GTX2080TI的300和300A核心的差异&#xff1f; 在拼多多/淘宝上&#xff0c;GTX2080TI的300A核心的会比300核心的贵100&#xffe5;左右。 但是怎么区分呢&#xff1f; 300a核心和300请问怎么区分呢&#xff1f;[嘻嘻] devicr ID diviceid 1e07是300a 1e04是300 Gp…

【文章转载】ChatGPT 提示词十级技巧: 从新手到专家

学习了微博网友宝玉xp老师《ChatGPT 提示词十级技巧: 从新手到专家》 个人学习要点&#xff1a; 1、关于提示中避免使用否定句&#xff0c;播主说&#xff1a;“没有人能准确解释为什么&#xff0c;但大语言模型在你告诉它去做某事时&#xff0c;表现似乎比你让它不做某事时更…