6.8. Изучаем особенности работы с Arduino Leonardo (и другими платами на основе процессора 32U4)
Leonardo, как и другие платы, построенные на микроконтроллерах с поддержкой интерфейса USB, обладают уникальной способностью эмулировать такие устройства, как, например, клавиатура и мышь. Далее рассмотрим этот вопрос подробнее.
При реализации подобных функций нужно соблюдать осторожность. Если, например, вы напишете программу, которая эмулирует мышь и перемещает курсор по экрану, то могут возникнуть проблемы при нажатии кнопки Загрузить в Arduino IDE. В этом разделе мы опишем несколько приемов, которые позволят избежать подобных проблем.
Совет
Если плата "зависла" в режиме эмуляции мыши или клавиатуры, чтобы перепрограммировать ее, нажмите и отпустите кнопку Reset, удерживая нажатой кнопку Загрузить в Arduino IDE.
При первом подключении платы Leonardo к компьютеру необходимо установить драйверы, как и для Arduino Uno (см. главу 1). Инструкции для установки Leonardo можно найти по адресам http://arduino.cc/en/Guide/ArduinoLeonardoMicro#toc8 или www.exploringarduino.com.
6.8.1. Эмуляция клавиатуры
Благодаря уникальной возможности Leonardo эмулировать USB-устройства, Плату Arduino легко превратить в клавиатуру. В результате можно отправлять комбинации клавиш в виде команд компьютеру или записывать данные непосредственно в файл, открытый на компьютере.
Плата Leonardo может эмулировать USB-клавиатуру, отправляя коды нажатия клавиш и их комбинаций. Рассмотрим эти возможности. Напишем простую программу, которая записывает данные от нескольких аналоговых датчиков в файл, разделяя их символом двоеточия ( формат CSV), который затем можно открыть в Excel или Google SpreadSheeets для построения графика.
Вызовем любой текстовый редактор, создадим пустой документ и сохраним его в файле с расширением csv. Для этого в диалоговом окне Сохранить можно выбрать тип файла Все файлы и вручную ввести имя файла с расширением, например data.csv.
Затем соберем простую схему, как показано на рис. 6.16. Устройство будет следить за показаниями температуры и освещенности, поступающими от аналоговых датчиков, с которыми мы уже встречались в главе 3. Кроме датчиков, в схеме есть кнопка для включения и выключения записи и светодиод, который будет показывать, идет ли в настоящее время запись данных.
Кнопка для включения/выключения записи снабжена функцией устранения дребезга ( см. главу 2). В процессе записи плата Arduino опрашивает датчики и раз в се-
- 144 -

