【ESP32 Arduino平衡小车制作】(一)霍尔编码器解码

【ESP32 Arduino平衡小车制作】(四) 直流电机PID控制 一、PID算法1-1 积分分离pid算法1-2 带有死区的pid算法1-3 微分先行pid算法二、程序编写三、硬件设计 一、PID算法 PID 是 结合Proportional(比例)、 Integral(积分)、Differential(微分)三种环节于一体的闭环控制算法,它是目前为止在连续控制系统中计数最为成熟的一种控制算法; PID 控制的实质是对目标值和实际值误差进行比例、积分、微分运算后的结果用来作用在输出上。 连续控制的理想 PID 控制规律 u(t)u(t)u(t) = K p&. 阅读详情
AI摘要

本文详细介绍了使用ESP32 Arduino制作平衡小车时,如何利用编码器进行速度测量。讲解了增量式和绝对式编码器的工作原理,以及M法、T法和M-T法三种常见的测速方法。接着,通过代码展示了ESP32如何处理编码器的正交信号,实现软件正交解码,并提供了计算速度的示例代码。最后,探讨了编码器脉冲数与转速的关系,为小车的速度控制提供理论基础。

在接下来的时间里,我将记录ESP32 Arduino平衡小车制作的全部过程。

一、编码器介绍

1-1增量式编码器

增量式旋转编码器是将设备运动时的位移信息变成连续的脉冲信号,脉冲个数表示位移量的大小。只有当设备运动的时候增量式编码器才会输出信号。编码器一般会把这些信号分为通道A和通道B 两组输出,并且这两组信号间有90° 的相位差。同时采集这两组信号就可以知道设备的运动和方向。

增量式编码器只输出设备的位置变化和运动方向,不会输出设备的绝对位置。

1-2 绝对式编码器

绝对式旋转编码器是将设备运动时的位移信息通过二进制编码的方式变成数字量直接输出。
这种编码器与增量式编码器的区别主要在内部的码盘。

二、常用测速方法

2-1 M 法(高速):

在一个固定的定时时间内(以秒为单位),统计这段时间的编码器脉冲数,计算速度值。

设编码器单圈总脉冲数为C,在时间T0 内,统计到的编码器脉冲数为M0,则转速n 的计算公式为:公式中的编码器单圈总脉冲数C 是常数,所以转速n 跟M0 成正比。

2-2 T 法(低速):

建立一个已知频率的高频脉冲并对其计数,计数时间由捕获到的编码器相邻两个脉冲的间隔时间TE 决定,计数值为M1。

设编码器单圈总脉冲数为C,高频脉冲的频率为F0,则转速n 的计算公式为:公式中的编码器单圈总脉冲数C 和高频脉冲频率F0 是常数,所以转速n 跟M1 成反比

2-3 M-T 法:

既测量编码器脉冲数又测量一定时间内的高频脉冲数。在一个相对固定的时间内,计数编码器脉冲数M0,并计数一个已知频率为F0 的高频脉冲,计数值为M1,计算速度值

设编码器单圈总脉冲数为C,则转速n 的计算公式为:

由于M/T 法公式中的F0 和C 是常数,所以转速n 就只受M0 和M1 的影响。电机高速时,M0增大,M1 减小,相当于M 法,低速时,M1 增大,M0 减小,相当于T 法。

三、ESP32编码器程序

3-1正交信号

编码器返回的数据是一组正交信号,由于Arduino和ESP32都没有正交解码功能,所以要想实现正交解码功能的话就需要用两个io口来同时判断当前是属于状态。
在这里插入图片描述一个脉冲信号周期完成4次跳变。精度提高

1时刻:TI2为低电平,TI1上升沿跳变,计数器向上计数;

2时刻:TI1为高电平,TI2上升沿跳变,计数器仍然向上计数;

3时刻:TI2为高电平,TI1下降沿跳变,计数器仍然向上计数;

4时刻:TI1为低电平,TI2下降沿跳变,计数器仍然向上计数。

3-2 代码编写

首先需要宏定义当前的使用的io口和中断时间。

#define ENCODER_L 	5  //编码器采集引脚 每路2个 共4个
#define DIRECTION_L 18
#define ENCODER_R   4
#define DIRECTION_R 19
#define interrupt_time 20 // 中断时间

配置对应的io口,一个编码器需要两个io口,一个用来检测外部跳边沿中断,另一个来判断方向。

