STM32-增量式旋轉編碼器測量


 

Development kit:MDK5.14

IDE:UV4

MCU:STM32F103C8T6

一、增量式旋轉編碼器

1、簡介

  • 編碼器(encoder)是將信號(如比特流)或數據進行編制、轉換為可用以通訊、傳輸和存儲的信號形式的設備。編碼器把角位移或直線位移轉換成電信號,前者稱為碼盤,后者稱為碼尺。
  • 按照讀出方式編碼器可以分為接觸式和非接觸式兩種;
  • 按照工作原理編碼器可分為增量式和絕對式兩類。增量式編碼器是將位移轉換成周期性的電信號,再把這個電信號轉變成計數脈沖,用脈沖的個數表示位移的大小。絕對式編碼器的每一個位置對應一個確定的數字碼,因此它的示值只與測量的起始和終止位置有關,而與測量的中間過程無關。 
  • 旋轉編碼器是集光機電技術於一體的速度位移傳感器。它將被測的角位移直接轉換成數字信號(高速脈沖信號)。
  • 我們通常用的是增量型編碼器,可將旋轉編碼器的輸出脈沖信號直接輸入給PLC,利用PLC的高速計數器對其脈沖信號進行計數,以獲得測量結果。不同型號的旋轉編碼器,其輸出脈沖的相數也不同,有的旋轉編碼器輸出A、B、Z三相脈沖,有的只有A、B相兩相,最簡單的只有A相。A、B為相差90度的脈沖,Z相信號在編碼器旋轉一圈只有一個脈沖,通常用來做零點的依據,連接時要注意PLC輸入的響應時間。旋轉編碼器還有一條屏蔽線,使用時要將屏蔽線接地,提高抗干擾性。
  • 信號輸出有正弦波(電流或電壓),方波(TTL、HTL),集電極開路(PNP、NPN),推拉式多種形式,其中TTL為長線差分驅動(對稱A,A-;B,B-;Z,Z-),HTL也稱推拉式、推挽式輸出,編碼器的信號接收設備接口應與編碼器對應。信號連接—編碼器的脈沖信號一般連接計數器、PLC、計算機,PLC和計算機連接的模塊有低速模塊與高速模塊之分,開關頻率有低有高。如單相聯接,用於單方向計數,單方向測速。A.B兩相聯接,用於正反向計數、判斷正反向和測速。A、B、Z三相聯接,用於帶參考位修正的位置測量。A、A-,B、B-,Z、Z-連接,由於帶有對稱負信號的連接,在后續的差分輸入電路中,將共模噪聲抑制,只取有用的差模信號,因此其抗干擾能力強,可傳輸較遠的距離。對於TTL的帶有對稱負信號輸出的編碼器,信號傳輸距離可達150米。
  • 線數:旋轉一周信號線輸出脈沖數,也成為分辨率

2、型號

博主此篇文章使用的旋轉編碼器型號有兩種。

傳感器(增量式旋轉編碼器)
型號 供電電壓 輸出方式 分辨率 品牌/廠家 輸出電平
S20-1000型拉線位移傳感器 5-24V NPN集電極開路 400 Omron/歐姆龍   

DT100E40R1024-HI

增量型大孔徑編碼器

 5-30V  HTL(推挽式)  1024

冬蒞自動化技術(上海)有限公司

www.shdongli.cn

高:VCC*70%

低:1V

 

 

 

 

 

 

 

 

二、硬件設計

   由於增量型編碼器輸出脈沖,可以直接接入PLC單片機,利用PLC高速計數器進行測量。將編碼器接入STM32單片機需要一個定時器資源,並將定時器配置為編碼器模式,稍后會簡要介紹配置方法。根據傳感器的輸出方式,進而來判斷是否需要進行信號預處理。對於集電極開路輸出的傳感器接入必須使用上拉電阻。注意STM32大多數引腳的輸入電壓都在3.3V左右,盡量不要過壓。如果電壓較大,最好加隔離電路,比如6N136光耦,類似下圖

 

  我在這里並沒有使用隔離電路,而是對傳感器統一使用了5V供電,並在信號接入端人為加了3.3V上拉(上拉電阻1K),這種接口電路在我自己設計的采集板上統一留出了8個。編碼器應用中並未使用Z相,僅使用了A、B兩相進行編碼器計數。按照線序說明接入STM32的定時器引腳,PA6、PA7對應TIM3的CH1、CH2通道,PB6、PB7對應TIM4的CH1、CH2通道。對於第二種傳感器的推挽輸出方式而言,實驗證明這種接入電路也是可行的。(具體電路沒有進行分析,只是圖個方便。但是5*70%=3.5V應該是勉強可以直接接入stm32引腳的)

三、軟件設計

1、STM32定時器編碼器模式簡介

  參考官方文檔,摘錄幾個要點:

  • 編碼器接口模式基本上相當於使用了一個帶有方向選擇的外部時鍾。
  • 兩個輸入TI1和TI2被用來最為增量編碼器的接口,TI1FP1和TI2FP2是TI1和TI2在通過濾波器和極性控制后的信號,計數器由每次在TI1FP1和TI2FP2的有效跳變驅動,根據跳變順序,產生計數脈沖和方向信號,計數器向上或向下計數,同時硬件對TIMx_CR1寄存器的DIR位進行相應設計
  • IC1、TI1概念理解:TI1是定時器輸入通道,IC1是輸入捕獲通道(兩者可以交錯)。配置CCMR1寄存器的CC1S位可以指定IC1的映射方式。可配置濾波器和預分頻器。

 

  •  計數方向與編碼器信號的關系

2、軟件實現

 1 /********************************************  2 
 3 TIM3、TIM4定時器編碼器模式配置  4 
 5 *********************************************/
 6 
 7 #include "sys.h"
 8 #include "encoder.h"
 9 
 10 int TIM3ITCount=0;//中斷溢出次數
 11 int TIM4ITCount=0;//中斷溢出次數
 12 
 13 void TIM3_IRQHandler(void)  14 {  15     if(TIM3->SR&0x0001)//溢出中斷
 16  {  17         
 18  }  19     TIM3->SR&=~(1<<0);//清除標志位 
 20 }  21 
 22 void TIM4_IRQHandler(void)  23 {  24     if(TIM4->SR&0x0001)//溢出中斷
 25  {  26  }  27     TIM4->SR&=~(1<<0);//清除標志位 
 28 }  29 
 30 void TIM3_Encoder_Init()  31 {  32  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  33  TIM_ICInitTypeDef TIM_ICInitStructure;  34  GPIO_InitTypeDef GPIO_InitStructure;  35  NVIC_InitTypeDef NVIC_InitStructure;  36     
 37     //時鍾使能
 38     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能 TIM3 時鍾
 39     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 時鍾  40     
 41     //GPIO配置
 42     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PA6、PA7設置
 43     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
 44     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  45     GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA  46     
 47     //定時器初始化
 48  TIM_DeInit(TIM3);  49     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  50     TIM_TimeBaseStructure.TIM_Period =65535;//預裝載值
 51     TIM_TimeBaseStructure.TIM_Prescaler = 0;//預分頻
 52     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;  53     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  54     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  55     
 56     //編碼器模式配置
 57  TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);  58     TIM_ICStructInit(&TIM_ICInitStructure);  59     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;
 60     TIM_ICInit(TIM3, &TIM_ICInitStructure);  61     
 62     //初始化 NVIC 中斷優先級分組
 63     NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中斷
 64     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級 2 級
 65     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先級 0 級
 66     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
 67     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC  68     
 69     //中斷配置
 70  TIM_ClearFlag(TIM3, TIM_FLAG_Update);  71  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);  72     
 73     //Reset counter
 74     TIM3->CNT = 0;  75     //使能定時器
 76  TIM_Cmd(TIM3, ENABLE);  77 }  78 
 79 void TIM4_Encoder_Init()  80 {  81  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  82  TIM_ICInitTypeDef TIM_ICInitStructure;  83  GPIO_InitTypeDef GPIO_InitStructure;  84  NVIC_InitTypeDef NVIC_InitStructure;  85     
 86     //時鍾使能
 87     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  //使能 TIM4 時鍾
 88     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能 GPIOB 時鍾  89     
 90     //GPIO配置
 91     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PB6、PB7設置
 92     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
 93     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  94     GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 GPIOA  95     
 96     //定時器初始化
 97  TIM_DeInit(TIM4);  98     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  99     TIM_TimeBaseStructure.TIM_Period =65535;//預裝載值
100     TIM_TimeBaseStructure.TIM_Prescaler = 0;//預分頻
101     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ; 102     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 103     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 104     
105     //編碼器模式配置
106  TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling); 107     TIM_ICStructInit(&TIM_ICInitStructure); 108     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;
109     TIM_ICInit(TIM4, &TIM_ICInitStructure); 110     
111     //初始化 NVIC 中斷優先級分組
112     NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4 中斷
113     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級 2 級
114     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //從優先級 0 級
115     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
116     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC 117     
118     //中斷配置
119  TIM_ClearFlag(TIM4, TIM_FLAG_Update); 120  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); 121     
122     //Reset counter
123     TIM4->CNT = 0; 124     //使能定時器
125  TIM_Cmd(TIM4, ENABLE); 126 }
encoder.c

 

3、注意事項

  • 更新中斷可以不開。但是由於沒有使用Z相信號,所以這里保留更新中斷,實際上目前中斷里什么也沒做
  • 由於是雙相下降沿計數,所以轉一次會輸出兩個脈沖,轉一周脈沖數為分辨率*2,注意處理。當然你也可以配置為其它計數倍數
  • 這里預裝載65535,可改為線數*2,即可對轉一周的位置進行嚴格編碼
  • TIMx->CNT的值即為編碼器的位置(並不一定是輸出脈沖值,跟旋轉方向和預裝載值有關,增量編碼器的零點是初始化自己定義的)
  • GPIO配置為浮空輸入模式。對於集電極開路輸出的編碼器,如果你沒有外部上拉,則使用內部上拉,配置為上拉輸入模式即可。

 

參考資料:

1、百度百科-旋轉編碼器

2、STM32定時器--正交編碼器模式詳解

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM