Arduino резистивная клавиатура. Подключение матричной клавиатуры к Arduino


Матричная клавиатура и ардуино. Очень интересное и своеобразное сочетание. Глядя на матрицу представляется множество устройств, которые могут быть исполнены с помощью небольшой клавиатуры: умный дом, различные охранные системы и системы управления. В общем большой спектр возможностей, который может быть ограничен лишь вашей фантазией.

Как подключить матричную клавиатуру к Arduino? Легко! Сейчас мы это Вам докажем. А также подключим сервоприводы к Arduino, и будем ими управлять, посылая команды с клавиатуры.

Для урока нам потребуется:

  1. Сервоприводы 2шт.
  2. Матричная клавиатура
  3. Соединительные провода "папа - папа"

Цель урока:

Научиться подключать и работать с клавиатурой. Мы подключим клавиатуру к Arduino, Также в Arduino будут подключены два сервопривода. С помощью управляющих команд, которые будут подаваться с клавиатуры, сервоприводы будут вращаться.

Краткая теория:

Клавиатура типа 4x4. Имеет 16 кнопок с индивидуальными обозначениями. Цифры от 0 до 9, а также символы: " A " , " B " , " C " , " D " и " * ", " # ".

Ход работы:

Для начала давайте соединим клавиатуру и Arduino. Это делается по схеме указанной ниже:

Также для работы нам потребуется подключить сервоприводы. Сервопривод имеет 3 провода, обычно это: коричневый (подключается к GND), красный (подключается к 5V) и оранжевый (управляющий, в данном случае один сервопривод подключается к 11 пину, другой - к 10).

После того, как схема была собрана, можно переходить к написанию скетча. В данном скетче используется библиотека Keypad, необходимая для подключения клавиатуры. Ее вы можете скачать нажав на кнопку .

И так, скетч. Открываем Arduino IDE и вставляем следующий скетч:

