原文:编码器速度和方向检测,371电机方向与速度检测,stm32编码器接口模式

转载链接:http://www.yfrobot.com/thread-2411-1-1.html

出处:yfrobot论坛

作者:aosini

编码器是什么玩意呢,它可是一个好玩的东西,做小车测速必不可少的玩意,下面,我将从编码器的原理讲起,一直到用stm32的编码器接口模式,测出电机转速与方向。

1.编码器

图1 编码器示意图

图1为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。371电机中的码盘就是这样的,他是334线码盘,具有较高的测速精度,也就是电机转一圈输出334个脉冲,芯片上已集成了脉冲整形触发电路,输出的是矩形波,直接接单片机IO就OK。        
     增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向)。下图为编码器的原理图:

图2 增量式旋转编码器

A,B两点对应两个光敏接受管,A,B两点间距为 S2 ,码盘的光栅间距分别为S0和S1。S0+S1的距离是S2的四倍。这样保证了A,B波形相位相差90度。旋转的反向不同,锯齿波A,B先到达高电平的顺序就会不同,如上图左侧所示,顺序的不同,就可以得到旋转的方向。

2.stm32编码器接口模式(寄存器)
        stm32的编码器接口模式在STM32中文参考手册中有详细的说明,在手册273页,14.3.12节。程序是完全按照 下图方式,设置寄存器的。

图3

从图3中可以看出,TI1波形先于TI2波形90°时,每遇到一个边沿变化是,计数器加1(可以通过寄存器设置加减),可以看出一个光栅,被计数了4次。TI1波形后于TI2波形90°时 ,每遇到一次边沿变化,计数器减1。
[color=rgb(51,102,153) !important]

  1. //TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)
  2. //arr:自动重装值 0XFFFF
  3. //psc:时钟预分频数        ,不分频
  4. void TIM2_Encoder_Init(u16 arr,u16 psc)
  5. {
  6. RCC->APB1ENR|=1<<0;       //TIM2时钟使能
  7. RCC->APB2ENR|=1<<2;       //使能PORTA时钟
  8. GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置
  9. GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入
  10. TIM2->ARR=arr;            //设定计数器自动重装值
  11. TIM2->PSC=psc;            //预分频器
  12. TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  13. TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  14. TIM2->CCER |= 0<<1;                  //IC1不反向
  15. TIM2->CCER |= 0<<5;           //IC2不反向
  16. TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效
  17. TIM2->CR1 |= 1<<0;                  //使能计数器
  18. }

复制代码

3 硬件

用到的模块有STM32核心板、L298电机驱动、371带编码器电机(1:34)。这里主要介绍一下电机,1:34指的是电机轴转动34圈,电机输出1圈。1:X,X值越小,电机的输出转速也就越快,扭矩也就越小;反之,X值越大,电机的输出转速越慢,扭矩也越大。

图4 电机实物图

左边两根黄线是电机两极。绿线和白线是脉冲输出线,分别接编码器的接收管A、B,用一根可以测得速度,两根同时用可测出电机速度与转向。红线和黑线是编码器电源接线,红正黑负,电压3.3V-5V,不不可接反。

4 控制代码