但是这个对于毛刺确实无法识别的,当有毛刺出现的时候也会计做是正常的脉冲,这也就是为什么esp32做软件正交解码的缺点,计数值也会改变

#include <Arduino.h>
#include<Ticker.h>

Ticker timer_read_encoder;  // 中断函数定时器定义

void setup()
{
    Serial.begin(115200);

	pinMode(ENCODER_L, INPUT);       //编码器引脚 输入模式
	pinMode(ENCODER_R, INPUT);       //编码器引脚 输入模式
	pinMode(DIRECTION_L, INPUT);     //编码器引脚 输入模式
	pinMode(DIRECTION_R, INPUT);     //编码器引脚 输入模式
	
	//编码器接口1 开启外部跳边沿中断 
	attachInterrupt(ENCODER_L, READ_ENCODER_L, CHANGE);  //中断函数READ_ENCODER_L
	//编码器接口2 开启外部跳边沿中断 
	attachInterrupt(ENCODER_R, READ_ENCODER_R, CHANGE);  //中断函数READ_ENCODER_R
	
	interrupts();                      //打开外部中断  
    timer_read_encoder.attach_ms(interrupt_time, read);  
}

void loop()
{
	Serial.print("Velocity_L:");Serial.print(Velocity_L);
	Serial.print(" | Velocity_Left:");Serial.println(Velocity_Left);
	Serial.print("Velocity_R:");Serial.print(Velocity_R);
	Serial.print(" | Velocity_Right:");Serial.println(Velocity_Right);
}

下面的部分放到主函数之前就可以,主要是跳变沿中断函数READ_ENCODER_L ()和READ_ENCODER_R()和定时器中断函数READ()。


int32_t Velocity_L, Velocity_R;   //左右轮编码器数据
int16_t Velocity_Left, Velocity_Right;     //左右轮速度


void READ_ENCODER_L(void);
void READ_ENCODER_R(void);
void read(void);


/**************************************************************************
函数功能:外部中断读取编码器数据,具有二倍频功能 注意外部中断是跳变沿触发
入口参数:无
返回  值:无
**************************************************************************/
void READ_ENCODER_L(void) {
  if (digitalRead(ENCODER_L) == LOW) {     //如果是下降沿触发的中断
    if (digitalRead(DIRECTION_L) == LOW)      Velocity_L--;  //根据另外一相电平判定方向
    else      Velocity_L++;
  }
  else {     //如果是上升沿触发的中断
    if (digitalRead(DIRECTION_L) == LOW)      Velocity_L++; //根据另外一相电平判定方向
    else     Velocity_L--; 
  }
}
/**************************************************************************
函数功能:外部中断读取编码器数据,具有二倍频功能 注意外部中断是跳变沿触发
入口参数:无
返回  值:无
**************************************************************************/
void READ_ENCODER_R(void) {
  if (digitalRead(ENCODER_R) == LOW) { //如果是下降沿触发的中断
    if (digitalRead(DIRECTION_R) == LOW)      Velocity_R--;//根据另外一相电平判定方向
    else      Velocity_R++;
  }
  else {   //如果是上升沿触发的中断
    if (digitalRead(DIRECTION_R) == LOW)      Velocity_R++; //根据另外一相电平判定方向
    else     Velocity_R--;
  }
}
void read(void)
{
/**************************************************************************
计算为转速n/s  500线光电编码器数据 定时时间为20MS
 转速 = num/500/20ms
 转速 = num*2/time
**************************************************************************/
    Velocity_Left = Velocity_L*2/interrupt_time;    Velocity_L = 0;  //读取左轮编码器数据,并清零,这就是通过M法测速(单位时间内的脉冲数)得到速度。
    Velocity_Right = Velocity_R*2/interrupt_time;    Velocity_R = 0; //读取右轮编码器数据,并清零
   
}

四、速度计算

首先我们的esp32实际使用的m法测速,即:计算固定时间内的脉冲数。
编码器如果想把速断计算为转速n/s具体步骤如下:

①明确参数:编码器规格:500线(转一圈是500个脉冲), 定时时间为interrupt_time(单位MS)

②固定时间内的圈数M:脉冲数num/500

③转换为秒:固定时间内的圈数/interrupt_time(单位ms)

总的来说公式就是num*2/interrupt_time,

这里我的时间是20ms,所以转速为num/500/20ms=num*40。
在这里插入图片描述

