Устройства ввода играют важную роль в различных электронных проектах, они помогают осуществлять взаимодействие с внешним миром. Устройства ввода могут быть различной сложности – начиная от обычной кнопки и заканчивая сенсорным экраном. В данной статье мы рассмотрим подключение джойстика к микроконтроллеру PIC. Для многих джойстик ассоциируется с устройством управления в компьютерных играх, но помимо этого он может выполнять и множество других полезных функций.
На первый взгляд может показаться что джойстик – это достаточно сложное устройство, но на самом деле он представляет собой простую комбинацию двух потенциометров и кнопки. Для его подключения необходимо использовать входы АЦП (аналого-цифрового преобразователя), которые сейчас есть практически в любом современном микроконтроллере. Ранее на нашем сайте мы уже рассматривали использование АЦП в микроконтроллере PIC – если вы знакомились с этой статьей, то для вас понимание представленного проекта подключения джойстика к микроконтроллеру PIC не вызовет никаких сложностей.
Также на нашем сайте мы рассматривали подключение джойстика к другим микроконтроллерам (платам):
Необходимые компоненты
- Микроконтроллер PIC16F877A (купить на AliExpress).
- Модуль джойстика (купить на AliExpress).
- Держатель микросхем на 40 контактов (купить на AliExpress).
- Программатор PICkit 3 (купить на AliExpress).
- Кварцевый генератор 20 МГц (купить на AliExpress).
- Конденсаторы 22 пФ (2 шт.), 0,1 мкФ и 10 мкФ (купить на AliExpress).
- Резистор 220 Ом (купить на AliExpress).
- Регулятор напряжения 7805 (купить на AliExpress).
- Светодиод – 5 шт. (купить на AliExpress).
- Адаптер 12V.
- Макетная и перфорированная платы.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Принципы работы джойстика
Джойстики изготавливаются различных форм и размеров. Внешний вид типового модуля джойстика показан на рисунке ниже. Фактически, джойстик представляет собой два потенциометра и кнопку, смонтированных на единую механическую платформу. Потенциометры используются для отслеживания перемещений рукоятки джойстика по осям X и Y. Потенциометры представляют собой аналоговые устройства, поэтому для считывания с них значений с помощью потенциометра необходимо использование АЦП.
Используемый нами модуль джойстика имеет 5 контактов, два из которых используются для подачи на него питания, а по остальным трем передаются данные. Джойстик запитывается от напряжения +5V. Контакты данных имеют обозначения VRX, VRY и SW.
Контакт “VRX” расшифровывается как "Variable voltage on X-axis" (переменное напряжение на оси X), а контакт “VRY” – как Variable voltage on Y-axis (переменное напряжение на оси Y). Контакт “SW” означает переключатель (switch).
Таким образом, когда мы будем перемещать джойстик вправо или влево, напряжение на контакте VRX будет изменяться. При перемещении джойстика вверх или вниз напряжение будет изменяться на контакте VRY, а при перемещении джойстика по диагонали напряжение будет изменяться одновременно на контактах VRX и VRY. При нажатии кнопки на джойстике контакт SW будет замыкаться на землю (ground). Представленная ниже картинка более наглядно показывает изменения на контактах джойстика при перемещениях его ручки.
Схема проекта
Схема подключения джойстика к микроконтроллеру PIC представлена на следующем рисунке. Как мы уже знаем, для подключения джойстика нам потребуется три контакта микроконтроллера PIC – один цифровой и два аналоговых.
На представленной схеме вы можете видеть что джойстик мы изобразили с помощью двух потенциометров RV1 и RV3. Используемые контакты джойстика на представленной схеме выделены фиолетовым цветом. Аналоговые контакты джойстика подключены к контактам A0 и A1 микроконтроллера PIC, а его цифровой контакт – к контакту RB0 микроконтроллера. Также к микроконтроллеру PIC у нас подключены 5 светодиодов – с помощью них мы будем показывать направление, в котором движется ручка джойстика. Светодиоды подключены к контактам порта PORTC (с RC0 по RC4).
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Объяснение программы для микроконтроллера PIC
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
В программе нам будет необходимо считывать уровень напряжения на аналоговых контактах джойстика и в соответствии с ним управлять включением/выключением светодиодов.
Первым делом в программе мы должны произвести настройку конфигурационных бит, затем – настройку модуля АЦП микроконтроллера PIC. После этого – инициализировать используемые контакты и указать их режим работы (на ввод или вывод данных). Светодиоды у нас подключены к PORTC, поэтому его контакты мы настраиваем в режим вывода данных.
1 2 3 4 5 |
//*****I/O Configuration****// TRISC=0X00; //PORT C is used as output ports PORTC=0X00; //MAke all pins low TRISB0=1; //RB0 is used as input //***End of I/O configuration**/// |
Для контактов АЦП нам не нужно отдельно настраивать режим работы на ввод данных поскольку при задействовании функций АЦП этот режим будет установлен для них автоматически. Для настройки модуля АЦП микроконтроллера мы запрограммируем функцию ADC_Initialize() и затем просто вызовем ее в программе.
1 |
ADC_Initialize(); //Configure the ADC module |
Затем внутри бесконечного цикла мы будем считывать значения контактов джойстика VRX, VRY и SW и в зависимости от их значений предпринимать необходимые действия. Считывание аналоговых значений с контактов VRX и VRY мы будем производить с помощью следующих строчек кода:
1 2 |
int joy_X = (ADC_Read(0)); //Read the X-Axis of joystick int joy_Y = (ADC_Read(1)); //Read the Y-Axis of Joystick |
С помощью этих команд мы будем считывать значения с контактов VRX и VRY и сохранять их в переменных joy_X и joy_Y соответственно. Функция ADC_Read(0) позволяет произвести считывание значения АЦП с канала 0 (контакт A0), а функция ADC_Read(1) – с канала 1 (контакт A1).
Как мы уже знаем, значения на выходе АЦП микроконтроллера PIC могут изменяться в диапазоне от 0 до 1023. В нашем случае эти значения будут зависеть от положения оси джойстика.
В нашем проекте мы использовали значение 200 в качестве нижней границы для осей джойстика, а 800 – в качестве верхней границы. Вы можете изменить эти границы по своему усмотрению. В программе мы с помощью условных операторов IF будем сравнивать считанное значение с выхода АЦП с этими границами и в зависимости от результатов сравнения давать команду на включение соответствующего светодиода.
1 2 3 4 5 6 |
if (joy_X < 200) //Joy moved up {RC0=0; RC1=1;} //Glow upper LED else if (joy_X > 800) //Joy moved down {RC0=1; RC1=0;} //Glow Lower LED else //If not moved {RC0=0; RC1=0;} //Turn off both led |
Аналогичным образом поступаем и для оси Y джойстика.
1 2 3 4 5 6 |
if (joy_Y < 200) //Joy moved Left {RC2=0; RC3=1;} //Glow left LED else if (joy_Y > 800) //Joy moved Right {RC2=1; RC3=0;} //Glow Right LED else //If not moved {RC2=0; RC3=0;} //Turn off both LED |
Также в программе нам необходимо проверять нажата ли кнопка на джойстике. У нас в проекте она подключена к контакту RB0. Если она нажата, то мы будем включать центральный светодиод в нашем проекте.
1 2 3 4 |
if (RB0==1) //If Joy is pressed RC4=1; //Glow middle LED else RC4=0; //OFF middle LED |
Моделирование работы проекта
Смоделировать работу проекта можно в симуляторе Proteus, нарисовав в нем схему проекта и загрузив в него программу проекта в шестнадцатеричном коде (hex code). Смоделированная в симуляторе Proteus схема проекта приведена на следующем рисунке.
Тестирование работы проекта
Схему проекта можно собрать на макетной или перфорированной плате. Мы использовали часть схемы с установленным на перфорированную плату микроконтроллером PIC из нашего предыдущего проекта мигания светодиодом, а остальную часть схемы собрали на макетной плате. В результате у нас получилась следующая конструкция проекта:
После сборки схемы проекта необходимо загрузить программу в микроконтроллер с помощью программатора PICkit3. После этого вы можете приступить к тестированию работы проекта. Наклоняйте ручку джойстика в разные стороны – вы должны увидеть как в схеме загораются соответствующие светодиоды.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы
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 |
/* * File: PIC_Joystick.c * Author: Aswinth * This program can read the values from a joy stick and control the LED based on the values * Created on 3 May, 2018, 4:05 PM for www.circuitdigest.com */ // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #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 is digital I/O, HV on MCLR must be used for programming) #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) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #define _XTAL_FREQ 20000000 void ADC_Initialize() { ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected (включаем АЦП и выбираем частоту Fosc/16) ADCON1 = 0b11000000; // выбираем внутреннее опорное напряжение для работы АЦП } unsigned int ADC_Read(unsigned char channel) { ADCON0 &= 0x11000101; //очищаем биты выбора канала АЦП ADCON0 |= channel<<3; //устанавливаем необходимый канал АЦП __delay_ms(2); //Acquisition time to charge hold capacitor GO_nDONE = 1; //начинаем процесс АЦП while(GO_nDONE); //ждем пока процесс АЦП не завершится return ((ADRESH<<8)+ADRESL); //возвращаем результат } void main() { //*****I/O Configuration****// TRISC=0X00; //контакты PORT C используются на вывод данных PORTC=0X00; // подаем на все контакты PORTC уровень low TRISB0=1; //контакт RB0 используется в качестве входного контакта //***End of I/O configuration**/// ADC_Initialize(); //конфигурируем модуль АЦП while(1) { int joy_X = (ADC_Read(0)); //считываем положение оси X джойстика int joy_Y = (ADC_Read(1)); //считываем положение оси Y джойстика if (joy_X < 200) //Joy moved up {RC0=0; RC1=1;} //зажигаем верхний светодиод else if (joy_X > 800) //Joy moved down {RC0=1; RC1=0;} // зажигаем нижний светодиод else //если джойстик не двигается {RC0=0; RC1=0;} //выключаем оба светодиода if (joy_Y < 200) //джойстик движется влево {RC2=0; RC3=1;} // зажигаем левый светодиод else if (joy_Y > 800) // джойстик движется вправо {RC2=1; RC3=0;} // зажигаем правый светодиод else // если джойстик не двигается {RC2=0; RC3=0;} // выключаем оба светодиода if (RB0==1) //если кнопка джойстика нажата RC4=1; // зажигаем центральный светодиод else RC4=0; // выключаем центральный светодиод } } |