FPGA实现电机霍尔编码器模块

news2024/9/29 21:28:16

一. 简介

想要知道直流电机的转速,就需要用到编码器,常用的编码器有霍尔和光电两种,但是光电编码器比较贵(性能好于霍尔),所以平常的时候使用最多的是霍尔编码器了。

霍尔编码器一般有AB两相信号输出,默认的时候为低电平,当电机转动的时候,AB两相会输出具有一定相位差的脉冲,根据相位差可以确定电机旋转的方向,另外根据单位时间内,脉冲的数量可以确定电机的转速(线数X(编码器参数):电机旋转一圈产生的脉冲数,减速电机有一个减速比Y(Y越大,扭矩越大,负载转速越小),也就是说负载(一般为轮胎)旋转一圈所产生的脉冲数为: X * Y)。AB输出的脉冲波形如下

请添加图片描述

编码器的使用方法如上,非常简单,下面就用FPGA来写一个编码器模块吧!

二. 编码器模块架构

首先,需要明确一下,编码器模块需要实现那些功能,经过简单的思考,可以确定要实现的功能如下,其中加速度不是必须的。
请添加图片描述

功能确定了之后,就可以简单设计一下框图如下,根据框图可以很清晰来编写各个模块了。

请添加图片描述

三.定时器模块

定时器模块的功能非常简单。就是每隔一段时间产生一个触发信号,用来清除脉冲计数 和 计算一次速度与加速度。我这里是设置的5ms触发一次,具体多少时间触发一次合适,可以根据实际的测试效果而定。

四. 编码器脉冲检测模块

该模块的主要功能是用来检测AB两相的脉冲并且判断脉冲的方向。一共有两种方法来检测:

  1. 单边沿检测 : 检测AB某一相的A沿,然后判断另外一相的电平。例如检测A相的上升沿为有效脉冲,然后判断B相的电平为电机旋转方向。该方法非常简单,但是抗干扰能力并没有那么强,容易误判。
  2. 四边沿检测 : 依次检测每一个边沿,如果四个边沿均满足要求,则该脉冲为有效脉冲,否则为无效脉冲。该方法抗干扰能力比较强,但逻辑上稍微有点点复杂相较于第一种方法来说。

两种方法的实现,对于FPGA来说,不是什么难事,第一种就不提了;第二种方法的话,一个状态机就可以了,在对应的状态里面检测一相的边沿信号和另外一相的电平,两相都满足的话,就跳到下一个状态,四个状态均满足的话,则输出一个有效电平,否则的话,均回到初始状态。本次使用的是一段式状态机,代码片段如下(两个状态)。

always@(posedge sys_clk_i or negedge sys_rst_n_i) begin
    if( sys_rst_n_i == 1'b0 ) begin
        step <= 6'b00_0000;
        encoder_AB_detect_dir_reg <= 1'b0;
    end
    else begin
        case (step)
        6'b00_0000: begin                 //处理第一个边沿
            if( (encoder_A_posedge  | encoder_B_posedge) && encoder_AB_detect_en_i == 1'b1)  
                step <= 6'b00_0001;
            else
                step <= step;
        end
        6'b00_0001: begin  //处理第二个边沿
            if( encoder_A_posedge == 1'b1)
                if( encoder_B_d0 == 1'b1) begin
                    step <= 6'b00_0100;
                    encoder_AB_detect_dir_reg <= 1'b0; //在第二个边沿的时候,确定旋转方向
                end
                else
                    step <= 6'b00_0000;
            else if( encoder_B_posedge == 1'b1)
                if( encoder_A_d0 == 1'b1) begin
                    step <= 6'b00_0010;
                    encoder_AB_detect_dir_reg <= 1'b1; //在第二个边沿的时候,确定旋转方向
                end
                else
                    step <= 6'b00_0000;
            else if( encoder_A_negedge | encoder_B_negedge)   //检测到下降沿 表示错误 
                step <= 6'b00_0000;
            else  
                step <= step;  //需进行超时处理
        end

然后模块的信号如下,

module encoder_AB_detect(
    input              sys_clk_i                ,
    input              sys_rst_n_i              ,
    
    input              encoder_AB_detect_en_i   ,       //编码器检测使能
    output             encoder_AB_detect_valid_o,       //编码器检测有效输出
    output             encoder_AB_detect_dir_o  ,       //编码器检测方向输出
    //硬件编码器输入
    input              motor_encoder_A_i        ,      //编码器A相输入
    input              motor_encoder_B_i               //编码器B相输入
);

五. 脉冲计数模块

计算脉冲数,由于电机在朝一个方向转动的时候,可能会由于不确定因数的影响,产生另外一个方向的脉冲,所以在计算的时候需要对其进行处理。

分别计数两个方向的脉冲数,以脉冲数多的方向为当前方向,多的脉冲数 减去 少的脉冲数 为当前方向的脉冲数。

assign encoder_Phase_count_dir_o = ( encoder_Phase_Cnt_dir0 > encoder_Phase_Cnt_dir1 ) ? 1'b0 : 1'b1;
assign encoder_Phase_count_o     = ( encoder_Phase_Cnt_dir0 > encoder_Phase_Cnt_dir1 ) ? (encoder_Phase_Cnt_dir0 - encoder_Phase_Cnt_dir1): 
                                                                                         (encoder_Phase_Cnt_dir1 - encoder_Phase_Cnt_dir0);

//编码器脉冲计数
always@(posedge sys_clk_i or negedge sys_rst_n_i) begin
    if( sys_rst_n_i == 1'b0) begin
        encoder_Phase_Cnt_dir0 <= 16'd0;
        encoder_Phase_Cnt_dir1 <= 16'd0;
    end
    else if( encoder_Phase_count_clear_i == 1'b1 ) begin  //定时器输入,重新开始计数
        encoder_Phase_Cnt_dir0 <= 16'd0;
        encoder_Phase_Cnt_dir1 <= 16'd0;
    end
    else if( encoder_AB_detect_valid_i == 1'b1 )  //对两个方向的脉冲分别计数
        if( encoder_AB_detect_dir_i == 1'b0 ) begin
            encoder_Phase_Cnt_dir0 <= encoder_Phase_Cnt_dir0 + 1'b1;
            encoder_Phase_Cnt_dir1 <= encoder_Phase_Cnt_dir1;
        end
        else begin
            encoder_Phase_Cnt_dir0 <= encoder_Phase_Cnt_dir0;
            encoder_Phase_Cnt_dir1 <= encoder_Phase_Cnt_dir1 + 1'b1;   
        end
    else begin
        encoder_Phase_Cnt_dir0 <= encoder_Phase_Cnt_dir0;
        encoder_Phase_Cnt_dir1 <= encoder_Phase_Cnt_dir1;
    end
end

六. 速度与加速度检测模块

当定时器信号输入时,根据脉冲计数模块输入的脉冲数来计算。速度的单位为 圈数/分钟,而检测周期为5ms,所以RPM = 圈数 *( 1分钟 / 5ms ),然后这里使用的编码器为500线,电机的减速比为20,所以一圈对应的编码器脉冲数为500 * 20 = 10000 ,所以最终RPM = ( 脉冲数 / 10000) * ( 1分钟 / 5ms) = 1.2 * 脉冲数。 为了便于计算将RMP扩大10倍, 即 RPM = 12 * 脉冲数 = ( 8 + 4) * 脉冲数。将脉冲数左移3位 加速 脉冲数左移2位 即可。

加速度就更加简单了,只需要将当前速度 减去 上一时刻的速度 即可,加速度有方向,还需要判断一下加速度方向。

assign encoder_speed = ( encoder_Phase_count_i << 3 ) + ( encoder_Phase_count_i << 2 );
always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        encoder_speed_d0 <= 16'd0;
        encoder_speed_o  <= 16'd0;
        encoder_acc_o    <= 16'd0;
        encoder_acc_dir_o<= 1'b0;
    end
    else if( cal_en_i == 1'b1 ) begin
        encoder_speed_d0 <= encoder_speed_o;
        encoder_speed_o  <= encoder_speed;
        encoder_acc_o    <= (encoder_speed > encoder_speed_d0) ? encoder_speed - encoder_speed_d0 : encoder_speed_d0 - encoder_speed;
        encoder_acc_dir_o<= (encoder_speed > encoder_speed_d0) ? 1'b1 : 1'b0;
    end
    else begin
        encoder_speed_d0 <= encoder_speed_d0;
        encoder_speed_o  <= encoder_speed_o;
        encoder_acc_o    <= encoder_acc_o;
        encoder_acc_dir_o<= encoder_acc_dir_o;
    end
end

七. 角度检测模块

当需要旋转对应角度的时候,就需要对其旋转角度进行检测。旋转一圈,对应的脉冲数为10000,所以每个脉冲数对应的角度为0.036°,为了便于计算,这里将角度扩大10倍,每个脉冲数对应的角度就变成了0.36°,每5个脉冲数对应的角度就变成了1.8°,这样以5个脉冲数为一个脉冲单位,所以每一个脉冲单位角度就变化了1°,先不管0.8°,而0.8 * 5 = 4°,所以每5个脉冲单位角度就变化了4°,这样就非常方便计算了,当是会有一定的误差,最大误差角度约为: 3.2° + 1° = 4.2°,即实际误差角度为0.42°,还是可以接受的。

always@(posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        encoder_num_angle_o <= 20'd0;
    else if( encoder_accumulate_clr_i == 1'b1)
        encoder_num_angle_o <= 20'd0;
    else if( encoder_accumulate_en_i == 1'b1 && encoder_AB_detect_valid_i == 1'b1 )
        if( encoder_AB_Angle_Cnt1 == 'd4 )
            encoder_num_angle_o <= encoder_num_angle_o + 'd4 + 'd1;
        else if( encoder_AB_Angle_Cnt == 'd4)
            encoder_num_angle_o <= encoder_num_angle_o + 1'b1;
        else    
            encoder_num_angle_o <= encoder_num_angle_o;
    else
        encoder_num_angle_o <= encoder_num_angle_o;
end

八. 小结

现在一个简单的编码器模块,就写完啦,算是一个基础版本吧,后面会根据需求进行完善。

需要完整模块文件的话关注gzh FPGA之旅 可以回复 编码器1.0 获取

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

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

相关文章

AB试验(五)实验过程中的一些答疑解惑

AB试验&#xff08;五&#xff09;实验过程中的一些答疑解惑 实验结果不显著怎么办 出现实验结果不显著的原因 A/B测试的变化确实没有效果&#xff0c;两组指标在事实上是相同的A/B测试的变化有效果&#xff0c;但由于变化的程度很小&#xff0c;测试灵敏度power不足&#x…

Linux 安全 - LSM机制

文章目录 前言一、LSM起源二、LSM简介2.1 MAC2.2 LSM特征 三、Major and Minor LSMs3.1 Major LSMs3.2 Minor LSMs3.3 BPF LSM 四、LSM 框架五、LSM Capabilities Module六、LSM hooks 说明参考资料 前言 在这两篇文章中介绍了 Linux 安全机制 Credentials &#xff1a; Linu…

关于GD32引脚PA13、PA15、PB3、PB4配置为普通引脚的问题

关于GD32引脚PA13、PA15、PB3、PB4配置为普通引脚的问题 在实际开发中&#xff0c;经常会遇到引脚资源受限需要将一些具有特定功能的引脚配置为普通引脚或其他引脚功能使用的情况。 博主之前遇到过类似的情况&#xff0c;都正常解决了。但偶尔也会出现在配置引脚时少了一些配…

Go语言基础学习教程(一)导学部分

Go语言基础 将在工作中学习的东西整理出来作为一个简单的Go语言基础教程 Go语言 Go语言(Golang)是Google公司2009年推出的一门"高级编程言语", 目的是为了解决: "现有主流编程语言"明显落后于硬件发展速度的问题不能合理利用多核CPU的优势提升软件系统性…

ref与DOM-findDomNode-unmountComponentAtNode知识点及应用例子

​​​​​​http​​​http://t.csdnimg.cn/og3BI 知识点讲解↑ 需求: (下载/导出 用post请求时:) 实例: react部分代码 1、点击下载按钮&#xff0c;需要传给后端数据&#xff0c;到数据扁平&#xff0c;不是那么复杂&#xff0c;只需url地址即可完成下载&#xff0c;后端…

靶场通关记录

目录 一、信息收集-端口扫描 目标开放端口收集 目标端口对应服务探测 信息收集-端口测试 二、 22-SSH弱口令爆破(挂着干别的) 80-HTTP端口的信息收集 三、信息收集-目录访问 漏洞利用-getwebshell 总结 getwebshell → 源码注释发现用户名 → robots.txt发现base64密码 …

mybatisplus接口解析

一、前言 java开发应用程序与数据库交互使用比较多的就是mybatisplus接口。通过mybatisplus接口&#xff0c;我们可以通过程序更好得到对数据库表进行增删查改。 二、mybatisplus Mapper接口源码 /*** Mapper 继承该接口后&#xff0c;无需编写 mapper.xml 文件&#xff0c;即…

1576. 替换所有的问号

1576. 替换所有的问号 C代码&#xff1a;自己写的 char * modifyString(char * s){int n strlen(s);for (int i 0; i < n; i){if (s[i] ?) {if (i ! 0 && i ! n-1) {for (int j 0; j < 26; j) {if (a j ! s[i-1] && a j ! s[i1]) {s[i] a j;br…

SeleniumIDE 自动化用例录制、测试用例结构分析

1、SeleniumIDE用例录制 SeleniumIDE用例录制使用场景 刚开始入门UI自动化测试团队代码基础较差技术成长之后学习价值不高 SeleniumIDE的下载以及安装 官网&#xff1a;https://www.selenium.dev/Chrome插件&#xff1a;https://chrome.google.com/webstore/detail/seleniu…

对音频切分成小音频(机器学习用)

我是把so-vits中小工具&#xff0c;分析源码然后提取出来了。以后可以写在自己的程序里。 -------流程&#xff08;这是我做的流程&#xff0c;你可以不用看&#xff09; 从开源代码中快速获取自己需要的东西 如果有界面f12看他里面的接口&#xff0c;然后在源码中全局搜索&…

英国/法国/意大利/德国/西班牙,电动交通设备合规政策更新!

英国/法国/意大利/德国/西班牙&#xff0c;电动交通设备合规政策更新&#xff01; 产品安全 合规政策更新&#xff01;或加昵称咨询 NOTICE 尊敬的卖家&#xff1a; 您好&#xff01; 我们此次联系您是因为您正在销售需要审批流程的商品。为此&#xff0c;亚马逊正在实施审…

九大装修收纳空间的设计,收藏备用!福州中宅装饰,福州装修

如果房子面积不大&#xff0c;收纳设计就显得非常重要。其实装修房子中很多地方都可以做收纳&#xff0c;九大空间每一处都可以放下你的东西&#xff0c;让你摆脱收纳烦恼。 收纳空间少的话&#xff0c;装修完后住久了怕会乱成一窝&#xff0c;因此装修的时候&#xff0c;收纳…

google hack常用语法介绍

Google hacker (Google黑客)是利用GOOGLE提供的搜索功能查找黑客们想找到的信息.一般是查找网站后台,网管的个人信息,也可以用来查找某人在网络上的活动. Google hacker 一般是做为黑客在入侵时的一个手段.在入侵过程中有时需要查找后台的登陆口就需要用到GOOGLE HACKER.有…

在asp.net中,实现类似安卓界面toast的方法(附更多弹窗样式)

最近在以前的asp.net网页中&#xff0c;每次点击确定都弹窗&#xff0c;然后还要弹窗点击确认&#xff0c;太麻烦了&#xff0c;这次想升级一下&#xff0c;实现类似安卓toast的弹窗提示方式。于是百度了一下&#xff0c;目前看到有两种&#xff0c;sweetalert和toastr。 这里…

Python接口自动化测试实战详解,你想要的全都有

前言 接口自动化测试是当前软件开发中最重要的环节之一&#xff0c;可以提高代码质量、加速开发周期、减少手工测试成本等优点。Python语言在接口自动化测试方面应用广泛&#xff0c;因为它具有简单易学、开发效率高、库丰富等特点。 一、接口自动化测试概述 接口自动化测试…

六个交易日市值蒸发20亿港元,第四范式难逃AI大模型“魔咒”

AI独角兽第四范式终于敲钟了。 北京第四范式智能技术股份有限公司(06682.HK&#xff0c;下称“第四范式”)于9月28日正式挂牌港交所&#xff0c;发行价为55.60港元/股&#xff0c;IPO首日报收58.50港元/股。 上市后6个交易日&#xff0c;截至10月6日港股收盘&#xff0c;第四…

【无监控,不运维!这份监控建设总结太赞了!】

运维行业有句话&#xff1a;“无监控、不运维”&#xff0c;是的&#xff0c;一点也不夸张&#xff0c;监控俗称“第三只眼”。没了监控&#xff0c;什么基础运维&#xff0c;业务运维都是“瞎子”。所以说监控是运维这个职业的根本。 尤其是在现在DevOps这么火的时候&#xf…

【网络安全】网络安全的最后一道防线——“密码”

网络安全的最后一道防线——“密码” 前言超星学习通泄露1.7亿条信息事件武汉市地震监测中心遭境外网络攻击事件 一、密码起源1、 古代密码2、近代密码3、现代密码4、量子密码 二、商密专栏推荐三、如何利用密码保护账号安全&#xff1f;1、账号安全的三大危险&#xff1f;&…

LLaMA Adapter和LLaMA Adapter V2

LLaMA Adapter论文地址&#xff1a; https://arxiv.org/pdf/2303.16199.pdf LLaMA Adapter V2论文地址&#xff1a; https://arxiv.org/pdf/2304.15010.pdf LLaMA Adapter效果展示地址&#xff1a; LLaMA Adapter 双语多模态通用模型 为你写诗 - 知乎 LLaMA Adapter GitH…

PSN 两步验证解除2023.10.9经验贴

背景 本人10月1号收到Sony邮件&#xff0c;说是不规律登录&#xff0c;需修改密码后登录&#xff0c;然后我10月8日登录PS4的时候&#xff0c;提示两步验证。当时就想坏了&#xff0c;然后找B站相关经验贴&#xff0c;10月9号电话香港客服&#xff0c;解除了两步验证&#xff0…