旋轉編碼器與PIC微控制器介面
轉載於www.viadean.com
旋轉編碼器 是一種輸入裝置,其幫助使用者與系統進行互動。它看起來更像是一個無線電電位器旋轉編碼器是一種輸入裝置, 可幫助使用者與系統互動。它看起來更像是一個無線電電位器, 但它輸出一系列脈衝, 這使得它的應用獨特。當編碼器的旋鈕旋轉時, 它以小步的形式旋轉, 這有助於它用於 stepper/servo 電機控制。
在本文中,我們將瞭解不同型別的旋轉編碼器及其工作原理。我們還將它與PIC微控制器PIC16F877A連線,並通過旋轉編碼器控制整數值,並在16 * 2 LCD螢幕上顯示其值。在本教程的最後, 您將會很樂意為您的專案使用旋轉編碼器。所以讓我們開始吧…。
旋轉編碼器及其型別
旋轉編碼器通常稱為軸編碼器。它是一個機電感測器, 這意味著它將機械運動轉換為電子脈衝, 或者換句話說, 它將角度位置或運動或軸位置轉換為數字或模擬訊號。它由一個旋鈕組成, 當旋轉時, 它將逐步移動, 併產生每個步驟具有預定寬度的脈衝列車序列。
市場上有很多種型別的旋轉編碼器, 設計師可以根據自己的應用選擇一種。下面列出了最常見的型別
增量編碼器
絕對編碼器
磁性編碼器
光學編碼器
鐳射編碼器
這些編碼器是基於輸出訊號和感測技術進行分類的, 增量編碼器和絕對編碼器是根據輸出訊號進行分類的, 磁編碼器和鐳射編碼器是基於感測技術進行分類的。此處使用的編碼器是增量型別的編碼器。
絕對編碼器即使在斷電後也會儲存位置資訊, 當我們再次對其通電時, 位置資訊也會可用。
另一種基本型別, 增量編碼器提供資料時, 編碼器更改它的位置。它無法儲存倉位資訊。
ky-040 旋轉編碼器夾頭及說明
ky-040 增量型旋轉編碼器的針腳如下所示。在這個專案中, 我們將與來自微晶片的流行微控制器 pic16f877a 介面這個旋轉編碼器。
前兩個引腳 (接地和 vcc) 用於為編碼器供電, 通常使用 + 5v 電源。除了以順時針和逆時針方向旋轉旋鈕外, 編碼器還具有一個開關 (活動低), 可通過按內旋鈕進行按壓。此開關的訊號是通過引腳 3 (sw) 獲得的。最後, 它有兩個輸出引腳 (dt 和 clk), 產生波形, 如下所述。我們以前把這個旋轉編碼器與 arduino 介面過。
旋轉編碼器的工作原理
輸出完全取決於內部銅墊, 提供與 gnd 和 vcc 與軸的連線。
旋轉編碼器有兩個部分。軸輪, 它與軸連線, 並根據軸的旋轉和完成電氣連線的底座順時針或逆時針旋轉。基座具有連線到 dt 或 clk 的埠或點, 這樣當軸輪旋轉時, 它將連線基點, 並在 dt 和 clk 埠上提供方波。
輸出將像軸旋轉時
兩個埠提供方波,但時序略有不同。因此,如果我們接受輸出為1和0,則只能有四個狀態,0 0,1 0,1 1,0 1.二進位制輸出的序列決定順時針轉動或逆時針轉動。例如,如果旋轉編碼器在空閒狀態下提供1 0並在此之後提供1 1,則意味著編碼器將其位置向順時針方向改變一步,但如果在空閒1 0之後提供0 0,則意味著軸一步一步地沿逆時針方向轉動其位置。
所需元件
現在是確定我們需要什麼介面旋轉編碼器與 pic 微控制器的時候了,
PIC16F877A
電阻器
1k電阻器
10k
4.7k電容器33pF陶瓷圓盤電容器 - 2個
20Mhz晶體
16x2顯示
旋轉編碼器
5V介面卡。
麵包板
連線線。
PIC16F877A旋轉編碼器介面電路圖
下面是根據電路圖連線元件後的最終設定圖:
我們使用單個1K電阻來代替LCD的對比度,而不是使用電位計。
程式碼說明
完整的PIC程式碼 在本專案的最後給出了 演示視訊,這裡我們將解釋程式碼的一些重要部分。如果您是PIC微控制器的就遵循我們的 新手,請PIC教程 從一開始。
正如我們之前討論的那樣,我們需要 檢查輸出並區分DT和CLK的二進位制輸出,因此我們建立了一個 if-else為操作部分。
if (Encoder_CLK != position){
if (Encoder_DT != position){
// lcd_com (0x01);
counter++; // Increase the counter which will be printed on the lcd
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
}
else{
// lcd_com (0x01);
lcd_com (0xC0);
counter--; // decrease the counter
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
//lcd_puts("Left");
}
}
我們還需要在每一步上儲存位置。為此, 我們使用了一個儲存當前位置的變數 “position”。
position = Encoder_CLK; // It is to store the encoder clock position on the variable. Can be 0 or 1
除此之外,還提供了一個選項,用於 通知開關按壓LCD上的。
if (Encoder_SW == 0)
{
sw_delayms(20); //debounce delay
if (Encoder_SW == 0)
{ //lcd_com(1);
//lcd_com(0xC0);
lcd_puts ("switch pressed");
// itoa(counter, value, 10);
// lcd_puts(value);
}
}
系統 _ init 函式用於初始化引腳 ito 操作、lcd 和儲存旋轉編碼器位置。
void system_init()
{
TRISB = 0x00; // PORT B as output, This port is used for LCD
TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;
TRISCbits.TRISC4 = 1;
lcd_init(); // This will Initialize the LCD
position = Encoder_CLK;// Sotred the CLK position on system init, before the while loop start.
}
lcd 功能寫在 lcd. h 庫上, 其中聲明瞭 lcd _ put ()、lcd _ cmd ()。
完整程式碼:
/*
* File: main.c
* Author: Sourav Gupta
*
* Created on 18 Dec 2018, 18:57
*/
/*
* Configuration Related settings. Specific for microcontroller unit.
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 20000000
/*
* System Header files inclusions
*/
#include <xc.h>
//#include <string.h>
#include <stdlib.h>
#include "supporting c files/lcd.h"
#define Encoder_SW PORTDbits.RD2
#define Encoder_DT PORTDbits.RD3
#define Encoder_CLK PORTCbits.RC4
/*
* Program flow related functions
*/
int counter; // It will hold the count of rotary encoder.
int position; // It will store the rotary encoder position.
void sw_delayms(unsigned int d);
int value[7];
/*
* System Init Function
*/
void system_init ();
/* Main function single Thread*/
void main(void) {
system_init();
lcd_puts ("Circuit Digest");
lcd_com(0xC0);
counter = 0;
while(1){
lcd_com(0xC0);
if (Encoder_SW == 0){
sw_delayms(20);
if (Encoder_SW == 0){
//lcd_com(1);
//lcd_com(0xC0);
lcd_puts ("switch pressed");
// itoa(counter, value, 10);
// lcd_puts(value);
}
}
if (Encoder_CLK != position){
if (Encoder_DT != position){
// lcd_com (0x01);
counter++;
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
}
else{
// lcd_com (0x01);
lcd_com (0xC0);
counter--;
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
//lcd_puts("Left");
}
}
position = Encoder_CLK;
}
return;
}
void sw_delayms(unsigned int d){
int x, y;
for(x=0;x<d;x++)
for(y=0;y<=1275;y++);
}
void system_init(){
TRISB = 0x00; // PORT B as output, This port is used for LCD
TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;
TRISCbits.TRISC4 = 1;
lcd_init(); // This will Initialize the LCD
position = Encoder_CLK;// Sotred the CLK position on system init, before the while loop start.
}