工作指示灯、电机方向与速度控制代码。

  1. //LED IO 初始化 端口PD.2  运行指示灯
  2. void LED_Init(void)
  3. {
  4. RCC->APB2ENR|=1<<5;      //使能PORTD时钟
  5. GPIOD->CRL&=0XFFFFF0FF;
  6. GPIOD->CRL|=0X00000300;  //PD.2推挽输出
  7. GPIOD->ODR|=1<<2;        //PD.2输出高
  8. }
  9. //电机旋转方向控制信号端口初始化
  10. //PC1~0推挽输出,输出高
  11. void M_Init(void)
  12. {
  13. RCC->APB2ENR|=1<<4;      //使能PORTC时钟
  14. GPIOC->CRL&=0XFFFFFF00;
  15. GPIOC->CRL|=0X00000033;  //PC1~0推挽输出
  16. GPIOC->ODR|=0XF<<0;             //PC1~0输出高电平
  17. }
  18. //定时器TIM3,PWM输出初始化,CH1(PA6)
  19. //arr:自动重装值
  20. //psc:时钟预分频数
  21. //设置自动重装值为900,那么PWM频率=72000/900=8Khz
  22. 见STM32参考手册,14.3.9PWM模式。
  23. void TIM3_PWM_Init(u16 arr,u16 psc) //arr设定计数器自动重装值
  24. //psc预分频器不分频,psc=0
  25. {
  26. RCC->APB1ENR|=1<<1;       //TIM3时钟使能
  27. GPIOA->CRL&=0XF0FFFFFF;//PA6输出
  28. GPIOA->CRL|=0X0B000000;//复用功能输出
  29. GPIOA->ODR|=1<<6;//PA6上拉
  30. TIM3->ARR=arr;//设定计数器自动重装值
  31. TIM3->PSC=psc;//预分频器不分频
  32. TIM3->CCMR1|=6<<4;  //CH1 PWM1模式        高电平有效
  33. TIM3->CCMR1|=1<<3; //CH1预装载使能
  34. TIM3->CCER|=1<<0;   //OC1 输出使能
  35. TIM3->CR1=0x0080;   //ARPE使能
  36. TIM3->CR1|=0x01;    //使能定时器3
  37. }
  38. //电机方向与速度控制,速度调节范围为-100~+100
  39. //大于0时,正转,小于0时,反转
  40. // 占空比低于0.4时电机不转
  41. //(占空比是指高电平在一个周期之内所占的时间比率)
  42. //TIM3->CCR1的设定范围为0~900(因为arr=900)
  43. //见STM32参考手册,14.3.9PWM模式。
  44. void Motor_Speed_Control(s16 motorSpeed)
  45. {
  46. s16 speed = 0 ;
  47. if(motorSpeed>100)  speed = 100;
  48. else if (motorSpeed<-100)  speed = -100;
  49. else  speed = motorSpeed;
  50. if(speed == 0)
  51. {
  52. M_1 = 0;
  53. M_2 = 0;
  54. }
  55. else if(speed > 0)
  56. {
  57. M_1 = 0;
  58. M_2 = 1;
  59. TIM3->CCR1 = speed * 9;
  60. }
  61. else
  62. {
  63. M_1 = 1;
  64. M_2 = 0;
  65. TIM3->CCR1 = -speed * 9;
  66. }
  67. }

复制代码

电机速度与方向检测代码

  1. //TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)
  2. //arr:自动重装值 0XFFFF
  3. //psc:时钟预分频数        ,不分频
  4. //见STM32中文手册 14.3.12编码器接口模式
  5. void TIM2_Encoder_Init(u16 arr,u16 psc)
  6. {
  7. RCC->APB1ENR|=1<<0;       //TIM2时钟使能
  8. RCC->APB2ENR|=1<<2;       //使能PORTA时钟
  9. GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置
  10. GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入
  11. TIM2->ARR=arr;            //设定计数器自动重装值
  12. TIM2->PSC=psc;            //预分频器
  13. TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  14. TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  15. TIM2->CCER |= 0<<1;                  //IC1不反向
  16. TIM2->CCER |= 0<<5;           //IC2不反向
  17. TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效
  18. TIM2->CR1 |= 1<<0;                  //使能计数器
  19. }
  20. //计数寄存器赋值
  21. void TIM2_Encoder_Write(int data)
  22. {
  23. TIM2->CNT = data;
  24. }
  25. //读计数个数
  26. int TIM2_Encoder_Read(void)
  27. {
  28. TIM2_Encoder_Write(0);        //计数器清0
  29. delay_ms(10);          //检测时间,可调节
  30. return (int)((s16)(TIM2->CNT));           //数据类型转换
  31. //记录边沿变化次数(一个栅格被记录4次)
  32. }

复制代码