基于arduino控制带编码器直流电机速度 基于arduino控制带编码器直流电机速度 模块:带减速的直流电机(减速比1:120),霍尔编码器(每圈13个信号单相)arduino UNO,TB6612FNG,3.7V电源 编码器连接在直流电机输入端,输出一圈单相有(13*120)个脉冲 #define AIN1 3 #define AIN2 4 #define PWMA 5 #define AA 2 ... 阅读详情

相关推荐

ESP32驱动编码器--SIQ-02FVS3 (Vscode + IDF)

提示:本博客作为学习笔记,有错误的地方希望指正 文章目录一、编码器简介二、硬件设计三、实现代码四、显示结果 一、编码器简介   编码器一般分为霍尔式的和光栅式的编码器,我这里使用的式SIQ-02FVS3这种迷你编码器,和EC11的驱动方法差不多,但是这种编码器体积比较小,但是价格比价贵。下面是编码器的实物图。SIQ-02FVS3还带有按压按键,实现多功能。   那么我们该怎样去使用这个编码器呢,从给出的数据手册上面我们看到一个波形,我们就是通过这个波形去判断编码器是否转动以及编码器转动的方向,可以从图中可

believe666的博客 1万+

Arduino ESP32 旋转编码器

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

COYOO 1万+

Arduino UNO与霍尔编码器实现电机转速测量:从原理到实践

在嵌入式开发和机器人控制领域,实时、精确的速度反馈是构建闭环控制系统的基石。其核心原理通常涉及传感器对物理量(如旋转)的感知与转换,通过测量单位时间内的脉冲信号数量来计算转速。霍尔编码器作为一种基于霍尔效应的磁敏传感器,因其非接触、寿命长、抗干扰能力强的特点,成为电机测速的常用技术方案。该技术方案在低成本微控制器平台上具有极高的工程实践价值,能够为智能小车、机械臂、自动化设备等应用场景提供可靠的速度数据。本文聚焦于如何利用Arduino UNO的**中断处理**机制,高效捕获霍尔编码器的**正交编码信号**

weixin_33824363的博客 381

【ESP32 Arduino平衡小车制作】(三) 直流电机pwm控制

基于ESP32的直流电机PWM控制 直流电机驱动器 驱动器使用 H桥电路进行驱动,核心电路 H 桥加上一些必要的外围电路,共同组成直流有刷电机的驱动器。H 桥本身可作为集成电路使用,也可由分立元件构成。 集成电路形式的 H 桥一般用于中小功率需求的应用,或者是对电路面积有要求的场合。 分立元件形式的 H 桥通常用于大功率或者超大功率需求的应用,主要由 MOSFET 或 IGBT 晶体管组成。 这里我使用的是TB6612这款直流驱动芯片 可利用IN1和IN2这两个输入信号,选择正转,反转,短路制动器、和停机等

weixin_45829708的博客 1万+

旋转编码器:如何在 Arduino 上使用 Keys KY-040 编码器

旋转编码器是一种输入设备,您可以在任一方向连续旋转。当您转动设备时,它会生成数字脉冲,以使用两个相控输出信号显示旋转方向。这两个输出还指示单个位置运动,因此您可以在控制面板中使用它们来增加或减少参数。 注意:由于开关弹跳,旋转编码器会产生极其嘈杂的输出振荡,本页上的信息为您提供了 两种消除这种噪声的技术。第一种是简单的过滤方法,第二种方法使用表解码从低质量设备中获得非常好的输出。 下面用于演示的编码器类型也称为增量旋转编码器,因为它产生指示单步变化的脉冲。其他类型生成绝对输出,即为编码器的特定位置生成相

armcsdn的博客 9718

AS5600编码器的使用

AS5600为绝对编码器,即根据安装的磁铁角度不同,初始位置的读数不同,读出来的数是当前初始位置在0~360°的一个值。 流程图: 初始化: 校准标定磁块【checkMagnetPresence()函数,通过返回值确定磁块位置是否准确距离】→读取初始角度值【ReadRawAngle()读取当前的绝对位置角度值信息】→ 进入循环(每次循环都是有耗时,故转速不能超过某特定的值): 读取更新当前的角度值【ReadRawAngle()函数】→计算转过的角度数值【correctAngle()函数,可以计算角度值】→计

qq_40969179的博客 1万+

低成本具身智能小车实战:树莓派与ESP32搭建目标追踪系统

