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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在接下来的时间里,我将记录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做软件正交解码的缺点,计数值也会改变

#
### ESP32 Arduino 函数列表及用法 #### 1. CAN 总线库函数 ESP32-Arduino-CAN 库提供了用于配置和操作CAN总线的功能。这些功能允许设备间通过高效可靠的通信协议交换数据。 - **初始化 CAN 接口** `begin(long canSpeed)` 方法用来启动 CAN 控制器并设置波特率。 ```cpp Can.begin(CAN_500KBPS); ``` - **发送消息** 发送条标准格式的消息到 CAN 网络上可以使用如下代码: ```cpp Can_message msg; msg.id = 0x123; // 设置ID msg.flags.extended = false; // 是否扩展帧 msg.len = 8; // 数据长度 memcpy(msg.data, dataToSend, sizeof(dataToSend)); // 复制要传输的数据 Can.write(msg); // 将消息写入缓冲区准备发送 ``` - **接收消息** 可以利用循环读取接收到的信息直到没有更多可用为止: ```cpp while (Can.available()) { Can.read(msg); Serial.print("Received ID="); Serial.println(msg.id); for(int i=0;i<msg.len;i++){ Serial.printf("%X ", msg.data[i]); } Serial.println(); } ``` 以上内容均基于 ESP32-Arduino-CAN 的官方文档说明[^1]。 #### 2. 霍尔编码器解码相关函数 对于采用霍尔传感器实现位置反馈的应用场景,比如平衡小车项目里提到的电机控制部分,则涉及到如何解析来自编码器的位置变化信号。 - **正交编码处理** 当检测到来自两个通道A/B相位差90度角脉冲序列时,可以通过中断服务例程来更新当前位置计数器变量。 ```cpp volatile long encoderPos = 0; void IRAM_ATTR onEncoder() { static bool lastStateB = digitalRead(ENCODER_PIN_B); bool currentStateB = !lastStateB; if(digitalRead(ENCODER_PIN_A)){ encoderPos += currentStateB ? 1 : -1; }else{ encoderPos -= currentStateB ? 1 : -1; } lastStateB = currentStateB; } attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), onEncoder, CHANGE); ``` 此段代码展示了当 A 或 B 引脚状态改变触发 ISR 来调整全局变量 `encoderPos` 的值,从而跟踪旋转方向与角度的变化情况[^2]。 #### 3. OLED 显示屏驱动 U8g2 库命令集 U8g2 是款支持多种图形 LCD 屏幕类型的 C++ 类库,在这里特别适用于 IIC/SPI 方式的 SSD1306/OLED 设备连接方案下显示文字或简单图像图案。 - **绘制固定文本** 使用 `drawStr()` 函数可以在指定坐标处打印字符串信息至屏幕之上。 ```cpp u8g2.drawStr(xPosition, yPosition, "Hello World!"); ``` 其中 `(xPosition,yPosition)` 定义了起始点相对于左上方边界的偏移量;而 `"Hello World!"` 即为待呈现的具体字符串对象[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值