Рис. 6.16. Схема подключения датчиков температуры и освещенности
кунду отправляет в компьютер данные, разделенные запятой. При этом загорается светодиодный индикатор. Поскольку Arduino постоянно опрашивает состояние кнопки, то задержку 1000 мс перед каждой отправкой данных формирует не функция delay(), а функция millis(), которая возвращает количество миллисекунд с последнего сброса платы Arduino. Вы можете посылать данные каждый раз, когда функция millis() выдает значение, кратное 1000 мс, фактически создавая задержку между посылками, равную 1 с. Это реализует оператор остатка деления по модулю (%). Если, например, вы выполните операцию 1000%1000, то результат будет равен нулю, т. к. 1000/1000 = 1 с нулевым остатком. 1500%1000 вернет 500, потому что 1500/1000= 1 с остатком 500. Выполняя деление по модулю millis() на 1000, по
- 145 -
лучим нулевой результат каждый раз, когда millis() выдает значение, кратное 1000, т. е. каждую секунду.
Изучите код листинга 6.9 и загрузите его на плату Arduino Leonardo. Убедитесь, что вы выбрали опцию Arduino Leonardo из меню Инструменты -> Board в Arduino IDE.
Листинг 6.9. Запись данных освещенности и температуры - csv_logger.ino
// Запись данных температуры и освещенности
const int TEMP=0;// Датчик температуры к аналоговому входу 0
const int LIGHT=1;// Датчик освещенности к аналоговому входу 1
const int LED=3;// Светодиод к выводу 13
const int BUTTON=2; // Кнопка к выводу 2
boolean lastButton = LOW;//Последнее состояние кнопки
boolean currentButton = LOW;//Текущее состояние кнопки
boolean running = false;//По умолчанию запись выключена
int counter = 1;//Индекс записываемых данных
void setup()
{
pinMode (LED, OUTPUT);// Контакт светодиода как выход OUTPUT
Keyboard.begin();// Запуск эмуляции клавиатуры
}
void loop()
{
currentButton = debounce(lastButton);// Чтение состояния
if (lastButton == LOW && currentButton==HIGH) // Если нажатие...
running = !running;// Переключить статус записи
lastButton = currentButton;// Установить статус кнопки
if ( running)// Запись включена
{
digitalWrite(LED, HIGH);// Включить светодиод
if (millis() % 1000 == 0)// Прошло 1000 мс
{
int temperature = analogRead(TEMP); // Чтение данных
// с датчика температуры
int brightness = analogRead(LIGHT); // Чтение данных
// с датчика освещенности
Keyboard.print(counter);// Вывод индекса данных
Keyboard.print(",");// Вывод разделителя
Keyboard.print(temperature);// Вывод температуры
Keyboard.print(",");// Вывод разделителя
Keyboard.println(brightness);// Вывод освещенности
// и символа новой строки
counter++;// Инкремент индекса
}
- 146 -
else
{
digitalWrite(LED, LOW);// Запись выключена, погасить светодиод
}
}
}
/*
* Функция устранения дребезга кнопки
* Получает предыдущий и возвращает текущий статус.
*/
boolean debounce(boolean last)
{
boolean current = digitalRead(BUTTON); // Чтение состояния кнопки
if (last != current)// Состояние изменилось...
{
delay(5);// Ждем 5 мс
current = digitalRead(BUTTON);// Чтение состояния кнопки
}
return current;// Возврат текущего состояния кнопки
}
Подробнее рассмотрим некоторые новые функциональные возможности, реализованные в этой программе. Как и ранее при инициализации последовательного порта, клавиатура инициализируется оператором Keyboard.begin() в функции setup().
В цикле loop() Arduino проверяет состояние кнопки и запускает программу устранения дребезга. При нажатии на кнопку значение переменной статуса записи инвертируется. Это достигается применением оператора ! к переменной running.
Когда программа находится в режиме записи, отправка данных выполняется раз в 1000 мс, благодаря описанному ранее приему. Функции эмулированной клавиатуры и последовательного порта очень похожи. Команда Keyboard.print() отправляет строку в компьютер. После получения данных аналоговых датчиков программа передает данные в компьютер в виде нажатия клавиш. Благодаря команде Keyboard.println() Arduino эмулирует нажатие клавиши <Enter> (или <Retum>)
после отправки строки. Индекс данных и оба аналоговых значения при выводе разделяются запятой.
У становите курсор на строке в текстовом документе и нажмите кнопку включения режима записи. Вы должны увидеть, что документ начнет заполняться данными.
Закройте ладонью датчик освещенности или возьмите в руку датчик температуры, значения должны измениться. Затем нажмите кнопку еще раз, чтобы остановить отправку данных. После сохранения файла его можно импортировать в электроую таблицу, чтобы построить график. Как это сделать, показано в видеоуроке к главе.
- 147 -
ПРИМЕЧАНИЕ
Посмотрите демонстрационный видеоклип со страницы
http://www.exploringarduino.com/content/ch6.
6.8.2. Отправка команд для управления компьютером
Плата Leonardo пригодна и для эмуляции нажатия комбинаций клавиш. На компьютерах с операционной системой Windows нажатие комбинации клавиш <Windows>+<L> блокирует экран компьютера (в Linux существует комбинация <Ctrl>+<Alt>+<L> ). Можно, например, по сигналу от датчика освещенности заблокировать компьютер, когда выключается свет. В OS Х для блокировки компьютера предусмотрены комбинации <Control>+<Shift>+<Eject> или <Control>+<Shift>+ +<Power>, которые Leonardo не может сформировать, т. к. невозможно смоделировать нажатие клавиш <Eject> и <Power>. Рассмотрим, как заблокировать компьютер с Windows. Подойдет схема, показанная на рис. 6.16, хотя будет использоваться только датчик.
Запустите предыдущую программу при нескольких различных уровнях освещенности и посмотрите на изменение показаний датчика. С учетом полученных данных нужно выбрать пороговое значение освещенности, ниже которого компьютер следует заблокировать (в моей комнате при выключенном свете показания датчика равны 300, а при включенном - 700, я выбрал пороговое значение 500). Когда значение от датчика станет ниже порогового, на компьютер будет отправлена команда блокировки. Возможно, для вашего помещения потребуется другое значение порога.
Загрузите код листинга 6.10 на плату Arduino. Подберите порог срабатывания путем анализа данных при различной освещенности. Если порог окажется неправильным, то компьютер может быть заблокированным, как только вы запустите его!
Листинг 6.10. Блокировка компьютера по сигналу от датчика освещенности - lock_computer.ino
// Блокировка компьютера при выключении света
const int LIGHT=1;//Датчик освещенности на контакт 1
//Значение с датчика освещенности для блокировки компьютера
const int THRESHOLD =500; //
void setup()
{
Keyboard.begin();
}
void loop()
{
int brightness = analogRead(LIGHT); // Чтение данных датчика
- 148 -
if (brightness < THRESHOLD)
{
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('1');
delay (100);
Keyboard.releaseAll();
}
}
После запуска программы попробуйте выключить свет в комнате. Ваш компьютер должен заблокироваться.
ПРИМЕЧАНИЕ
Вы можете посмотреть демонстрационный видеоклип, расположенный на странице http://www.exploringarduino.com/content/ch6.
В этом примере реализованы две новые функции для эмулятора клавиатуры:
Keyboard.press() И Keyboard.releaseAll(). Запуск Keyboard.press() эквивалентен удержанию клавиши нажатой. Если вы хотите сэмулировать нажатие клавиш <Windows> и <L>, запустите Keyboard.press() для каждой клавиши. Выдержав паузу, вызовите функцию Keyboard. releaseAll(), чтобы завершить нажатие комбинации клавиш. Список специальных клавиш можно найти на сайте http://arduino.cc/en/Reference/KeyboardModifiers.
6.8.3. Эмуляция мыши
С помощью двухкоординатного джойстика и нескольких кнопок можно превратить плату Arduino Leonardo в мышь. Джойстик будет перемещать курсор мыши, а кнопки будут выполнять функции левой, средней и правой кнопок мыши. Как и для клавиатуры, в языке Arduino есть много встроенных функций, позволяющих реализовать функциональность мыши.
Сначала соберите схему с джойстиком и кнопками, как показано на рис. 6.17. Не забывайте, что кнопки нужно снабдить подтягивающими резисторами. Джойстик подключается к аналоговым выводам 0 и 1. Джойстики содержат два потенциометра, присоединенные к рукоятке. При перемещении рукоятки джойстика в направлении х меняется сопротивление одного из потенциометров, в направлении у другого.
На рис. 6.17 изображен джойстик SparkFun, но подойдет любой (в демонстрациоом видеоклипе показан джойстик Parallax). В зависимости от типа джойстика, возможно, потребуется скорректировать диапазон значений функцией map() или поменять х и у в коде программы.
Собрав схему, можно загрузить программу на плату Leonardo. Скопируйте и запустите код листинга 6.1 1 и поуправляйте курсором с помощью джойстика и кнопок; курсор на экране компьютера должен реагировать соответствующим образом.
- 149 -