#include // Подключаем библиотеку
#include
//используем библиотеку для работы с сервоприводом
Servo servo; //объявляем переменную servo типа Servo
Servo servo2; //объявляем переменную servo2 типа Servo
const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца
char keys = {
{"1","2","3","A"},
{"4","5","6","B"},
{"7","8","9","C"},
{"*","0","#","D"}
};
byte rowPins = {2,3, 4, 5};
byte colPins = {6, 7, 8, 9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int n1=0;
int n2=0;

Void setup(){
Serial.begin(9600);
servo.attach(11); //привязываем привод к порту 11
servo2.attach(10); //привязываем привод к порту 10
}
void loop(){
servo.write(n1); //ставим вал под 0
servo2.write(n2); //ставим вал под 0
char key = keypad.getKey();
if (key == "1") {
n1 = n1 + 45;
if (n1 > 180)
{ n1 = 0; }
}
else if (key == "2")
{ n1 = n1 - 45;
if (n1 < 0) { n1=180; }
}
else if (key == "3")
{ n1 = n1 + 90;
if (n1 > 180) { n1=0; }
}
else if (key == "4")
{ n2 = n2 + 45;
if (n2 > 180) { n2 = 0; }
}
else if (key == "5")
{ n2 = n2 - 45;
if (n2 < 0) { n2=180; }
}
else if (key == "6")
{ n2 = n2 + 90;
if (n2 > 180) { n2=0; }
}
​} ​

​Загружаем скетч в Arduino. И теперь нажимаем на кнопки 1 - 6. Кнопки с 1 по 3, отвечают за первый сервопривод, а кнопки с 4 по 6 - за вторую. При нажатии на кнопки 1, 2, 3, 4 сервоприводы будут менять свой угол поворота на 45 градусов, а при нажатии на 5 и 6 - на угол 90 градусов.

Эта статья посвящена матричной клавиатуре. Я расскажу об устройстве клавиатуры, её возможностях. И, конечно, статья содержит программный код с подробными пояснениями.


Собственно матричная клавиатурка.


Схема.


Все предельно просто. Если ни одна из кнопок не нажата, то между вертикальными линиями (1, 2, 3, 4) и горизонтальными линиями (5, 6, 7, 8) нет контакта. Нажатие кнопочки приводит к возникновению контакта между одной из вертикальных линий (1, 2, 3, 4) и одной из горизонтальных линий (5, 6, 7, 8). Например, нажатие кнопки S1 приводит к возникновению контакта между линиями 4 и 5.


Впрочем, никто не запрещает подключать эту клавиатурку к контроллеру через резисторы ом в 500. Это поспособствует защите контроллера от ошибок при подключении, а также программных ошибок.

Как работать с этой клавиатурой? Самая первая мысль, что приходит в голову, заключается в том, чтобы сконфигурировать выводы ардуино к которым подключены линии 1, 2, 3 и 4 как вход с включенным подтягивающим резистором. А выводы ардуино к которым подключены линии 5, 6, 7 и 8 сконфигурировать как выход и установить на них логический ноль. Пока ни одна из кнопок не нажата, на выводах ардуино связанных с линиями 1, 2, 3 и 4 будет логическая единица. Если кнопку нажать, то на одном из выводов ардуино связанном с линией 1, 2, 3 или 4 установится логический ноль. Но с любой из этих линий связано сразу четыре кнопки. Чтобы узнать какая конкретно кнопка нажата нужно изменить настройки. Выводы ардуино к которым подключены линии 1, 2, 3 и 4 следует сконфигурировать как выход и установить на них логический ноль. А выводы ардуино к которым подключены линии 5, 6, 7 и 8 необходимо сконфигурировать как вход с включенным подтягивающим резистором. Теперь логический ноль будет на одном из выводов ардуино связанном с линией 5, 6, 7 или 8. С каждой из этих линий также связано сразу четыре кнопки. Однако у каждой из линий 5, 6, 7 и 8 есть лишь одна общая кнопка с каждой из линий 1, 2, 3 и 4. Кнопка, которая нажата, находится на пересечении линий на которых читается логический ноль при первом и при втором варианте настроек.

Для наглядности опишу как это все будет работать при нажатии кнопки S2. Выводы ардуино к которым подключены линии 1, 2, 3 и 4 сконфигурированы как вход с включенным подтягивающим резистором. Выводы ардуино к которым подключены линии 5, 6, 7 и 8 сконфигурированы как выход и на них установлен логический ноль. На выводах ардуино связанных с линиями 1, 2 и 4 будет читаться логическая единица. На выводе ардуино связанном с линией 3 будет читаться логический ноль. Такое возможно при нажатии одной из кнопок S2, S6, S10 и S14. Теперь настройки меняются. Выводы ардуино к которым подключены линии 1, 2, 3 и 4 сконфигурированы как выход и на них установлен логический ноль. Выводы ардуино к которым подключены линии 5, 6, 7 и 8 сконфигурированы как вход с включенным подтягивающим резистором. На выводах ардуино связанных с линиями 6, 7 и 8 будет читаться логическая единица. На выводе ардуино связанном с линией 5 будет читаться логический ноль. Такое возможно при нажатии одной из кнопок S1, S2, S3 или S4. У линий 3 и 5 есть лишь одна общая кнопка. Это кнопка S2. Нажатая кнопка находится на пересечении линий 3 и 5.

Программа.

//////////////////////// // // Arduino Uno // //////////////////////// // // Sketch: Matrix Keyboard // // Keyboard --- Arduino Uno // // 1 --- D11 // 2 --- D10 // 3 --- D9 // 4 --- D8 // 5 --- A0 (D14) // 6 --- A1 (D15) // 7 --- A2 (D16) // 8 --- A3 (D17) #include void setup() { DDRB = 0b00000000; PORTB = 0b00000000; DDRC = 0b00000000; PORTC = 0b00000000; DDRD = 0b00000000; PORTD = 0b00000000; Serial.begin(9600); } void loop() { unsigned char x = 4, y = 4; DDRB = 0b00000000; PORTB = 0b00001111; _delay_us(10); // Wait 10 us DDRC = 0b00001111; PORTC = 0b00000000; _delay_us(10); // Wait 10 us if ((PINB & 0b00000001) == 0) x = 0; if ((PINB & 0b00000010) == 0) x = 1; if ((PINB & 0b00000100) == 0) x = 2; if ((PINB & 0b00001000) == 0) x = 3; DDRC = 0b00000000; PORTC = 0b00001111; _delay_us(10); // Wait 10 us DDRB = 0b00001111; PORTB = 0b00000000; _delay_us(10); // Wait 10 us if ((PINC & 0b00000001) == 0) y = 0; if ((PINC & 0b00000010) == 0) y = 1; if ((PINC & 0b00000100) == 0) y = 2; if ((PINC & 0b00001000) == 0) y = 3; if (x != 4 && y != 4) Serial.println(((y*4)+x+1)); _delay_ms(1000); // Wait 1000 ms } // // End // ////////////////////////
Результат работы программы можно наблюдать в мониторе порта Arduino IDE.


Основным недостатком описанного алгоритма является некорректная работа при одновременном нажатии нескольких кнопок. Здесь нужно сказать, что есть алгоритм для матричной клавиатуры позволяющий корректно обрабатывать одновременное нажатие двух кнопок. Но про него я расскажу как нибудь позже.

Клавиатуры позволяют пользователям вводить данные во время выполнения программы. Данная статья показывает вам, как подключить к Arduino 12-кнопочную клавиатуру, и как использовать библиотеку Keypad.h.

Клавиатура часто требуется для обеспечения ввода данных в систему на Arduino, и мембранные клавиатуры являются экономичным решением для многих приложений. Они довольно тонкие и могут быть легко установлены везде, где они необходимы.

В данной статье мы покажем, как использовать 12-кнопочную цифровую клавиатуру, похожую на ту, что вы можете увидеть на телефоне. 12-кнопочная клавиатура имеет три столбца и четыре строки. Нажатие кнопки замыкает вывод одной из строк с выводом одного из столбцов. Из этой информации Arduino может определить, какая кнопка была нажата. Например, когда нажата кнопка 1, замкнуты столбец 1 и строка 1. Arduino определит это и введет в программу 1.

На рисунке ниже показано, как внутри клавиатуры расположены строки и столбцы.

Эксперимент

В данном эксперименте мы продемонстрируем работу с библиотекой " keypad.h " для Arduino. Когда пользователь нажимает на кнопку на клавиатуре, программа отображает соответствующее значение в мониторе последовательного порта.

Необходимые комплектующие

Схема соединений

Подключите клавиатуру к плате Arduino, как показано на рисунке ниже.

Код

/* Пример кода для руководства по работе с матричной клавиатурой 3x4 совместно с платой Arduino. Данный код выводит значение нажатой на клавиатуре кнопки в монитор последовательного порта. */ #include "Keypad.h" const byte Rows= 4; // количество строк на клавиатуре, 4 const byte Cols= 3; // количество столбцов на клавиатуре, 3 // определяем массив символов соответствующий распределению кнопок на клавиатуре: char keymap= { {"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}, {"*", "0", "#"} }; // соединения клавиатуры с выводами Arduino задаются так: byte rPins= {A6,A5,A4,A3}; // строки с 0 по 3 byte cPins= {A2,A1,A0}; // столбцы с 0 по 2 // команда для библиотеки клавиатуры // инициализирует экземпляр класса Keypad Keypad kpd= Keypad(makeKeymap(keymap), rPins, cPins, Rows, Cols); void setup() { Serial.begin(9600); // инициализация монитора последовательного порта } // Если кнопка нажата, эта кнопка сохраняется в переменной keypressed. // Если keypressed не равна NO_KEY, то выводим значение в последовательный порт. void loop() { char keypressed = kpd.getKey(); if (keypressed != NO_KEY) { Serial.println(keypressed); } }

Заключение

Это очень простой пример, но я думаю, вы смогли увидеть, как легко получить в программе на Arduino данные ввода с клавиатуры. Вы можете использовать этот тип ввода во многих различных проектах, в том числе.

Существует большое количество различных мастер-китов для тех или иных микроконтроллеров. Однако в Arduino придумали модель мастер-кита с практически нулевым порогом вхождения. Достаточно ввести три строки кода и ты уже мигаешь светодиодом или управляешь двигателем. Но по мере обростания макетной платы всякими датчиками, дисплеем и кнопочками начинаешь понимать, что не хватает более расширенного метода ввода - клавиатуры. Не дорогой и мобильный вариант описан под катом.

Часть первая - теоретическая

Есть много методов подключения клавиатуры к Arduino:
  • обычные матричные клавиатуры которые цепляются напрямую к портам (Keypad Tutorial). Недостаток - занимает много портов ввода/вывода, мало кнопок.
  • матричные клавиатуры подключенные через I2C (I2C Port expander and Keypads). Достоинства - занимает всего два вывода, позволяет использовать несколько устройств на той же шине. Недостатки - нужно включать в проект библиотеку для работы с I2C, мало кнопок
  • обычная PS/2 клавиатура (PS2 Keyboard). Достоинства - большая аппаратная база, куча кнопок на любой вкус, занимает мало выводов. Недостатки - нужна библиотека для преобразования скан-кодов, размер - PS/2 клавиатуры не отличаются мобильными размерами
Отвергнув все эти методы из-за малого количества кнопок или большого размера, я вспомнил что у меня на антрессолях уже лет десять лежит миниатюрная клавиатура для сотового телефона - Ericsson Chatboard:


Конкретно эта модель CHA-01 рассчитана питание 5 вольт и представляется телефону… модемом!
Есть еще модель CHA-10, которая используется с более новыми (если так можно сказать про аппараты пяти- семилетнего возраста) телефонами и работает от 3.3 вольт. Обе модели не сложно приобрести на EBay за ~$12 с доставкой.

Можно ограничится немодифицированной версией клавиатуры. Поискать разъем от старого телефона для подключения. Разработать библиотеку, которая будет парсить ввод от клавиатуры, и радоваться жизни.
Однако радоваться долго не получится - большой оверхед протокола (нажатие клавиши 0 вызывает, например, "AT*EKSE=0", а www - "AT*EAPP=0,5,«WWW: »,«WWW»") и включение ввода только после нажатия кнопки SMS не придают удобства использованию.

Выход - сделать на основе этой клавиатуры нечто свое, которое будет работать как необходимо нам и с возможностью изменять поведение если понадобится.

Часть вторая - практическая

Поиск на просторах интернета выдал следующую страницу , которую я использовал в качестве основы для своей переделки. Самым ценной информацией от туда было что микроконтроллер в клавиатуре и Atmel Mega162 совпадают по выводам и последним можно заменить встроенный.


Внутри клавиатура представляет собой стандартную матричную размером 7х7 и занимает 14 выводов микроконтроллера. Наружу информация выдается через UART.

Взяв за основу приведенную информацию строим план перевоплощения:
- заменить микроконтроллер на mega162 ($3 на рынке)
- заменить разъем на «распространенный»
- добавить возможность изменять ПО когда захочется (благо это реализуемо через бутлоадер)
- настроить нормальную IDE для работы с AVR/Arduino (чтобы избавится от ненужного здесь C++/библиотек)
- написать простое ПО для проверки работоспособности (проверка настройки IDE и ознакомление с Си для AVR)

Вооружившись паяльной станцией снимаем ненужные компоненты:

Распиновку оригинального разъема для CHA-01 можно найти :

1, 5 - Vcc +5 Вольт
2 - Chatboard serial out
3 - GND
4 - Chatboard serial in

Припаиваем наши запчасти:

В отличии от автора вышеприведенной статьи, я выбрал в качестве разъема стандартную линейку PBS-08 - она отлично помещается в корпус без напильника и даже ложится на нужные места на плате. И решил не переключаться на внешний резонатор.
В разъем были выведены RX, TX, GND, Vcc, MOSI, MISO, SCK и RST. Таким образом мы сможем в дальнейшем перепрограммировать устройство без извлечения из корпуса.
Кажется что все готово и можно подключать к программатору (я брал попользоваться USBASP, но можно использовать и ардуину для программирования других AVR - ArduinoISP)


Но avrdude напрочь отказывается видеть микроконтроллер. Так как до этого, опыта подобных переделок у меня не было - пришлось обратится к более опытным товарищам для диагностики. За дело взялась тяжелая артиллерия с осцилографом и генератором. После непродолжительных боев я был послан… RTFM.
Оказывается USBASP работает с быстрыми микроконтроллерами (более 4МГц), а mega162 по-умолчанию включает «делитель на 8» и работает от внутреннего генератора на частоте 1МГц. Так как частоты 1МГц для клавиатуры более чем достаточно (да и потребление меньше), я решил ее не менять а искать выходы из ситуации. Выход нашелся очень быстро - у USBASP есть джампер, который понижает «частоту общения» с микроконтроллером (или есть опция -B у avrdude, которая делает это программно, мне помогло -B 3).

Теперь, когда avrdude видит кристалл, казалось бы, следует перепрошить и забыть:) Но опыт первого RTFM меня немного остудил и я решил сначала прогнать ПО на эмуляторе (как оказалось не зря). Для этого, на Протеусе опытных товарищей, была собрана схема клавиатуры. И написана прошивка, которая опрашивала клавиатуру и выводила необходимый символ в UART. И так, все скомпилировано, загружено в эмулятор, параметры виртуального терминала выставлены в 9600,8n1. Но терминал почему-то показывает мусор при нажатии клавиши. Дебаг режим USART в эмуляторе показал что скорость обмена выставляется в 10200 а не в 9600… Опять RTFM - Baud rate зависит от частоты кристалла и при 1МГц стандартная настройка позволяет достичь скорости 4800 (при ошибке 0.2%), тогда как при скорости 9600 ошибка уже составляет 7%! В даташите также приведена таблица ошибок для различных Baudrate/MHz - откуда видно, что на частоте в 1МГц можно достичь ошибки в 0.2% только настройкой Double-rate USART. На Си это выглядит вот так:
#define F_CPU 1000000UL #define BAUD_RATE 9600UL // Init serial UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1); UBRR0H = ((F_CPU/(BAUD_RATE*8L)-1) >> 8); UCSR0A = _BV(U2X0); // Set double-speed, for low freq cpu UCSR0B = _BV(TXEN0)|_BV(RXEN0); // Enable TX, Enable RX UCSR0C = _BV(URSEL0)|_BV(UCSZ00)|_BV(UCSZ01); // 8n1 async
Ура, наш код отлично работает в эмуляторе - показывает все нажатия, отрабатывает нажатие Shift и тп.

Переходим к заливке ПО в клавиатуру. Бутлоадер взял с первой ссылки (stk500boot.zip). Так как он тоже работает через USART - изменил в исходниках инициализацию и скорость на 9600.
Заливается бутлоадер через USBASP следующей коммандой:
avrdude -c usbasp -p m162 -B 3 -U flash:w:stk500boot.hex:i -U hfuse:w:0x98:m

Изменение hfuse необходимо для изменения reset-vector - чтобы загрузка микроконтроллера начиналась с бутлоадера.
Дальнейшее общение с клавиатурой можно осуществлять через UART, и USBASP нам не понадобится.
Я выбрал USB-UART (Serial) конвертер на основе FTDI - так как на таком же чипе построена сама ардуина, соответственно драйвера в системе у меня уже стоят.

По случайному стечению обстоятельств разъем конвертера и моей клавиатуры идеально подошли друг другу, поэтому подключил напрямую:

Несмотря на заявление что данный бутлоадер STK500 совместимый - avrdude не захотел с ним работать через тип программатора stk500v1 - ругался что неверный ID устройства. По исходникам было видно что бутлоадер умеет читать и отдавать ID устройства, поэтому методом перебора я нашел что оно прекрасно работает если указать тип arduino.
Команда для заливки прошивки через UART:
avrdude -c arduino -p m162 -b 9600 -P /dev/tty.usbserial-00001004 -U flash:w:chatboard.hex:i

Проверка через терминал показала что нажимаются далеко не все кнопки, да и главная фича бутлоадера, переходить в режим апдейта ПО по нажатию кнопки Yes, тоже не работает. Перепрошить клавиатуру через UART стало невозможным. Более детальное исследование показало что не работает три колонки кнопок из матрицы 7х7. Все снова уперлось в RTFM… три вывода используемые нами для опроса клавиатуры имеют также альтернативную функцию (JTAG) включенную по-умолчанию. Выключив JTAG (переписать hfuse на 0xD8) получаем полностью работоспособную клавиатуру:

Время подключать к Arduino. В качестве интерфейсного разъема я выбрал нестандартный miniUSB, чтобы не воткнуть случайно что-то неподходящее. Донором для провода послужила старая мышка (откуда еще можно вынуть энкодер). Подключение к клавиатуре - стандартным штырьковым разъемом.
Переходник miniUSB - UART был собран для распиновки UART на SensorShield (на моей макетке пока нет стандартизированного вывода для UART).

Итоги

  • Клавиатура достаточно маленькая чтобы таскать ее с собой в кармане.
  • Опрос клавиатуры по UART позволяет работать с ней без каких-либо внешних библиотек (экономит место во флеше)
  • Использование UART позволит в дальнейшем подключить клавиатуру без проводов через Bluetooth-serial или XBee-serial
PS. Размер прошивки скомилированной в Eclipse + avr-gcc всего 600 байт. Тогда как бинарика меньше чем 3к я в Arduino IDE не видел.
PPS. Исходники и прошивку можно взять здесь:






2024 © gtavrl.ru.