这里我们只显示边沿变化次数,没有具体的算出速度。
主函数

  1. int main(void)
  2. {
  3. //        motorSpeed的范围为-100 ~ +100;
  4. s16 motorSpeed = 100;
  5. Stm32_Clock_Init(9); //系统时钟设置
  6. delay_init(72);             //延时初始化
  7. uart_init(72,9600);  //串口1初始化
  8. LED_Init();                         //初始化与LED连接的硬件接口
  9. M_Init();                           初始化电机运行方向控制端口
  10. TIM3_PWM_Init(900,0);          //不分频。PWM频率=72000/900=8Khz
  11. TIM2_Encoder_Init(0xffff, 0); //计数器自动重装值为最大
  12. while(1)
  13. {
  14. LED =! LED;
  15. Motor_Speed_Control(motorSpeed);
  16. printf("编码器值:%d\n ",TIM2_Encoder_Read());
  17. }
  18. }

复制代码

5 估算验证
         这里我们只是大概的估算验证测量值是否正确,不具有完全正确性。
        我们设置motorSpeed = 100 ,得到测量值如下图:

图5 motorSpeed = 100

因为误差是不可避免的,所以看到每次检测的值都是不一样的。我们取462,因为一个光栅被记录了4次,所以在10ms内一共检测到了462/4=115.5,那么得到11.55个/ms,每ms内检测到11.55个光栅。

通过码表,记录电机输出50圈,用时50.2s,那么这时应该检测到的光栅个数为50*34(电机转34圈,输出1圈)*334(每圈有334个光栅)=567800,除以时间,得到估算值11.31个/ms。可以看出估算值与测量值是相近的,认为测量是准确的。
      设置motorSpeed = -50 ,得到测量值如下图 :

图6 motorSpeed=-50

可以看到测量值是负值,说明电机是反转,与实际设置相符。

附件

 stm32 编码器接口.rar (76.87 KB, 下载次数: 39)

我们读的是计数器TIM2->CNT中的值,此值为什么会是负的,这里为什么这样用?      编码器模式中使用上下计数,假设我们初始化TIM2_Encoder_Init_1(0xff, 0);自动装载值为0xFF,这时,计数器中的值,就会在0x00与0xFF之间循环变化,由0x01减为0x00,再减1时,计数器中的值为0xFF,我们将此数做为有符型整数处理,当然,计数的前提是每个周期的计数个数不能超过0x7F,超过,计数将不准确。
      符号强制转换,return (int)((s16)(TIM2->CNT));里面有个类型转换,强制转换返回有符型数据。数值都是以补码表示的,正整数补码是源码,负整数补码是绝对值取反加1。向下计数时减1,为0时,就需要向高位借位减“1”,可以这样理解,一个8位数00000000B-00000001B,但0不够减1的,就向不存在的第9位借1,100000000B-00000001B=11111111B,数是以补码形式表示的,这样11111111B就为-1了。
      在例程中,初始化自动重装值为0xFFFF可以做个实验,直接输出TIM2->CNT的值看一下:      printf("编码器值1:%x \r\n",TIM2->CNT)。