Рис. 6.17. Схема мыши на основе джойстика и платы Leonardo
Листинг 6.11. Программа управления курсором мыши для Leonardo - mouse.ino
// Создаем мышь !
const int LEFT_BUTTON=4;//Вход для левой кнопки мыши
const int MIDDLE_BUTTON=3;//Вход ДЛЯ средней кнопки мыши
const int RIGHT_BUTTON =2;//Вход для правой кнопки мыши
const int X_AXIS=0;//Аналоговый вход для оси х джойстика
const int Y_AXIS=1;//Аналоговый вход для оси у джойстика
void setup()
{
- 150 -
Mouse.begin();
}
void loop()
{
int xVal=readJoystick(X_AXIS);//Получить отклонение джойстика по оси х
int yVal = readJoystick(Y_AXIS);//Получить отклонение джойстика по оси у
Mouse.move(xVal, yVal, 0);//Перемещаем мышь
readButton(LEFT_BUTTON, MOUSE_LEFT);// Чтение состояния левой кнопки
readButton(MIDDLE_BUTTON, MOUSE_MIDDLE);//Чтение состояния средней кнопки
readButton(RIGHT_BUTTON, MOUSE_RIGHT); //Чтение состояния правой кнопки
delay(5);
}
int readJoystick(int axis)// Чтение значения джойстика, масштабирование
{
int val = analogRead(axis);
// Чтение аналогового значения
val = map(val, 0, 1023, -10, 10); // Масштабирование значения
if (val <= 2 && val >= -2)
// Убрать дрейф мыши
return 0;
else// Вернуть значение
return val;
}
// Чтение состояния кнопок и отправка команд мыши
void readButton(int pin, char mouseCommand)
{
// Если кнопка нажата, эмулируем нажатие, если она еще не быпа нажата
if (digitalRead(pin) == HIGH)
{
if ( ! Mouse.isPressed (mouseCommand) )
{
Mouse.press(mouseCommand);
}
}
// Отпустить нажатие мыши
else
{
if (Mouse.isPressed(mouseCommand))
- 151 -
{
Mouse.release(mouseCommand);
}
}
}
Это, безусловно, один из наиболее сложных примеров из всех, рассмотренных до сих пор. Подробно разберем его, чтобы понять новые функции и ход выполнения программы.
В начале программы определены контакты для подключения кнопок и джойстика, в функции setup() подключена библиотека эмулятора мыши. В цикле loop() непрерывно опрашиваются контакты джойстика и выдаются значения для движения курсора мыши. Контакты кнопок также проверяются и при нажатии кнопки сигнал передается в компьютер.
Функция readJoystick() считывает и масштабирует значения от джойстика. По каждой координате джойстик выдает ряд значений от 0 до 1024, полученных от АЦП.
Но курсор мыши перемещается по относительным координатам и передача Mouse.move() нулевого значения соответствует отсутствию движения по этой оси.
Передача положительного значения для оси х будет перемещать курсор мыши вправо, а отрицательного - влево. Чем больше величина, тем дальше будет перемещаться курсор. Таким образом, в функции readJoystick() значения от 0 до 1023 масштабируем к диапазону от -10 до 10.
Для устранения дрейфа предусмотрен небольшой запас в районе нуля, где курсор мыши должен быть неподвижен. Это связано с тем, что во время нахождения рукоятки джойстика в среднем положении фактическое значение может колебаться вокруг 512. Мы должны быть уверены, что при отпускании джойстика курсор мыши не будет двигаться самопроизвольно. Значения х и у передаются функции mouse.move(), что приводит к перемещению курсора на экране. Третий аргумент функции mouse.move() определяет движение колеса прокрутки.
Функция readButton() служит для определения состояния каждой из трех кнопок.
Функция определяет текущее состояние мыши с помощью команды mouse.isPressed() и опрашивает мышь через функции Mouse.press() и Mouse.release().
ПРИМЕЧАНИЕ
Демонстрационный видеоклип эмулятора мыши для управления компьютером с помощью джойстика можно посмотреть на странице http://www.exploringarduino.com/content/ch6.
Резюме
В этой главе вы узнали следующее:
• Как подключить плату Arduino к компьютеру через USB-преобразователь последовательного порта.
- 152 -
• Как осуществляется преобразование USB-интерфейса в последовательный порт на различных платах Arduino.
• Как можно отправлять данные с Arduino в компьютер через USB-интерфейс.
• Как форматировать отправляемые данные с помощью специальных символов.
• Что последовательные данные передаются в виде символа, который можно преобразовать в целые числа различными способами.
• Как отправлять данные в виде списков с разделителями-запятыми и преобразовывать их в команды с помощью встроенных функций.
• Как можно передать данные из Arduino внешнему приложению на языке Processing.
• Что можно отправлять данные из Processing-приложения на периферийные устройства, подключенные к Arduino.
• Что плата Arduino Leonardo может эмулировать клавиатуру и мышь.
Больше книг — больше знаний!
Заберите 30% скидку новым пользователям на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУