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

一. 简介

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

霍尔编码器一般有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) beginif( sys_rst_n_i == 1'b0 ) beginstep <= 6'b00_0000;encoder_AB_detect_dir_reg <= 1'b0;endelse begincase (step)6'b00_0000: begin                 //处理第一个边沿if( (encoder_A_posedge  | encoder_B_posedge) && encoder_AB_detect_en_i == 1'b1)  step <= 6'b00_0001;elsestep <= step;end6'b00_0001: begin  //处理第二个边沿if( encoder_A_posedge == 1'b1)if( encoder_B_d0 == 1'b1) beginstep <= 6'b00_0100;encoder_AB_detect_dir_reg <= 1'b0; //在第二个边沿的时候,确定旋转方向endelsestep <= 6'b00_0000;else if( encoder_B_posedge == 1'b1)if( encoder_A_d0 == 1'b1) beginstep <= 6'b00_0010;encoder_AB_detect_dir_reg <= 1'b1; //在第二个边沿的时候,确定旋转方向endelsestep <= 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) beginif( sys_rst_n_i == 1'b0) beginencoder_Phase_Cnt_dir0 <= 16'd0;encoder_Phase_Cnt_dir1 <= 16'd0;endelse if( encoder_Phase_count_clear_i == 1'b1 ) begin  //定时器输入,重新开始计数encoder_Phase_Cnt_dir0 <= 16'd0;encoder_Phase_Cnt_dir1 <= 16'd0;endelse if( encoder_AB_detect_valid_i == 1'b1 )  //对两个方向的脉冲分别计数if( encoder_AB_detect_dir_i == 1'b0 ) beginencoder_Phase_Cnt_dir0 <= encoder_Phase_Cnt_dir0 + 1'b1;encoder_Phase_Cnt_dir1 <= encoder_Phase_Cnt_dir1;endelse beginencoder_Phase_Cnt_dir0 <= encoder_Phase_Cnt_dir0;encoder_Phase_Cnt_dir1 <= encoder_Phase_Cnt_dir1 + 1'b1;   endelse beginencoder_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 ) beginif( sys_rst_n_i == 1'b0 ) beginencoder_speed_d0 <= 16'd0;encoder_speed_o  <= 16'd0;encoder_acc_o    <= 16'd0;encoder_acc_dir_o<= 1'b0;endelse if( cal_en_i == 1'b1 ) beginencoder_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;endelse beginencoder_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 ) beginif( 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;elseencoder_num_angle_o <= encoder_num_angle_o;
end

八. 小结

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

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

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

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

相关文章

基于springboot实现家具销售电商平台管理系统项目【项目源码+论文说明】

基于springboot实现家具销售电商平台管理系统演示 摘要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的交易方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&am…

ssti 前置学习

python venv环境 可以把它想象成一个容器&#xff0c;该容器供你用来存放你的Python脚本以及安装各种Python第三方模块&#xff0c;容器里的环境和本机是完全分开的 创建venv环境安装flask #apt install python3.10-venv #cd /opt #python3 -m venv flask1 #cd /opt 选…

信息增益,经验熵和经验条件熵——决策树

目录 1.经验熵 2.经验条件熵 3.信息增益 4.增益比率 5.例子1 6.例子2 在决策树模型中&#xff0c;我们会考虑应该选择哪一个特征作为根节点最好&#xff0c;这里就用到了信息增益 通俗上讲&#xff0c;信息增益就是在做出判断时&#xff0c;该信息对你影响程度的大小。比…

SpringCloud源码探析(十)-Web消息推送

1.概述 消息推送在日常使用中的场景比较多&#xff0c;比如有人点赞了我的博客或者关注了我&#xff0c;这时我就会收到一条推送消息&#xff0c;以此来吸引我点击或者打开应用。消息推送的方式主要分为两种&#xff1a;web消息推送和移动端消息推送。它将所要发送的信息&…

剑指offer——JZ84 二叉树中和为某一值的路径(三) 解题思路与具体代码【C++】

一、题目描述与要求 二叉树中和为某一值的路径(三)_牛客题霸_牛客网 (nowcoder.com) 题目描述 给定一个二叉树root和一个整数值 sum &#xff0c;求该树有多少路径的的节点值之和等于 sum 。 1.该题路径定义不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff…

【已解决】msvcp140.dll丢失怎样修复?msvcp140.dll重新安装的解决方法

今天我要和大家分享的是关于msvcp140.dll丢失的五种不同解决方法。我们知道&#xff0c;在运行一些软件或游戏的时候&#xff0c;经常会遇到“msvcp140.dll丢失”的问题&#xff0c;这可能会影响到我们的使用体验。那么&#xff0c;面对这个问题&#xff0c;我们应该如何应对呢…

【2023研电赛】安谋科技企业命题特别奖:面向独居老人的智能居家监护系统

本文为2023年第十八届中国研究生电子设计竞赛安谋科技企业命题特别奖分享&#xff0c;参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&#xff01;&#xff0c;分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来…

Http请求响应 Ajax 过滤器

10/10/2023 近期总结&#xff1a; 最近学的后端部署&#xff0c;web服务器运行&#xff0c;各种请求响应&#xff0c;内容很多&#xff0c;学的很乱&#xff0c;还是需要好好整理&#xff0c;前面JavaSE内容还没有完全掌握&#xff0c;再加上一边刷题&#xff0c;感觉压力很大哈…

JavaScript Web APIs第五天笔记

Web APIs - 第5天笔记 目标&#xff1a; 能够利用JS操作浏览器,具备利用本地存储实现学生就业表的能力 BOM操作综合案例 js组成 JavaScript的组成 ECMAScript: 规定了js基础语法核心知识。比如&#xff1a;变量、分支语句、循环语句、对象等等 Web APIs : DOM 文档对象模型&…

IP协议总结

一、定义。 IP全称为Internet Protocol&#xff0c;是TCP/IP协议族中的一员&#xff0c;负责实现数据在网络上的传输。它是一种无连接、不可靠的数据报协议。 IP协议常用于Internet网络和局域网中&#xff0c;它通过将数据包进行分组并进行逐跳转发来实现数据在网络中的传输。…

攻防世界题目练习——Web引导模式(一)

题目目录 1. command_execution2.xff_referer3.simple_js4.php_rce5.Web_php_include6.upload17. warmup 难度1全部写过了&#xff0c;这个系列里没有 指路&#xff1a; 攻防世界题目练习——Web难度1&#xff08;一&#xff09; 攻防世界题目练习——Web难度1&#xff08;二&a…

【力扣2011】执行操作后的变量值

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析 一、题目描述 题目链接&#xff1a;执行操作后的变量值 存在一种仅支持 4 种操作和 1 个变量 …

Python 无废话-办公自动化Excel格式美化

设置字体 在使用openpyxl 处理excel 设置格式&#xff0c;需要导入Font类&#xff0c;设置Font初始化参数&#xff0c;常见参数如下&#xff1a; 关键字参数 数据类型 描述 name 字符串 字体名称&#xff0c;如Calibri或Times New Roman size 整型 大小点数 bold …

mysql面试题34:Hash索引和B+树区别是什么?在设计索引怎么选择?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Hash索引和B+树区别是什么?在设计索引怎么选择? 在MySQL中,Hash索引和B+树索引是两种常见的索引类型,他们有以下区别: 数据结构:Hash索引:…

【小沐学Python】Python实现Web图表功能(Dash)

文章目录 1、简介2、安装3、功能示例3.1 Hello World3.2 连接到数据3.3 可视化数据3.4 控件和回调3.5 设置应用的样式3.5.1 HTML and CSS3.5.2 Dash Design Kit (DDK)3.5.3 Dash Bootstrap Components3.5.4 Dash Mantine Components 4、更多示例4.1 Basic Dashboard4.2 Using C…

从0开始学go第六天

方法一&#xff1a;gin获取querystring参数 package main//querystring import ("net/http""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/web", func(c *gin.Context) {//获取浏览器那边发请求携带的query String参数//…

基于 Mtcnn(人脸检测)+Hopenet(姿态检测)+拉普拉斯算子(模糊度检测) 的人脸检测服务

写在前面 工作原因&#xff0c;顺便整理博文内容为一个 人脸检测服务分享以打包 Docker 镜像&#xff0c;可以直接使用服务目前支持 http 方式该检测器主要适用低质量人脸图片处理理解不足小伙伴帮忙指正&#xff0c;多交流&#xff0c;相互学习 对每个人而言&#xff0c;真正的…

【Python】WebUI自动化—Selenium的下载和安装、基本用法、项目实战(16)

文章目录 一.介绍二.下载安装selenium三.安装浏览器驱动四.QuickStart—自动访问百度五.Selenium基本用法1.定位节点1.1.单个元素定位1.2.多个元素定位 2.控制浏览器2.1.设置浏览器窗口大小、位置2.2.浏览器前进、刷新、后退、关闭3.3.等待3.4.Frame3.5.多窗口3.6.元素定位不到…

为Yolov7环境安装Cuba匹配的Pytorch

1. 查看Cuba版本 方法一 nvidia-smi 找到CUDA Version 方法二 Nvidia Control Panel > 系统信息 > 组件 > 2. 安装Cuba匹配版本的PyTorch https://pytorch.org/get-started/locally/这里使用conda安装 conda install pytorch torchvision torchaudio pytorch-cu…

Oracle笔记-对ROWNUM的一次理解(简单分页)

此博文记录时间&#xff1a;2023-05-05&#xff0c;发到互联网上是2023-10-09 这个在分页里面用得比较多&#xff0c;在MySQL中&#xff0c;通常使用limit去操作&#xff0c;而去感觉比较简单&#xff0c;Oracle中无此关键字。 通过查阅资料后&#xff0c;要实现分页需要用到…