Re: [問題] 請教關於『旋轉編碼器』的數值讀取問題

看板Electronics作者 (卡比)時間12年前 (2013/05/30 14:11), 編輯推噓2(206)
留言8則, 3人參與, 最新討論串2/2 (看更多)
小弟我先前在此提出問題後, 得到許多前輩的協助,在此先拜謝! 因為這問題後來解決了,所以我想就來此回報,並且把我的學習心得和解法, 來分享一下!若有相關需求的朋友也能少走點冤枉路... 我當時問題是:旋轉編碼器,輸出的脈衝數量『太多』, 但無法更換元件(不管是編碼器或處理器),也不能動原有程式。 本來我想要『除頻』--把原本的脈衝數量按照比例減少, 結果,速度確實降低,但『旋轉方向』卻錯亂。 旋轉編碼器的原理是--輸出A,B兩條線,旋轉時,會有固定的脈波出現, 根據方向不同,會有不同的相位差。(如下) 正轉時(A線脈波比B線提前半個相位): A ___---___---___---___ B _____---___---___---___ 反轉時(B線比A線提前): A _____---___---___---___ B ___---___---___---___ 我的想法是--脈衝太多,那就兩條線同時除頻,拿TTL IC去做, 不就會同時減少脈波數量? 有問題的原因到底何在呢? 我思考了好久,直到那天看到一群小朋友在玩遊戲,突然之間恍然大悟 『一二三~~~木頭人!!』 對啦,我這樣的電路設計,就是在跟脈波玩木頭人! 我讓MCU當鬼,而編碼器則是扮演木頭人! 然後,我試圖用除頻器遮住鬼的眼睛.....只讓他隔一段時間回頭看一眼... 但我忽略了...木頭人在鬼看不到的時候不管做了什麼動作,都會被忽視! MCU只能得知最後脈波的『總數量』變化,但其中到底誰先誰後,之間超前落後關係, 它一概不知道......所以,方向就無法正確的得知 (也許先往左半圈,再往右一圈,而MCU最後只知道往右移動了半圈...) 在找資料以及板友協助之下,我重新思考解決方式--- 首先要分析這兩線訊號的行為模式,其實很簡單,就是-- 『當A訊號邊緣觸發時,判斷B訊號是0或1,就可判定方向』 既然有這麼簡單的邏輯,那我就選擇外加一個單晶片,負責處理。 選用的還是這顆『單晶片之中的皮卡丘』..89C51 (就是...二十年不進化,經驗值暴表,什麼招式都生得出來) 簡單說,就是用A線輸入INT0外部中斷,判斷邊緣觸發, 進入ISR再去判斷B線電位高低。 當進入中斷達到一定次數時,輸出產生一個轉動的相位訊號,給原本的MCU輸入,就完成此功能了。 而要降低的比例,只要決定『進入中斷多少次產生一個輸出』就可以了。 以下為我的程式碼和註解,給需要的朋友參考啦...... 版權沒有,歡迎使用。 再次感謝各位協助我的朋友們! 輸入為P3.1和P3.2(接編碼器A/B線),輸出為P2.0和P2.1(接原本MCU的輸入) -- COUNT EQU 30 ;輸入脈波多少次才輸出一次 ;正轉次數計數為為R3,反轉次數為R4 org 0h JMP LOP ;跳到主程式 ORG 03H ;中斷位址 JMP INT0_HANDLING ;跳到中斷ISR LOP: ;主程式 clr P2.0 ;輸出接點設定 clr P2.1 SETB EA ;打開中斷總開關 SETB EX0 ;致能 INT0 (Pin12,3.2) SETB IT0 ; 負緣觸發 setb P3.2 ;輸入中斷接腳設定 (A接點) setb P3.1 ;輸入非中斷接腳設定 (B接點) ajmp LOP INT0_HANDLING: ;中斷ISR CLR EA ;關掉中斷 JB P3.1,FR ; 如果B接點高電位,判斷為正轉 ;以下為反轉時動作 mov R3,#COUNT ;偵測到反轉,把正轉count重置 DJNZ R4,BACK ;如果還沒觸發足夠次數,不動作 mov R4,#COUNT ;觸發次數到達,重置count setb P2.1 ; 先拉高P2.1 ACALL DLY1 ;等待 setb P2.0 ; 再拉高P2.0 ACALL DLY1 ;等待 CLR P2.1 ;先降低P2.1 ACALL DLY1 ;等待 CLR P2.0;再降低P2.0 RETI FR: ;正轉時的動作 mov R4,#COUNT ;偵測到正轉,把反轉count重置 DJNZ R3,BACK ;如果還沒觸發足夠次數,不動作 mov R3,#COUNT ;觸發次數到達,重置count setb P2.0 ; 先拉高P2.0 ACALL DLY1 ;等待 setb P2.1 ; 再拉高P2.1 ACALL DLY1 ;等待 CLR P2.0 ;先降低P2.0 ACALL DLY1 ;等待 CLR P2.1;再降低P2.1 BACK: RETI ;折返回呼叫中斷副程式的地方 DLY1: ;延時40m秒副程式 MOV R6,#100 DL1: MOV R7,#200 DJNZ R7,$ DJNZ R6,DL1 RET end -- / ︵ 笑年A,我教你 ﹨﹨ 奶子不是用來看的,是拿來摸的 ∕  ノ╮ ╱∕∕ \ \ \    ︵  ∕ ∕ \/ / / / /\ (( ) (-w- ) / ∕﹨ /﹨﹨﹨ \ \ノ\/ / ∕ ︶ ̄ /﹀(掰)> ﹨ ﹨ ﹀ ∕ ﹨ `﹀ ∕ / \ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 210.202.48.60

05/30 15:33, , 1F
恭喜你解決問題了
05/30 15:33, 1F

05/30 15:35, , 2F
我記得89C51只有負緣觸發,這樣做的話不是等分的
05/30 15:35, 2F

05/30 15:36, , 3F
沒事 當我沒說啥。 你是用一倍解析吧?
05/30 15:36, 3F

05/30 15:48, , 4F
其實這樣還是有點小bug存在.....但我沒有很要求精確性
05/30 15:48, 4F

05/30 15:48, , 5F
實際上應該要做到正反轉分別用不同暫存器去計數才對
05/30 15:48, 5F

05/30 15:58, , 6F
旋轉編碼器的解碼方式很多種,主要看CPU的處理效率。
05/30 15:58, 6F

05/30 15:59, , 7F
像DSP一樣有解碼硬體電路的就另外一回事了
05/30 15:59, 7F
謝謝前輩的指導! 我稍微修改了一下code,已經把正反轉的計算暫存器分開, 這樣才能確實做到『連續輸入相同方向』才有動作 ※ 編輯: lcabc 來自: 210.202.48.60 (05/30 16:09)

11/28 11:20, , 8F
感謝分享T_T 我也困擾好久
11/28 11:20, 8F
文章代碼(AID): #1HfksieJ (Electronics)
文章代碼(AID): #1HfksieJ (Electronics)