嵌入式人工智能(32-基于树莓派4B的旋转编码器-EnCoder11)

news2024/9/17 8:56:01

1、旋转编码器

旋转编码器是一种输入设备,通常用于测量和控制旋转运动。它由一个旋转轴和一系列编码器组成。旋转编码器可以根据旋转轴的位置和方向来测量旋转角度,并将其转化为电子信号输出。

旋转编码器通常分为两种类型:绝对值编码器和增量值编码器。

绝对值编码器可以直接输出旋转轴的绝对位置,无需进行位置复位。它通常使用一组二进制编码来表示不同的位置。绝对值编码器具有高精度和高分辨率,适用于需要准确度较高的应用。

增量值编码器则根据旋转轴的运动方向和速度来输出增量值。它通常包含两个输出信号,一个输出脉冲信号用于计数旋转轴的步数,另一个输出方向信号用于指示旋转方向。增量值编码器相对较简单,成本较低,适用于一般的旋转控制应用。

旋转编码器广泛应用于各种领域,如机械加工、机器人控制、汽车导航等。它可以实现精确的角度测量和控制,提高系统的精度和稳定性。

2、EnCode11

EC11旋转编码器广泛用于车载DVD,车载导航,汽车影音上常被人称为车载编码器。编码器主要用于频率调节,高度调节温度调节及音量调节的参数控制。

EC11旋转编码器通常具有两个正交的输出信号(A相和B相),通过检测这两个信号的变化来确定旋转的方向和步长。它还可能具有一个开关信号输出,用于表示按压旋钮的操作。

EC11旋转编码器的工作原理是通过编码盘上的凹槽和接触触点的接触来感知旋转运动。当旋转编码器旋转时,凹槽和接触触点之间的接触状态会不断变化,从而产生相应的输出信号。

总而言之,EC11旋转编码器是一种常见的用于测量和控制旋转运动的输入设备,具有防尘、防水和耐用的设计,适用于各种工业和消费电子应用。

上面2种旋转编码器实际上是一种,就是引脚编号不同,具体对应关系如下。

GND:接地连接。
VCC(+):正电源电压,额定电压5伏。
SW:按钮开关的输出(低电平有效)。当按下旋钮时,电压变低。
DT(输出 B):与CLK输出类似,但滞后于CLK 90°相移。该输出用于确定旋转方向。
CLK(输出A):用于确定旋转量的主要输出脉冲。每次仅通过一个制动装置(咔嗒声)向任一方向转动旋钮时,“CLK”输出就会经历一个先高后低的周期。

3、EC11工作原理

丝印上显示“CLK”、“DT”、“SW”、“+”、“GND”这类是Arduino的编码器,我多说一段话,做个笔记,就是介绍下Arduino,Arduino是一个开源电子平台,它起源于意大利,主要用于简化原型设计和物联网(IoT)项目的创建。Arduino板通常包括微控制器、输入/输出端口以及用于连接各种传感器和设备的插槽。用户可以通过编写简单的基于文本的程序,也就是称为“sketches”的,利用 Ardunio IDE(集成开发环境)来控制硬件。

Arduino的魅力在于其易学性,即使是缺乏专业电路知识的人也能快速上手。它广泛应用于教育、艺术、自动化、家居自动化等领域,支持各种扩展模块,如WiFi、蓝牙等,使得项目具备无线通信功能。通过Arduino,人们可以轻松地将物理世界与数字世界连接起来。

实际上我们树莓派+Python也可以,能比Arduino难不倒哪去,有机会我们也玩玩Arduino的ESP32。言归正传,“CLK”、“DT”:在该模块上显示的丝印名称为这两个,不明白为什么是这个丝印,应该实际对应于编码器常用的“A”、“B”信号吧,这两个信号的发生方式如下:

正旋:如上图当旋钮开始正向旋转时,“A”从低电平变为高电平,“B”保持不变;当旋钮旋转到预定位置时,“A”维持为高电平,“B”然后跟着从低电平跳变到高电平。也就是说,正旋时,“A”总是先与“B”开始电平变化。
反旋:与正旋相反,“B”总是先与“A”开始电平变化。

4、EC11与树莓派连接

VCC:5V

GND:GND

A:GPIO19(BOARD35)

B:GPIO26(BOARD37)

