當前位置:首頁 > 公眾號精選 > 嵌入式微處理器
[導讀]若要對伺服系統(tǒng)中的電機進行高精度控制,需要準確的轉子角度位置,這時候自然會想到,如果能張江轉子每一圈進行細分,這樣每次轉多少角度便能精確知道。


▍編碼器的由來和原理
若要對伺服系統(tǒng)中的電機進行高精度控制,需要準確的轉子角度位置,這時候自然會想到,如果能張江轉子每一圈進行細分,這樣每次轉多少角度便能精確知道。在這樣的背景下,相對編碼器就誕生了。
在網上找到下文這個圖,很形象的表征了相對編碼器的原理。

如圖所示,在碼盤上平均開出很多個等間距的槽,一段是LED燈發(fā)出信號,另一端是接收器接收信號。如果信號能穿過碼盤,則接收信號為高電平,反之則為低電平。這樣當轉子轉起來以后,就不斷的處高低電平。這就是編碼器基本原理。
可以看到這里有三個信號,A/B/Z,這時候就要想為什么要3個信號呢?如果僅僅對一圈做細分,命名一個信號就可以了。這就涉及到下面兩個問題。
(1)如果是1個信號channel A,電機是正轉還是反轉就不知道了。需要一個相對的參考信號channel B,A和B相互呈一個角度,這樣通過A和B的相對位置就能知道電機是順時鐘轉還是逆時針轉了。
(2)如果是2個信號,其中一旦有碼盤有損壞,就可能出現檢測結果無法校驗的情況。舉個例子,如果一圈開了16個槽,則每旋轉一圈,正常情況下就有16個高低電平的信號出來。但如果一個槽壞了,實際上每轉一圈只有15個信號出來,但這時如果僅僅通過channel A和channel B是無法判斷的。在進行數據處理時還是認為16個信號為一圈,處理結果就有較大的偏差。為了避免這樣的問題,補充z信號,一圈只出一個,這樣就能相互交驗了。一方面通過對A或者B計數,知道z是否有問題,反之對z信號計數就能知道A/B是否有問題。
所以就有了上圖的z/A/B三個信號,共同組成了一個功能齊全的編碼器。
在網上經??吹秸fA/B之間相互差90°,這個90°是認為360°為一個周期而言的。如下圖所示。通過看A/B相對位置就知道電機是正轉還是反轉了。

實測波形,如下圖所示(示波器不太好,有點毛刺)

正轉

反轉
使用STM32,讓編碼器說話
背景
STM32中提供了編碼器接口,比較適用于相對編碼器的應用場景。在手冊中可以看到:

可以看到這里使用專用的模塊就能完成相應的計數,通過數據的變化就能測出電機的轉速。
所以,我想讓編碼器說話。在家翻箱倒柜以后,我準備了如下幾個東西:
(1) 帶編碼器的直流電機:這是作為編碼器的載體使用,電機編碼器的分辨率較低,每圈只有16個脈沖。但不影響測試。
(2) 直流電源:用來直觀的調電機的轉速和正反轉。
為了避免打廣告的嫌疑,就不貼電源和電機圖片了。
(3) STM32開發(fā)板:在家翻箱倒柜,找出2015年在21ic獲得的STM32072 discovery板

(4) LED數碼管。用來通過編碼器的數據處理,顯示電機的轉速。
試驗第一步,讓LED數碼管顯示起來。
因為顯示數據是最終目的。使用的這個板子,是集成了HC595鎖存器的板子。相比于網上買的大部分51開發(fā)板數碼管電機設計,使用兩個HC595,可以大大減少pin腳的數量。網上使用的4位數碼管,需要8個pin作為段選或者位選,非常麻煩。
根據HC595的手冊,具有鎖存加移位的特性(圖中我標注所示)

最上面的3個SH-CP/DS/ST-CP,像極了SPI通信波形,只要合理配置,只需要3個信號線即可完成4數碼管的輪流顯示。
于是在開發(fā)板的pin做了如下硬件配置
Pin(數碼管) 74HC595 SPI Pin
SCLK Pin11(shift) SPICLK PB13
RCLK Pin12(Storage) NSS PB12
DIO Pin14(datainput) SPIMOSI PC3
QH Pin9(dataoutput) SPIMISO PC2