具身智能的核心在于让机器人通过感知、决策与控制形成完整闭环,而这一过程并不依赖昂贵硬件。在机器人开发中,树莓派与ESP32的组合为低成本平台提供了可行方案:前者承担视觉处理与决策计算,后者负责实时电机控制,二者通过串口协同,构成了典型的上下位机架构。理解这一架构,需要从ROS 2的分布式通信模型入手,掌握话题、服务与QoS机制,再结合PID控制器实现稳定的目标追踪。本文面向机器人竞赛、ROS 2学习者和DIY开发者,展示如何基于传统视觉与有限状态机,在数百元预算内搭建一套可复现的感知-决策-控制链路,并给出

weixin_33827590的博客 322

编码电机的使用方法(ESP32--Arduino)

编码器主要分为光电编码器和磁编码器(霍尔编码器)。

2302_81176524的博客 4437

聊天机器人为何仍需STM32:从大模型到电机控制的实战拆解

在嵌入式系统与人工智能融合的浪潮下,不少开发者误以为接上大模型API就能造出机器人。然而,能对话的“大脑”与能行动的“身体”是两套截然不同的技术体系。机器人运动控制依赖毫秒级响应的实时系统,这正是STM32这类微控制器的核心优势。它通过定时器、PWM、编码器接口和中断机制,承担起底盘驱动、舵机控制、避障急停等“小脑”职责,与大模型在云端或上位机完成的任务形成明确分工。本文以语音交互机械臂小车为例,从系统架构、数据流、关键参数计算到PID闭环调试,完整呈现STM32在机器人项目中的工程价值,为嵌入式开发和机器

weixin_34072458的博客 281

旋转编码器如何工作并与Arduino接口

顺时针旋转旋钮时,首先连接A引脚,然后连接B引脚。换句话说,它寻找电压变化,从高到低或从低到高,这是在您旋转旋钮时发生的。当然,您可以使用Arduino 5V输出,但请记住,伺服器可能会在Arduino使用的5V线上感应电噪声,这可能不是您想要的。但是,在您需要知道位置变化而不是确切位置的情况下,旋转编码器是最好的。为此,我们只需读取编码器模块上的DT引脚,并将其与CLK引脚的当前状态进行比较。首先,我们包括内置的Arduino Servo库,并创建一个表示我们的伺服电机的伺服对象。

sxstj的博客 820

ESP32学习笔记15-脉冲计数器 (PCNT)正交编码器-脉冲计数

PCNT 用于统计输入信号的上升沿和/或下降沿的数量。ESP32 集成了多个脉冲计数单元,每个单元都是包含多个通道的独立计数器。通道可独立配置为统计上升沿或下降沿的递增计数器或递减计数器PCNT 通道可检测边沿信号及电平信号能设置为递增计数,递减计数,或停止计数电平信号就是所谓的控制信号,可用来控制边沿信号的计数模式通过设置电平信号与边沿信号的检测模式,PCNT 单元可用作正交解码器每个 PCNT 单元还包含一个滤波器,用于滤除线路毛刺控制引脚=1,技术方向++

Car12 3264

ARDUINO编码器反馈电机初步代码

由于ARDUINO R3的定时器资源比较紧缺,考虑到模块化移植,尽可能减少了对定时器资源的占用 使用的是定次数计时间的方法,该方法在低速下会出现较大误差,可以适当调小指定次数值,考虑到直流电机转速不会太慢(低速很多时候会停转),固此种方法大多是情况下非常实际用,且转速越高误差越低,如果追求低速定时测量可以直接使用定时器定时间进行方波计数,此外本代码目前仅写出了测量速度而没有考虑电机AB相可以测量方向,若要添加AB相可以将代码IO接口加一个,并且测量上升沿的先后顺序得出转向,相关代码后续小比赛结束后会放出。

m0_73989054的博客 1252

ESP32 PULSE CNT脉冲计数器使用(简单DEMO)

ESP32 PULSE CNT脉冲计数器使用,他的功能很简单就是实现脉冲个数的计数。

编码器相关知识及ESP32-Arduino程序

编码器主要分为光电编码器和磁编码器(霍尔编码器)。 一、主要原理: 对于编码器来讲,其本质在于测量距离,或者说路程。通过计算转一圈的脉冲个数,从而实现测速。 1.光电编码器:是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器,光电编码器是由光源、光码盘和光敏元件组成。光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,光栅盘与电动机同速旋转,经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号,通过计算每秒光电编

ksjz123的博客 1万+

linux应用程序段错误调试