C:GPIO21(BOARD40)

旋转编码器有2个动作,一个是旋转,包括顺时针旋转和逆时针旋转。另一个是按下,车载收音机旋钮也有这个按下的动作,有的是作为退出键,这个按下的输入检测到低电平,可自行定义功能。

但是我这款EC11ABC的C引脚,用万用表测试按下无法产生低电平,令大家失望了,看来这个C引脚硬件内部没有实现按下接地的逻辑,我们用一个按键来模拟即可。

5、实验代码与现象

顺时针旋转编码器,计数值增加,OLED屏上面显示该数值。逆时针旋转编码器,计数值减少。

同时可根据这个计数值改变LED灯的亮暗,注意占空比的范围是(0-100),而编码器的值是(-无穷至+无穷),同学们可以思考下,如何做一个数学函数,将其映射过去。代码有点BUG,我就不改了。

import RPi.GPIO as GPIO
import time
from PIL import Image  
from PIL import ImageDraw
from PIL import ImageFont
import RPi.GPIO as GPIO
import luma.oled as oled  
from luma.core.interface.serial import i2c    
from luma.oled.device import ssd1306  
from luma.core.render import canvas

WIDTH=128
HEIGHT=64 

PWM_LED = 11
RoAPin = 35    # 旋转编码器CLK管脚
RoBPin = 37    # 旋转编码器DT管脚
BtnPin = 13    # 旋转编码器SW管脚
#global globalCounter
globalCounter = 0  # 计数器值

flag = 0                # 是否发生旋转标志位
Last_RoB_Status = 0     # DT 状态
Current_RoB_Status = 0  # CLK 状态

# 初始化工作
def setup():
    GPIO.setmode(GPIO.BOARD)       # 采用实际的物理管脚给GPIO口
    GPIO.setwarnings(False)        # 忽略GPIO操作注意警告
    GPIO.setup(PWM_LED, GPIO.OUT)
    GPIO.setup(RoAPin, GPIO.IN)    # 旋转编码器CLK管脚,设置为输入模式
    GPIO.setup(RoBPin, GPIO.IN)    # 旋转编码器DT管脚,设置为输入模式
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 设置BtnPin管脚为输入模式,上拉至高电平(3.3V)

def load_device():
    # 创建I2C接口对象  
    serial = i2c(port=1, address=0x3C)  # 地址可能因显示屏型号而异,由命令行“sudo i2cdetect -y 1”得到
    # 创建OLED设备对象  
    device = ssd1306(serial, WIDTH, HEIGHT) 
    return device
	
# 旋转编码方向位判断函数
def rotaryDeal():
    global flag                   # 是否发生旋转标志位
    global Last_RoB_Status
    global Current_RoB_Status
    global globalCounter         # 计数器值
    pwm = GPIO.PWM(PWM_LED, 80)
    pwm.start(0)
    if GPIO.input(BtnPin)==GPIO.HIGH:
        Last_RoB_Status = GPIO.input(RoBPin)
        while(not GPIO.input(RoAPin)):       # 判断CLK管脚的电平变化来区分方向
            Current_RoB_Status = GPIO.input(RoBPin)
            flag = 1    # 发生旋转标记
        if flag == 1:   # 标记位为1 发生了旋转
            flag = 0    # 复位标记位
            if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
                globalCounter = globalCounter - 1   # 逆时针方向,负
            if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
                globalCounter = globalCounter + 1   # 顺时针方向,正
            print(globalCounter)
            with canvas(device) as draw:
                draw.rectangle(device.bounding_box, outline=0, fill=0)
                draw.text((0,0), "当前计数值为:",font=font, fill='white')
                draw.text((20,20), str(globalCounter), font=font, fill="white")
            PwmCounter=int(abs(globalCounter)/255*100)
            for i in range(0, PwmCounter, 1):
                # 更改占空比,
                pwm.ChangeDutyCycle(i)
                time.sleep(0.02)               
    else:
        globalCounter = 0
        with canvas(device) as draw:
                draw.rectangle(device.bounding_box, outline=0, fill=0)
                draw.text((0,0), "当前计数值为:",font=font, fill='white')
                draw.text((20,20), str(globalCounter), font=font, fill="white")
        print('计数值已经回零!')


# 中断函数,当SW管脚为0,使能中断
def btnISR():
    global globalCounter
    while True:
        if GPIO.input(BtnPin)==GPIO.LOW:
            time.sleep(0.2)
            if GPIO.input(BtnPin)==GPIO.LOW:
                print('Button pressed.')
                globalCounter = 0 # 给计数器赋
                print(globalCounter)
                break

# 循环函数
def loop():
	global globalCounter  
	tmp = 0	# 当前状态判断
	while True:
		rotaryDeal()      # 旋转编码方向位判断函数
		if tmp != globalCounter: # 判断状态值发生改变
			print ('globalCounter = %d' % globalCounter) # 打印出状态信息
			tmp = globalCounter    #  把当前状态赋值到下一个状态,避免重复打印

# 释放资源
def destroy():
	GPIO.cleanup()             # 释放资源

# 程序入口
if __name__ == '__main__':  
    global device
    device = load_device()  
    font = ImageFont.truetype('STKAITI.TTF',17)
    setup()    # 调用初始化工作
    try:
        loop() # 调用循环函数
    except KeyboardInterrupt:  # 当按下Ctrl+C时,将执行destroy()子程序。
        destroy()

这个代码有点长,后面再介绍传感器的综合实验还是减少点内容,不然代码过于冗长。一般做嵌入式开发,按键LED显示屏这三个是必备的输入输出设备。

旋转编码器

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

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

相关文章

【微服务】Spring Cloud Gateway

文章目录 强烈推荐引言主要功能关键概念示例配置依赖添加常见的几种整合案例1. 与 Spring Cloud Eureka 整合2. 与 Spring Cloud Config 整合3. 与 Spring Cloud Sleuth 和 Zipkin 整合4. 与 Spring Cloud Security 整合5. 与 Resilience4j 整合6. 与 Redis 整合 结论强烈推荐专…

Matlab编程资源库(19)级数与符号方程求解

一、级数符号求和 求无穷级数的和需要 符号表达式求和函数 symsum ,其调用 格式为: symsum(s,v,n,m) 其中 s 表示一个级数的通项,是一个符号表达式。 v 是求和变 量, v 省略时使用系统的默认变量。 n 和 m 是求和的开始项 和…

如何恢复WPS文档中未保存或删除的文件

由于各种原因,您可能会丢失 WPS 文档,例如意外删除、硬盘格式化、病毒攻击等。您是否遇到过丢失未保存的 WPS 文件的情况?您知道如何恢复 WPS 文档中未保存的文件吗? WPS Office 是一款办公套件,可以作为 Microsoft O…

火山引擎VeDI数据技术分享:两个步骤,为Parquet降本提效

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 作者:王恩策、徐庆 火山引擎 LAS 团队 火山引擎数智平台 VeDI 是火山引擎推出的新一代企业数据智能平台,基于字节跳动数据平台多年的“数据…

一个私有化的中文笔记工具个人知识库,极空间Docker部署中文版『Trilium Notes』

一个私有化的中文笔记工具&个人知识库,极空间Docker部署中文版『Trilium Notes』 哈喽小伙伴们好,我是Stark-C~ 最近被很多小伙伴问到NAS上的笔记工具,虽说之前也出过Memos,刚开始用起来还不错,但是用了一段时间…

W1R3S靶机全通详细教程

文章目录 w1r3s主机发现主机扫描 端口扫描tcp端口扫描UDP扫描漏洞扫描 攻击面分析FTP渗透匿名登录 web渗透目录爆破 cuppa cms文件包含漏洞getshell提权 w1r3s 引言 近些日子看红笔大佬的靶机精讲视频时,他的一句话让我感受颇深,很多视频在讲解时&…

《Windows API每日一练》23.1 Windows多媒体

本节我们将讲述单线程到多线程的演进过程,以及进程与线程的区别。 本节必须掌握的知识点: 多媒体硬件 API 概述 第172练:交互输入MCI命令 23.1.1多媒体硬件 多媒体硬件是指用于处理音频、视频和其他多媒体内容的硬件设备。在计算机系统中&…

迈尔沃护眼大路灯怎么样?书客、迈尔沃、霍尼韦尔护眼灯测评PK!

