Pull to refresh

Добавление метода ввода к Arduino

Reading time 6 min
Views 22K
imageСуществует большое количество различных мастер-китов для тех или иных микроконтроллеров. Однако в Arduino придумали модель мастер-кита с практически нулевым порогом вхождения. Достаточно ввести три строки кода и ты уже мигаешь светодиодом или управляешь двигателем. Но по мере обростания макетной платы всякими датчиками, дисплеем и кнопочками начинаешь понимать, что не хватает более расширенного метода ввода — клавиатуры. Не дорогой и мобильный вариант описан под катом.


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


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

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

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

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

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


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

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

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

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

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

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

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

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

Несмотря на заявление что данный бутлоадер 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) получаем полностью работоспособную клавиатуру:
image

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

Итоги


  • Клавиатура достаточно маленькая чтобы таскать ее с собой в кармане.
  • Опрос клавиатуры по UART позволяет работать с ней без каких-либо внешних библиотек (экономит место во флеше)
  • Использование UART позволит в дальнейшем подключить клавиатуру без проводов через Bluetooth-serial или XBee-serial

PS. Размер прошивки скомилированной в Eclipse + avr-gcc всего 600 байт. Тогда как бинарика меньше чем 3к я в Arduino IDE не видел.
PPS. Исходники и прошивку можно взять здесь: chatboard.tar.gz
Tags:
Hubs:
+38
Comments 7
Comments Comments 7

Articles