一、堆、栈 在分析段错误之前,先了解一下什么是堆?什么是栈? 堆:一般由开发者分配释放,如果没有释放,程序结束时,在有的OS中可能会被自动释放,分配方式类似于链表。堆的操作方式为,队列优先,先进先出的原则。 栈:由操作系统自动分配,存放函数的参数值,局部变量。栈的操作方式为,先进后出的原则。 堆栈中定义了一些操作。 两个最重要的是PUSH和POP。  PUSH:操作在堆栈的顶部加入一个元素...

农村种地人 1111

Cesium+Three.js融合实战:从零构建GIS与BIM一体化大场景

本文详细介绍了Cesium与Three.js融合技术在GIS与BIM一体化大场景中的应用实践。通过坐标系转换、双引擎协同渲染等核心技术,实现宏观地理信息与微观建筑细节的完美结合,为智慧城市、数字孪生等项目提供高效解决方案。文章包含环境配置、性能优化等实战经验,助力开发者快速掌握三维可视化开发技巧。

weixin_42563415的博客 262

Arduino学习笔记(14)-- Arduino使用增量编码器测速

原理参考:https://www.arduino.cn/thread-42559-1-1.html https://blog.youkuaiyun.com/qq_42795251/article/details/90057308 摘要: 利用Arduino、增量式光电编码器测量速度、方向、位移。 材料: Arduino mega 2560 分辨率256ABZ相增量式编码器 pc 编码器...

Techblog of HaoWANG 1万+

鱼眼双目测距实战:从OpenCV标定到SGBM匹配的完整流程解析

本文详细解析了鱼眼双目测距的完整流程,从OpenCV标定到SGBM匹配,涵盖标定、校正、匹配和测距四个关键阶段。通过实战经验分享,帮助开发者解决鱼眼镜头强畸变带来的测距挑战,提升测距精度至5%以内。特别适合机器人导航、自动驾驶和VR领域的开发者参考。

weixin_27298377的博客 124

arduino——编码器示例

KY-040旋转编码器模块 操作 旋转编码器提供两种交互方式: 每次用户旋转旋钮时,都会在 DT 和 CLK 引脚上产生低电平信号: 顺时针旋转会先使CLK引脚变为低电平,然后DT引脚也变为低电平。 逆时针旋转会使 DT 引脚首先变为低电平,然后 CLK 引脚变为低电平。 示例 代码 #define ENCODER_CLK 2 #define ENCODER_DT 3 void setup() { Serial.begin(115200); pinMode(ENCODER_CLK, I

m0_46152804的博客 3618

Qt 侧边菜单栏+堆叠窗口stackedWidget

效果如下:环境:Qt 6.6.2 MSVC2019 64bit。

weixin_41033231的博客 1568

2023-07-04 Fast-Lio论文中公式(6)与BCH公式中近似雅可比公式的一致性推导

将(1)式代入(6)式,就有。

wmorries的博客 478

编码器的原理以及在arduino中的使用

如果是光编码器,码盘上会有黑白的线,白色能透光,黑色不能透光。一旦经过白色的线,就会产生一个脉冲。A,B的脉冲顺序,代表了旋转的方向。

逐日者 2054

Unity之如何实现TTS文本转语音(真人发音)

微软Azure TTS 文本转语音 服务 将文本转换为逼真的语音的语音服务功能 支持个各国语言,各种中文各种方言,支持不同音色男音女音 支持离线和在线版本

TxNet 5480

基本定时器(TIM6/TIM7)

基本定时器最简单,就干一件事:到点了触发中断。定时器本质就是计数器,每个时钟脉冲加1,数到ARR就溢出、产生中断、清0重来。三个核心寄存器:PSC(预分频器):对输入时钟分频CNT(计数器):从0往上数ARR(自动重装载值):数到这个值就溢出,CNT清0,产生更新中断公式:  定时周期 = (PSC+1) × (ARR+1) / 定时器时钟  更新事件频率 = 定时器时钟 / ((PSC+1) × (ARR+1)) 例:TIM6时钟84MHz,要定时0.5秒(2

2401_89890233的博客 233

PSINS工具箱学习(四)捷联惯导更新算法

原始 Markdown文档、Visio流程图、XMind思维导图见:https://github.com/LiZhengXiao99/Navigation-Learning。

实践出真理,接毕设/课设项目开发指导 607

ResNet改进(7):添加 SK注意力机制

实现 SK 注意力机制。

2401_82355416的博客 732
上一篇: 【机器人学】-位姿描述和旋转变换(2)
下一篇: 【STM32G431RBT6】蓝桥杯嵌入式 ADC采样DMA传输配置
Mount.W
博客等级 码龄7年 477粉丝 35原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值