SPI配置代碼如下(配置了SPI幾個pin腳的定義,時鐘,SPI模式等):
void SPI_Digital_Tube_Config(void){ SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;  /* Disable the SPI peripheral */ SPI_Cmd(SPI2, DISABLE); /* Enable SCK, MOSI, MISO and NSS GPIO clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHBPeriphClockCmd(SPI_Digital_Tube_SCK_GPIO_CLK | SPI_Digital_Tube_MOSI_GPIO_CLK| SPI_Digital_Tube_NSS_GPIO_CLK, ENABLE);  /* SPI pin mappings */ GPIO_PinAFConfig(SPI_Digital_Tube_SCK_GPIO_PORT, SPI_Digital_Tube_SCK_SOURCE, SPI_Digital_Tube_SCK_AF); GPIO_PinAFConfig(SPI_Digital_Tube_MOSI_GPIO_PORT, SPI_Digital_Tube_MOSI_SOURCE, SPI_Digital_Tube_MOSI_AF); GPIO_PinAFConfig(SPI_Digital_Tube_MISO_GPIO_PORT, SPI_Digital_Tube_MISO_SOURCE, SPI_Digital_Tube_MISO_AF); GPIO_PinAFConfig(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_SOURCE, SPI_Digital_Tube_NSS_AF);  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;  /* SPI SCK pin configuration */ GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_SCK_PIN; GPIO_Init(SPI_Digital_Tube_SCK_GPIO_PORT, &GPIO_InitStructure);  /* SPI MOSI pin configuration */ GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_MOSI_PIN; GPIO_Init(SPI_Digital_Tube_MOSI_GPIO_PORT, &GPIO_InitStructure);  /* SPI MISO pin configuration */ GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_MISO_PIN; GPIO_Init(SPI_Digital_Tube_MISO_GPIO_PORT, &GPIO_InitStructure);  /* SPI NSS pin configuration */ GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_NSS_PIN; GPIO_Init(SPI_Digital_Tube_NSS_GPIO_PORT, &GPIO_InitStructure);  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Pin = SPI_Digital_Tube_NSS_PIN; GPIO_Init(SPI_Digital_Tube_NSS_GPIO_PORT, &GPIO_InitStructure);  /* SPI configuration -------------------------------------------------------*/ SPI_I2S_DeInit(SPI2); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;// SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_Init(SPI2, &SPI_InitStructure);  /* Initialize the FIFO threshold */ SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);  /* Enable the SPI peripheral */ SPI_Cmd(SPI2, ENABLE); // /* Enable NSS output for master mode */// SPI_SSOutputCmd(SPI2, ENABLE);} 

使用TIM6作為定時器,配置代碼如下(1ms定時周期):
static void BASIC_TIM_Mode_Config(void){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE); TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;//1ms  TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;//47 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter=0;  TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);  TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);  TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);  TIM_Cmd(BASIC_TIM, ENABLE); }

實際上每次只會有一個數碼管亮,為了較好的視覺體驗,將數碼管進行千位百位十位個位循環(huán)顯示,這樣做的好處是4個數碼管輪流顯示,其亮度相同,避免出現一個數碼管過亮的情形,影響視覺體驗。數碼管代碼如下:
void DisplayNumber(uint16_t num){ uint8_t mythousandNum,myhundredNum,mytenNum,myunitNum=0; if(num>9999)num=9999; mythousandNum=num/1000%10; myhundredNum=num/100%10; mytenNum=num/10%10; myunitNum=num%10; switch(mydisplaybit) { case thousaud: Display16(mythousandNum,4); mydisplaybit=hundred; break; case hundred: Display16(myhundredNum,3); mydisplaybit=ten; break; case ten: Display16(mytenNum,2); mydisplaybit=unit; break; case unit: Display16(myunitNum,1); mydisplaybit=thousaud; break; default: Display16(mythousandNum,4); mydisplaybit=hundred; break; }} static void Display16(uint8_t num,uint8_t place){ GPIO_ResetBits(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_PIN); uint16_t Temp=((Num[num])<<8)+((0x01)<<(place-1)); SPI2_Send_Byte16(Temp); GPIO_SetBits(SPI_Digital_Tube_NSS_GPIO_PORT, SPI_Digital_Tube_NSS_PIN);}

然后,每隔0.5s累加一次。在定時器中累計
void TIM6_DAC_IRQHandler(){ static uint16_t counter=0; static uint16_t num_buffer=0; if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) {  counter++; if(counter>499) { num_buffer++; counter=0; } DisplayNumber(num_buffer); TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);  } }
顯示的效果如下:  


所以,初試成功。
試驗第二步,讓編碼器說話。
首先,在STM32中配置編碼器。
使用PA6和PA7作為定時器3的通道1和通道2,進行下圖模式的計數。

即效果如下:

代碼如下
void TIM3_EncoderConfig(void){ TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;  HALL_TIM_APBxClock_FUN(ENCODER_TIM_CLK, ENABLE);  /* GPIOA clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //PA6 & PA7 RCC_AHBPeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  /* phase A & B*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);//TIM3_CH1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);//TIM3_CH2  TIM_DeInit(TIM3); TIM_TimeBaseStructure.TIM_Period =0xffff; TIM_TimeBaseStructure.TIM_Prescaler =0; TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);  TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);  TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM3, &TIM_ICInitStructure);  // Clear all pending interrupts TIM_ClearFlag(TIM3, TIM_FLAG_Update); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //Reset counter TIM_SetCounter(TIM3,0); TIM_Cmd(TIM3, ENABLE);  /* Enable the TIM1 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}
然后在中斷服務函數中,將編碼器的相對值計算出來,并根據編碼器計數的相對變化,計算出電機的轉速。具體代碼如下: 
void TIM6_DAC_IRQHandler(){ static uint16_t counter=0; static uint16_t num_buffer=0; static uint16_t temp_now=0; static uint16_t temp_pre=0; static uint16_t speed=0; if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) {  counter++; temp_now=(TIM_GetCounter(TIM3)&0xffff); if(counter>499) { num_buffer=(temp_now-temp_pre)>0?temp_now-temp_pre:temp_pre-temp_now; speed=100*num_buffer*60/64; counter=0; } DisplayNumber(speed); if(counter%10==0)temp_pre=temp_now;  TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);  } } 同時,為了防止TIM3中斷溢出,記得清除中斷標志位 
void TIM3_IRQHandler (){  if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); }}
 實際效果如下圖所示(東西太多,手機不好拍動圖,只能靜物顯示),可知,當電機電壓9.32V時,轉速為843rpm。當電壓為18.7V時,轉速為1687rpm。編碼器的波形也用示波器顯示出來了。還不錯哈,哈哈哈。 

結論
本文使用STM32F0 discovery開發(fā)板,完成了編碼器計數和電機轉速的計算,并通過數碼管將電機轉速實時顯示出來。
END

本文系21ic藍V作者grhr編纂

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關注更多精彩內容

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