stm32增量式光电编码器相关推荐

  1. Arduino、AB相增量式光电编码器测位移和速度方向

    利用Arduino.增量式光电编码器测量速度.方向.位移. 学校的一个项目作业,实测有效,若有改进的地方还需大佬们指点. 材料: Arduino mega 2560 2个2k电阻(红白之间2k,红绿之 ...

  2. 光电编码器的原理及应用场合_增量式光电编码器的构造和原理及应用

    内容摘要:光电编码器是一种精度高的数字化检测装置,外部有一个可以左右旋转同时又可按下的旋钮,被广泛用于车载电子设备的菜单选择和调节等.主要以日本阿尔卑斯EC11J微型光电编码器为例,分析了增量式光电编 ...

  3. 旋转增量式拉绳编码器出现故障应急处理

    旋转增量式拉绳编码器出现故障应急处理 旋转增量式拉绳编码器以转动时输出脉冲,通过计数设备来知道其位置,当编码器不动或停电时,依靠计数设备的内部记忆来记住位置.这样,当停电后,编码器不能有任何的移动,当 ...

  4. 增量式旋转编码器的使用,以arduino为例

    简介 旋转编码器是一种位置传感器,用于确定转轴的位置.旋转运动时,产生电信号,可以输出数字信号,也可以输出模拟信号. 组成 旋转编码器一般由5个引脚组成,前3个一起的引脚分别表示输出引脚A端,按纽公共 ...

  5. 增量式旋转编码器工作原理

    增量式旋转编码器工作原理 增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向).在接合数字电路特别是单片机后,增量式旋转编码器在 ...

  6. stm32+增量式pid+max6675 PWM温度控制

    stm32+增量式pid+max6675 PWM温度控制 本文采用的芯片为STM32F103RCT6 温度芯片为MAX6675 之前spi通讯的max6675代码: https://blog.csdn ...

  7. Arduino实现增量式旋转编码器(欧姆龙e6b2-cwz6c)程序编写

    最近由于项目需求,须采用编码器进行小车的速度和里程测量.由于考虑到Arduino的编程简便性,因此采用Arduino作为控制器.搜索了相关资料,发现STM32或者51单片机的编码器程序比较多.其中ST ...

  8. STM32增量式pid直流电机调速(内附源码)

    目录 一. 1.硬件组成 2.模块分析 1.TB6612电机驱动模块 2.直流减速电机 3.电源稳压模块 二.接线 三.代码思路讲解(详见源码) 四.STM32cubmx配置 1.系统基础配置:(重要 ...

  9. 【虹科新品】HK-MR340系列增量式光纤编码器产品介绍合集

    前言 HK-MR340系列产品很多?想要通过一篇文章迅速了解?那快点击本文进行浏览吧!本文将从一般特性.规格.应用三个角度讲解HK-MR340系列产品,让您快速对其具有框架性的了解. 01 一般特性 ...

  10. 增量式编码器c语言,增量式编码器

    机器人运行过程中,电机转动会产生各种干扰信号.通过两组电源给机器人驱动系统和控制系统供电,以消除干扰对稳定性的影响. 码盘加陀螺仪的方法在应用过程中发现陀螺仪的角度会随着机械振动发生漂移,影响定位精度 ...

最新文章

  1. 最新论文解读 | 神经网络“剪枝”的两个方法
  2. lintcode:打劫房屋 III
  3. python编程入门t-python高级编程——入门语法(一)
  4. mysql函数数组参数_MYSQL数组聚合函数,如PostgreSQL array_agg
  5. 如何用java写单链表_如何使用Java实现单链表?
  6. 微信朋友圈五月十大谣言:60岁以上老人打962899可享免费服务
  7. DUBBO监控环境搭建
  8. DeepFake——实际操作
  9. android 渐变歌词,Android UI之自定义——最简单的仿QQ音乐歌词颜色渐变
  10. 多功能芯片——GSV2002
  11. Windows磁盘清理方案
  12. JS 获取操作删除节点
  13. 加速度传感器 mag_将电话连接到没有辅助扬声器mag的汽车立体声
  14. 三年上一大台阶,联想凌拓做对了什么?
  15. 联想计算机系统还原怎么弄,【联想笔记本电脑一键还原的使用方法】 联想一键还原...
  16. 无向图全局最小边割集
  17. ps3能装linux上网,上百度聊QQ 装Linux让你的PS3无所不能
  18. java tongpaiyu danliantiao_五年级语文第一学期词语表
  19. Web 前端从入门菜鸟到实践老司机所需要的资料与指南合集
  20. vue动画transition

热门文章

  1. 美女的大眼睛远看才美
  2. C++ 中两个数据交换总结
  3. oracle merge into where,Oracle merge into语法简介
  4. docker php示例,Docker 编程语言之 PHP
  5. cassandra可视化工具_精华 | 140种Python标准库、第三方库和外部工具都有了
  6. sdr 软件_SDR软件定义无线电是什么?不仅仅是大频谱
  7. phpstudy mysql 漏洞_phpstudy后门漏洞复现php5.2
  8. C语言编译过程总结简版
  9. maven安装jar包到本地仓库
  10. 禅道---Bug管理模块