Когда ты уже не начинающий ардуинщик и погодных информеров у тебя уже несколько штук, хочется чего-то более «оригинального» и «полезного».

Предположим у нас имеется: Arduino Leonardo – 1 штука, Bluetooth модуль – 1 штука, Android смартфон – 1 штука. Ключевое отличие Leonardo от остальных ардуин заключается в том, что она поддерживает протоколы HID, а по-простому может притворятся мышкой или клавиатурой. Выглядит это примерно следующим образом:

#include "Mouse.h" // импортируем библиотеку работы с мышью
void setup(){}            // ничего не настраиваем
void loop()
{
 Mouse.move(10, -15, 3);  // сдвигаем курсор на 10 пикселей вправо, на 15 пикселей вверх и колесо на 3 оборота
}

Как видим все крайне просто. Метод Mouse.move(X, Y, WHEEL) принимает три относительных параметра: 

X – величина смещения в пикселях по оси X (отрицательные значения сдвигают влево)

Y – величина смещения в пикселях по оси Y (отрицательные значения сдвигают вверх)

WHEEL – величина смещения колеса прокрутки (отрицательные значения сдвигают в другую сторону)

Но сама по себе идея двигать курсор ничего не стоит, если не мы его контролируем, а значит нам нужно непосредственно HID (Human Interface Device), или по-простому устройство ввода. В нашем случае мы его сделаем из смартфона, «написав программу» в среде AppInventor, но, предварительно, разберемся с железной частью и напишем скетч для Arduino. Данные в Leonardo со смартфона мы будем отсылать по bluetooth. Модуль bluetooth можно использовать любой подходящий, наиболее популярным решением является HC-05(06). Подключаем по следующей схеме:


Если ваш модуль еще не настроен для управления с arduino  здесь имеется хороший мануал по его настройке.
Итак, модуль подключили и настроили. Теперь необходимо определиться с функционалом. Тут все стандартно, нам необходимо получать смещение по двум координатам, левый и правый клик мыши и обороты колеса. Для начала необходимо импортировать библиотеку для работы с мышью:

#include "Mouse.h"  // Импортируем библиотеку работы с мышью 

И создать переменные с которыми будем работать:

int8_t  mess;       // Сообщение пришедшее в Serial
bool _x = false;    // Префикс смещения по оси X
bool _y = false;    // Префикс смещения по оси Y
bool _w = false;    // Префикс оборотов колеса 

В настройках Setup мы указываем порт, к которому подключен модуль bluetooth. Здесь все несколько отличается от стандартных arduino-плат. Leonardo реализован на чипе Atmega32u4 и имеет встроенную поддержку USB-соединения. Соответственно нулевой Serial-порт реализован непосредственно внутри чипа, а стандартные цифровые выводы 0 и 1 реализуют Serial1. Это означает, что для инициализации UART соединения с модулем bluetooth, нам необходимо использовать следующую конструкцию в блоке Setup:

void setup()
{
  Serial1.begin(115200); // Настраиваем первый порт Serial1
}

Обратите внимание, что мы используем не Serial1, а Serial.

В цикле Loop постоянно опрашиваем буфер Serial1 и в случае поступления данных, производим их обработку:

void loop()
{
  if (Serial1.available())  // Проверяем наличие данных, если что-то есть реализуем код в скобках
  {
    //Если что-то пришло, то реализуется код в этих скобках
  }
}

Далее работаем с конструкцией   if (Serial1.available())  {  здесь будет наш основной код }. Принятый в буфер байт мы присваиваем переменной «mess» при помощи следующей конструкции: 

mess = Serial1.read();

Можно заметить, что при инициализации переменной «mess» я использовал тип данных int8_t. Этот тип представляет собой 8-ми битное число со знаком от -128 до 127. Логика работы здесь такая — смартфон отсылает нам пакеты 8-ми битных чисел в следующем виде:

  • Левый клик мыши: 8-ми битное число (108)
  • Правый клик мыши: 8-ми битное число (114)
  • Прокрутка колеса: два 8-ми битных числа — префикс (122), величина прокрутки (число)
  • Смещение по осям: четыре 8-ми битных числа – префикс по X (120), величина смещения (число), префикс по Y (121), величина смещения (число),

Как видим всего может быть 4 пакета. Если просто пришло число 108, то мы это должны интерпретировать как левый клик мыши, число 114 — правый клик. Прокрутка колеса состоит из двух чисел где первое число (122) дает нам понять, что следующее за ним число — это количество оборотов колеса. То же самое со смещением курсора, только там уже 4 числа: первое (120) говорит о том, что следующее за ним число, означает смещение по оси X, третье число (121) предваряет число смещения по оси Y.

Парсинг всего этого дела выглядит следующим образом:

void loop()
{
  if (Serial1.available())      // Проверяем наличие данных, если что-то есть реализуем код в скобках
  { 
    mess = Serial1.read();      // Пришедшее сообщение
    
    if (_x)                     // Если пришло сообщение смещения по X
    {
      Mouse.move(mess, 0, 0);   // Перемещаем указатель по оси X на пришедшее число 
      _x = false;               // Обнуляем флаг префикса
    }
    if (mess == 120) _x = true; // Если пришел префикс смещения по X

    if (_y)                     // Если пришло сообщение смещения по Y
    {
      Mouse.move(0, mess, 0);   // Перемещаем указатель по оси Y на пришедшее число 
      _y = false;               // Обнуляем флаг префикса
    }
    if (mess == 121) _y = true; // Если пришел префикс смещения по Y

    if (_w)                     // Если пришло сообщение прокрутки колеса
    {
      Mouse.move(0, 0, mess);   // прокручиваем колесо на пришедшее число 
      _w = false;               // Обнуляем флаг префикса
    }
    if (mess == 122) _w = true; // Если пришел префикс колеса прокрутки

    if (mess == 108) Mouse.click(MOUSE_LEFT); // Левый клик
    if (mess == 114) Mouse.click(MOUSE_RIGHT);// Правый клик
  }
}

После присвоения переменной «mess» пришедшего значения, мы определяем в условных операторах что это за число. Если это просто клик, то мы сразу реализуем клик мыши. Если это прокрутка или смещение, то мы присваиваем соответствующей булевской переменной значение true и следующее пришедшее число кладем в соответствующий параметр конструкции Mouse.move(смещение по X, смещение по Y, прокрутка колеса). Полный код выглядит так:

#include "Mouse.h"  // Импортируем библиотеку работы с мышью
int8_t  mess;       // Сообщение пришедшее в Serial
bool _x = false;    // Префикс смещения по оси X
bool _y = false;    // Префикс смещения по оси Y
bool _w = false;    // Префикс оборотов колеса

void setup()
{
  Serial1.begin(115200);        // Настраиваем первый порт Serial1
}

void loop()
{
  if (Serial1.available())      // Проверяем наличие данных, если что-то есть реализуем код в скобках
  { 
    mess = Serial1.read();      // Пришедшее сообщение
    
    if (_x)                     // Если пришло сообщение смещения по X
    {
      Mouse.move(mess, 0, 0);   // Перемещаем указатель по оси X на пришедшее число 
      _x = false;               // Обнуляем флаг префикса
    }
    if (mess == 120) _x = true; // Если пришел префикс смещения по X

    if (_y)                     // Если пришло сообщение смещения по Y
    {
      Mouse.move(0, mess, 0);   // Перемещаем указатель по оси Y на пришедшее число 
      _y = false;               // Обнуляем флаг префикса
    }
    if (mess == 121) _y = true; // Если пришел префикс смещения по Y

    if (_w)                     // Если пришло сообщение прокрутки колеса
    {
      Mouse.move(0, 0, mess);   // прокручиваем колесо на пришедшее число 
      _w = false;               // Обнуляем флаг префикса
    }
    if (mess == 122) _w = true; // Если пришел префикс колеса прокрутки

    if (mess == 108) Mouse.click(MOUSE_LEFT); // Левый клик
    if (mess == 114) Mouse.click(MOUSE_RIGHT);// Правый клик
  }
}

Теперь займемся реализацией приложения для смартфона. Не забываем, что мы только-только закончили делать погодные информеры и котопоилки, а значит Andriod Studio пойло для лохов изучать пока рано, посему нальем себе кефирчика используем среду AppInventor. На базовых навыках по работе с этой средой я останавливаться не стану, можно почитать здесь, а еще лучше просто открыть и потыкаться самому, там все очень просто. Сразу перейду к блокам. Полный ээээ…. ну пусть будет код программы выглядит так:


Совсем просто, правда? А так выглядит интерфейс:




Вверху, там, где надпись: «ПОДКЛЮЧЕНО», это кнопка (список) для выбора и подключения bluetooth устройства (BTN_connect). Ползунок чуть ниже (Multipiller), регулирует скорость перемещения указателя, число справа указывает во сколько раз(TXT_mult). Серая область ниже, это непосредственно зона тачпада (Touch). Под ней три области слева-направо: левая кнопка мыши (L_click), ползунок колесика (Scroll), правая кнопка мыши (R_click). 

Инициализация экрана и переменных:


Переменная «mult» (по умолчанию 2) – множитель смещения указателя. X_shift и Y_shift переменные смещения указателя. При открытии приложения, цвет панели «Touch» устанавливаем в черный.

Далее нам необходимо подключиться к bluetooth устройству (предполагается, что смартфон уже с ним спарен):


При инициализации (Перед Выбором) кнопки подключения (BTN_connect) в ее список добавятся все спаренные со смартфоном устройства и при клике по ней, откроется окно этого списка. По клику по соответствующему устройству (После Выбора), смартфон пытается подключится к выбранному устройству и в случае успеха, изменяет цвет фона «Touch» на серый, и надпись на кнопке выбора на «ПОДКЛЮЧЕНО».

Реализация смещения указателя:


Этот метод срабатывает при движении пальца по панели типа Canvas (Холст). Глобальным переменным X_shift и Y_shift присваиваются округленные (без точки) значения смещения по обоим осям. Затем, в случае если у нас установлено bluetooth соединение, программа отсылает четыре восьмибитных числа где первое число – префикс оси X (120), второе – смещение по Х, третье – префикс оси Y (121), четвертое – смещение по Y. Число смещения по обоим осям умножается на глобальную переменную «mult».
Реализация колесика схожа:


Здесь мы объявляем локальную переменную W_shift, которой точно так же присваиваем смещение по оси Y и отправляем через bluetooth два восьмибитных числа, предваряя префиксом 122.

Реализация кнопок совсем примитивна:


При клике по соответствующей кнопке происходит отправка одного восьмибитного числа.

Изменение множителя:


При изменении значения, происходит перезапись соответствующей переменной «mult» и текстовому полю (TXT_mult) присваивается новое значение «Текст».
 
Как видим, реализация крайне проста. На все про все потребуется один вечер времени одна Arduino Leonardo, один bluetooth модуль и смартфон, тоже одна штука. Зато теперь, можно управлять компьютером или телевизором не вставая с дивана.

При желании можно добавить двойной клик и перетаскивание мышью.

Видео процесса:


Исходники и приложение по ссылкам.



Аренда облачного сервера с быстрыми NVMе-дисками и посуточной оплатой у хостинга Маклауд.