Инкрементальный энкодер (Rotary encoder) во многом похож на обычный потенциометр, но его выход – это последовательность импульсов, что значительно отличает работу с ним по сравнению с другими известными устройствами ввода. При вращении оси инкрементального энкодера она вращается небольшими шагами, что делает его удобным для управления серво- и шаговыми двигателями, навигации по какому либо меню, увеличения/уменьшения каких либо значений и многое другое.
В этой статье мы рассмотрим различные типы инкрементальных энкодеров и принципы их работы. Также мы рассмотрим подключение инкрементального энкодера к микроконтроллеру PIC16F877A, с его помощью мы будем управлять значением переменной целого типа и отображать ее значение на экране ЖК дисплея 16х2.
Также на нашем сайте мы рассматривали подключение инкрементального энкодера к другим микроконтроллерам (платам):
Типы инкрементальных энкодеров
Инкрементальный энкодер также иногда называют круговым датчиком положения (shaft encoder). Он представляет собой электромеханический преобразователь, преобразующий механические движения в последовательность импульсов. Другими словами, он преобразует положение своей оси в цифровой или аналоговый сигнал. Он включат ось, которая вращается шаг за шагом и формирует последовательность импульсов с заданной шириной для каждого шага.
К наиболее популярным типам энкодеров относятся следующие:
- инкрементальный энкодер;
- абсолютный энкодер;
- магнитный энкодер;
- оптический энкодер;
- лазерный энкодер.
Эти энкодеры классифицируются по типу выходного сигнала и сенсорной техники. Инкрементальные и абсолютные энкодеры классифицируются на основе выходного сигнала. Магнитные, оптические и лазерные энкодеры классифицируются на основе сенсорной техники. В нашем проекте мы будем использовать инкрементальный энкодер.
Абсолютные энкодеры способны сохранять информацию о положении своей оси даже после выключения питания. Все другие типы энкодеров способны хранить информацию о местоположении своей оси только при включенном питании.
Инкрементальный энкодер KY-040
Назначение контактов (распиновка) инкрементального энкодера KY-040 показаны на рисунке ниже. В нашем проекте мы его будем подключать к популярному микроконтроллеру PIC16F877A.
Первые два контакта (Ground и Vcc) используются для подачи питания на энкодер, обычно +5V. Кроме способности вращения своей оси по часовой и против часовой стрелки энкодер также содержит переключатель (в активном состоянии low), который переключается при нажатии оси энкодера внутрь. Сигнал от этого переключателя доступен на контакте 3 (SW) энкодера. На двух выходных контактах DT и CLK формируются последовательности импульсов, по которым можно определить направление вращения энкодера.
Принцип работы инкрементального энкодера
Выходные сигналы энкодера полностью зависят от его внутренних медных пластин, которые обеспечивают соединение оси энкодера с контактами GND и VCC.
Инкрементальный энкодер состоит из двух основных частей. Первой из них является шестерня (Shaft Wheel), которая соединена с осью и вращается по часовой или против часовой стрелки в зависимости от вращения оси. Второй частью энкодера является база (основание) со всеми электрическими соединениями энкодера. База имеет точки (порты), которые соединены с контактами DT и CLK энкодера таким образом, что когда шестерня вращается, она подключается к точкам базы и формирует прямоугольную волну на контактах DT и CLK. Внешний вид данных прямоугольных волн показан на следующем рисунке.
Как видите, эти прямоугольные волны полностью идентичны, только сдвинуты относительно друг друга на ¼ периода. Поэтому на выходах энкодера возможны 4 состояния: 0 0, 1 0, 1 1, 0 1. Последовательность состояний выходов энкодера позволяет однозначно определить в какую сторону вращается его ось. К примеру, если в состоянии покоя на выходах энкодера были состояния 1 0, которые после начала вращения его оси сменились на 1 1, это будет означать что ось энкодера сделала один шаг в направлении по часовой стрелке. А если после состояния покоя значения 1 0 сменились на 0 0, это будет означать что ось энкодера сделала один шаг в направлении против часовой стрелки.
Необходимые компоненты
- Микроконтроллер PIC16F877A (купить на AliExpress).
- Инкрементальный энкодер (купить на AliExpress).
- Программатор PICkit 3 (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Кварцевый генератор 20 МГц (купить на AliExpress).
- Конденсаторы 33 пФ (2шт.) (купить на AliExpress).
- Резисторы 1 кОм, 4,7 кОм (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Адаптер питания на 5V.
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Схема проекта
Схема подключения инкрементального энкодера к микроконтроллеру PIC16F877A представлена на следующем рисунке.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Внешний вид соединений проекта на макетной плате показан на следующем рисунке. В окончательной версии проекта мы вместо потенциометра для регулировки контрастности ЖК дисплея использовали резистор 1 кОм.
Объяснение программы для микроконтроллера PIC
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Как уже отмечалось ранее, для определения направления вращения энкодера необходимо анализировать динамику изменений состояний его выходов DT и CLK. Фрагмент кода для выполнения этой задачи будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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”.
1 |
position = Encoder_CLK; // It is to store the encoder clock position on the variable. Can be 0 or 1. |
Дополнительно при нажатии переключателя энкодера мы будем выдавать об этом соответствующее сообщение на экран ЖК дисплея.
1 2 3 4 5 6 7 8 |
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); |
Функция system_init будет использоваться для инициализации используемых контактов, ЖК дисплея и первоначальной позиции оси энкодера.
1 2 3 4 5 6 7 8 |
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.c и lcd.h.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
/* * 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. } |
Весьма плохой перевод статьи зарубежного автора. Масса неточностей, недомолвок, ошибок...
Может подскажите где вы обнаружили ошибки и опечатки? Большинству посетителей сайта нравятся мои переводы и в комментариях на сайте мне уже много раз высказывали благодарность за проделанный мной труд
Здравствуйте! Можно получить исходный код в HEX формате
Добрый день. К сожалению у меня нет кода этой программы в HEX формате