迈尔沃护眼大路灯怎么样?作为一名专业的实测博主,温馨提示大家,虽然护眼落地灯是个好东西,它能够提供柔和舒适的环境光,减少对眼睛的伤害,但是千万别乱买跟风,盲目入手踩雷率80%以上。那么如何辨…

SpringBoot集成 Druid 连接池及监控配置详解

Spring Boot 集成 Druid 连接池及监控配置详解 Spring Boot 是当前 Java 开发中的热门框架,而在数据库连接池的选择上,Druid 因其性能和功能强大也备受青睐。在这篇文章中,我们将深入探讨如何在 Spring Boot 项目中集成 Druid 连接池&#x…

大厂linux面试题攻略二之Linux系统管理

一、Linux系统管理权限优化类 1.简述Linux权限划分原则(经验类) 文件权限: 默认权限: 特殊权限; ACL权限: sudo授权: 文件系统属性权限: 解题思路: 注意权限分离(Linux系统…

入门 PyQt6 看过来(案例)17~ 表格

PyQt6提供了两种用于有规律地呈现更多数据的控件,一种是表格结构的控件(QTableView),另一种是树形结构的控件(QTreeView)。表格控件属于QTableView类,QTableWidget继承于QTableView。 1 QTableView 表格控件 QTableView控件中QStandItemMod…

安胜:促进数据跨境有序流动 赋能企业数字化转型

数字化转型浪潮中,数据出境面临众多机遇与挑战。从业务角度,经济全球化推动外商投资、跨境业务等业务合作,企业数据跨境流动需求强烈,但数据违规现象频发,不仅导致巨大经济损失,还挑战了国家安全。从监管层…

什么是 HTTP/3?HTTP/3 为何席卷全球?HTTP/3 中有什么新内容?为什么需要它?

超文本传输​​协议 ( HTTP ) 是互联网的基石,有助于加载网页、流式传输视频以及为您最喜爱的应用程序获取数据。 去年 ,负责定义互联网技术的组织 互联网工程任务组 ( IETF )对该协议的新版本 HTTP/3 进行了标准化。自那时起,HTTP/3 和相关…

KubeSphere 部署向量数据库 Milvus 实战指南

作者:运维有术星主 Milvus 是一个为通用人工智能(GenAI)应用而构建的开源向量数据库。它以卓越的性能和灵活性,提供了一个强大的平台,用于存储、搜索和管理大规模的向量数据。Milvus 能够执行高速搜索,并以…

纷享销客北方战区游学营举行 五大专项助力伙伴业务“倍速增长”

首届纷享销客北方战区渠道核心伙伴游学营日前在山东济南登场,此次游学营一共设置了五大模块,包括财务专项、组织建设专项、团队成长专项、开源专项、续费及增购专项,旨在帮助纷享销客渠道伙伴夯实高质量增长基础,全方位提升企业经…

上海亚商投顾:沪指震荡收跌 地产、芯片股逆势走强

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 市场昨日探底回升,三大股指小幅下跌,黄白二线分化明显。 商业航天概念继续走强&#…

hive 中编写生成连续月sql

记录一下 sql 编写生成从一个确定的起始月份到当前月份的连续月份序列 SELECT substr(add_months(table1.start_dt,table2.pos),1,4) AS INDICT_YEAR,substr(add_months(table1.start_dt,table2.pos),1,7) AS INDICT_MON FROM (SELECT 2024-01-01 AS start_dt,substr(CURRE…

wpf基础

快速换行的快捷键 vs 工具->选项->文本编辑器->XAML->Formatting(格式化)->spacing(间距)-> 选择第三个 ,将各个属性分行放置。 然后按CtrlKD 如何快速生成下面的代码 鼠标放在Slider_ValueChanged上面然后FnF12 就可以快速生成 wpf中的绑定 在…

Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入|删除段落|删除标签

本教程主要实现【Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入|删除段落|删除标签】。 本文源码:https://gitee.com/songfayuan/go-zero-demo 教程源码分支:master 分支(_examples/word-template/fill-word-template.go&…

ZFIU001 批导会计凭证报错,通过监控点和消息类来定位触发的位置

在创建会计凭证的时候,发送错误,通过打消息类和消息号的条件断点/监控点才解决 文章目录 报错消息号:F5846 创建监控点创建条件断点 报错原因非常注意 报错 消息号:F5846 创建监控点 创建条件断点 报错原因 非常注意