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

编码器是什么玩意呢,它可是一个好玩的东西,做小车测速必不可少的玩意,下面,我将从编码器的原理讲起,一直到用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。
  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.         
  9.     GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置
  10.     GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入
  11.             
  12.     TIM2->ARR=arr;            //设定计数器自动重装值 
  13.     TIM2->PSC=psc;            //预分频器

  14.         TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  15.         TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  16.         TIM2->CCER |= 0<<1;                  //IC1不反向
  17.         TIM2->CCER |= 0<<5;           //IC2不反向
  18.         TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效
  19.         TIM2->CR1 |= 1<<0;                  //使能计数器
  20. }
复制代码
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.                   
  28.         GPIOA->CRL&=0XF0FFFFFF;//PA6输出
  29.         GPIOA->CRL|=0X0B000000;//复用功能输出           
  30.         GPIOA->ODR|=1<<6;//PA6上拉        

  31.         TIM3->ARR=arr;//设定计数器自动重装值 
  32.         TIM3->PSC=psc;//预分频器不分频
  33.         
  34.         TIM3->CCMR1|=6<<4;  //CH1 PWM1模式        高电平有效         
  35.         TIM3->CCMR1|=1<<3; //CH1预装载使能

  36.         TIM3->CCER|=1<<0;   //OC1 输出使能   

  37.         TIM3->CR1=0x0080;   //ARPE使能 
  38.         TIM3->CR1|=0x01;    //使能定时器3 
  39. }

  40. //电机方向与速度控制,速度调节范围为-100~+100
  41. //大于0时,正转,小于0时,反转
  42. // 占空比低于0.4时电机不转
  43. //(占空比是指高电平在一个周期之内所占的时间比率)
  44. //TIM3->CCR1的设定范围为0~900(因为arr=900)
  45. //见STM32参考手册,14.3.9PWM模式。
  46. void Motor_Speed_Control(s16 motorSpeed)         
  47. {
  48.     s16 speed = 0 ;        
  49.         
  50.     if(motorSpeed>100)  speed = 100;
  51.             else if (motorSpeed<-100)  speed = -100;
  52.                         else  speed = motorSpeed;
  53.         if(speed == 0)
  54.         {
  55.                 M_1 = 0;
  56.                 M_2 = 0;
  57.         }
  58.             else if(speed > 0)
  59.                 {
  60.                         M_1 = 0;
  61.                         M_2 = 1;
  62.                         TIM3->CCR1 = speed * 9;
  63.                 }
  64.                         else
  65.                         {
  66.                                 M_1 = 1;
  67.                                 M_2 = 0;
  68.                                 TIM3->CCR1 = -speed * 9;
  69.                         }
  70. }
复制代码

电机速度与方向检测代码

  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.         
  10.     GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置
  11.     GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入
  12.             
  13.     TIM2->ARR=arr;            //设定计数器自动重装值 
  14.     TIM2->PSC=psc;            //预分频器

  15.         TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  16.         TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  17.         TIM2->CCER |= 0<<1;                  //IC1不反向
  18.         TIM2->CCER |= 0<<5;           //IC2不反向
  19.     TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效
  20.         TIM2->CR1 |= 1<<0;                  //使能计数器
  21. }
  22. //计数寄存器赋值
  23. void TIM2_Encoder_Write(int data)
  24. {
  25.     TIM2->CNT = data;
  26. }
  27. //读计数个数
  28. int TIM2_Encoder_Read(void)
  29. {
  30.     TIM2_Encoder_Write(0);        //计数器清0
  31.         delay_ms(10);          //检测时间,可调节
  32.     return (int)((s16)(TIM2->CNT));           //数据类型转换
  33.                              //记录边沿变化次数(一个栅格被记录4次)
  34. }
复制代码

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

  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

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

      我们读的是计数器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, 1 00000000B-00000001B=11111111B,数是以补码形式表示的,这样11111111B就为-1了。
      在例程中,初始化自动重装值为0xFFFF可以做个实验,直接输出TIM2->CNT的值看一下:      printf("编码器值1:%x \r\n",TIM2->CNT)。
### 回答1: Arduino 霍尔编码电机是一种使用霍尔传感器检测电机位置的电机控制系统。霍尔编码电机通过在电机的旋转轴上安装磁极和霍尔传感器,实时测量磁场的变化来确定电机的位置和转速。 在Arduino上控制霍尔编码电机的过程如下: 首先,需要将霍尔传感器连接到Arduino的IO引脚上。可以使用数字输入引脚来读取霍尔传感器的输出信号。 然后,需要创建一个Arduino程序来读取和处理传感器的输出数据。可以使用digitalRead()函数来读取引脚上的电平值,如果引脚上检测到磁场变化,电平值会改变。可以通过定时器来测量引脚电平变化的时间差,从而得到电机的转速和方向。 接下来,可以根据传感器输出的数据来控制电机的运动。根据电平变化的时间差,可以计算出电机的转速,并根据电平变化的方向来确定电机的转向。可以使用PWM信号和电机驱动器来控制电机速度方向。 最后,可以根据需要编写其他功能,例如电机速度控制、位置控制等。 总结来说,Arduino霍尔编码电机是一种用霍尔传感器检测电机位置的电机控制系统。通过连接和读取传感器的输出数据,可以实时获取电机的转速和方向,并通过控制信号控制电机的运动。这些功能可以通过Arduino编程来实现。 ### 回答2: Arduino霍尔编码电机是指通过使用霍尔效应传感器检测电机的转速和转向,并且将这些信息传递给Arduino控制器进行处理的电机。霍尔编码电机通常由电机、霍尔效应传感器和Arduino控制器组成。 首先,霍尔效应传感器是一种基于霍尔效应的设备,可以检测磁场的存在和变化。在电机的转子上固定一个磁铁,并安装霍尔效应传感器检测磁场的变化。当电机转动时,磁铁会与霍尔效应传感器产生交互作用,传感器会生成相应的信号。 接下来,Arduino控制器可以读取霍尔传感器的信号,并根据信号的变化来判断电机的转速和转向。当电机转动时,传感器会生成一个脉冲,每个脉冲代表电机转动的一个步长。通过计算每秒钟脉冲的数量,我们可以得到电机的转速。而通过监测脉冲的方向,我们可以判断电机的转向。 最后,Arduino控制器可以根据读取到的转速和转向信息来对电机进行控制。比如,我们可以编写程序来控制电机的转速,或者根据一定的逻辑来改变电机的转向。 综上所述,Arduino霍尔编码电机通过使用霍尔效应传感器检测电机的转速和转向,并将这些信息传递给Arduino控制器进行处理和控制。这种电机具有高精度、稳定性好的特点,常用于需要精确控制转速和转向的应用领域,如机器人、自动化设备等。 ### 回答3: Arduino霍尔编码电机是一种可编程的电机,可以通过Arduino开发板控制。霍尔编码器是一种能够测量转子位置的装置,它利用霍尔效应来实现。这种编码器可以精确地测量电机的转速和旋转方向。 通过Arduino霍尔编码电机,我们可以实现一些功能,比如控制电机的转速和方向。通过编程,我们可以调整电机的转速,使其适应不同的应用场景。同时,我们也可以控制电机的旋转方向,使其正转或反转。 使用Arduino开发板控制霍尔编码电机还可以实现一些高级功能。比如,我们可以通过编程设置电机的加速度和减速度,实现平滑的启停效果。我们还可以根据需求设定电机的角度范围,并设置目标角度,使其自动旋转到目标角度位置。 与传统的直流电机相比,Arduino霍尔编码电机具有一些优势。首先,霍尔编码器可以提供精确的位置反馈,使得电机控制更加准确。其次,通过编程可以实现更多的功能和定制化的操作。此外,Arduino开发板的开放性使得学习和使用变得更加简单和方便。 总之,Arduino霍尔编码电机是一种多功能的电机,可以通过Arduino开发板实现精确的控制和定制化的操作。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值