Что и зачем?
Недавно я прочитал статью Михаила Санникова “Подключаем энкодер к компьютеру”. И так совпало, что на днях мне прислали плату Arduino, поэтому захотелось повторить эту простую конструкцию или сделать нечто подобное,
Сначала немного о том, что такое энкодер и зачем он вообще нужен. Энкодер — это преобразователь “угол — код”, выходным сигналом которого является код Грея. Существуют устройства ввода, построенные на энкодерах и внешне выглядищие как массивная шайба, вращая которую, можно, например, поворачивать модель в 3D-редакторе.

(картинка отсюда)
Однако энкодера у меня не было, в магазин ехать не хотелось, поэтому вместо него было решено приспособить старый переменный резистор на 150 КОм, валявшийся без дела в коробке с разным хламом.
Итак, сделать нужно было следующее:
- Подключить переменный резистор к Arduino;
- Сделать программу для контроллера, считывающую байт из аналогового порта и передающую его в компьютер;
- Написать программу для компьютера, эмулирующую нажатие определенных клавиш в зависимости от направления вращения вала переменного резистора.
Хард энд софт
В руководстве по программированию на сайте Arduino был найден пример Analog In, Out Serial, полностью решающий первую и вторую задачи.
Резистор подключается по такой схеме:

Однако код пришлось немного изменить: убрать все строки с Serial.print и заменить одной Serial.write(outputValue):
const int analogInPin = A0; // Переменный резистор подключен к порту A0
int sensorValue = 0; // значение, считанное из порта
void setup() {
Serial.begin(9600); // Инициализация COM-порта
}
// Чтение из порта A0 и вывод этого значения в COM-порт
void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 1023, 0, 255);
Serial.write(outputValue);
delay(10);
}
Управляющая программа для компьютера была написана на C# в Visual Studio 2010 Express.
Главное окно программы:

Диалоговое окно с настройками:

Примечание: нажатие на кнопку “Button” пока не обрабатывается.
Здесь стоит рассмотреть подробнее параметры из группы “Misc”. Первый нужен для эмуляции нажатия на клавишу, остальные — для устранения дребезга.
Latency — задержка в миллисекундах между нажатием на клавишу и отпусканием.
Buffer — количество последовательно считываемых значений из COM-порта.
Jitter — показывает допустимое отклонение от значения последней выборки.
Подавление дребезга и определение направления вращения вала переменного резистора работает следующим образом:
- в буфер считывается определенное число байт (параметр Buffer) из последовательного порта;
- если последний байт в буфере больше суммы первого байта и значения Jitter, то это значит, что вал вращается вправо;
- если последний байт в буфере меньше разности первого байта и значения Jitter, то это значит, что вал вращается влево.
Недостатки такого способа:
— задержка между началом поворота вала и реакцией на него программы;
— клавиша нажимается один раз, независимо от угла поворота. То есть можно быстро повернуть вал резистора (первый байт в буфере будет, скажем, 10, а последний — 30), и программа отработает это как одно нажатие.
Код алгоритма:
int[] buffer = new int[(int)conf.buffer]; // Buffer
int bufferTop = (int)conf.buffer - 1;
for (int i = 0; i < conf.buffer; i++)
{
buffer[i] = sp.ReadByte();
}
if (buffer[bufferTop] > (buffer[0] + conf.jitter))
{
// “Нажимаем” клавишу
}
else if (buffer[bufferTop] < (buffer[0] - conf.jitter))
{
// “Нажимаем” клавишу
}
Проект для Visual Studio, скетч для Arduino и схему можно скачать здесь: http://sourceforge.net/projects/keyemu/files/KeyEmu-0.1b-source.zip/download
В архиве находится каталог bin, содержащий откомпилированную программу. Для ее запуска понадобится установленный .NET Framework 4.
На этом пока все. Любопытный человек может доработать программу — реализовать обработку серии нажатий вместо одного, или же “нажимать” разные клавиши в зависимости от того, какое приложение активно в данный момент времени, или просто “полировать это глюкало” до бесконечности.