Как обхитрить тайм трекер при помощи Arduino

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Здравствуйте!
Вся моя семья работает удалённо. Супруга работает в крупной организации, в которой осуществляется мониторинг рабочего времени. Мониторинг реагирует на нажатие кнопок клавиатуры и колесо прокрутки мыши, с таймаутом 5 минут. Жена переболела COVID-19 и после болезни стала сильно уставать во время работы, поэтому позволяет себе небольшие перерывчики. На время этих перерывчиков она просит меня покрутить колесико мыши, но я бывает так увлекусь работой, что забываю это сделать. В связи с этим у меня возникло желание автоматизировать этот процесс.


Я вспомнил что у меня валяется Arduino Leonardo, а его легко запрограммировать на имитацию клавиатуры и мыши. Покопавшись в ящиках нашел его и запрограммировал на имитацию колесика мыши. Но жена меня раскритиковала, так как у них запрещается пользоваться не зарегистрированными USB устройствами (а Arduino обязательно вызовет вопросы). Поэтому было решено крутить колесико мыши механически, для чего был заказан шаговый двигатель 28BYJ-48 в комплекте с драйвером двигателя на микросхеме ULN2003 и взят из другого «пыльного» ящика Arduino Nano.

Рисунок 1. Шаговый двигатель 28BYJ-48 с драйвером на микросхеме ULN2003.
Рисунок 1. Шаговый двигатель 28BYJ-48 с драйвером на микросхеме ULN2003.

Подключил двигатель и кнопку к Arduno, двигатель запитывал как напрямую через Arduino, так и через внешний источник питания. Сейчас двигатель запитывается через Arduino (так меньше проводов висит, а Аrduino это терпит). Написал скетч (как смог) имитирующий прокрутку документа человеком при изучении сложного документа. Прокрутка осуществляется группами то в одну, то в другую сторону через разные промежутки времени. Запустить/остановить процесс скроллинга можно нажатием на кнопку или командами «START», «STOP» переданными по последовательному порту.

Рисунок 2. Схема подключения шагового двигателя (через драйвер) с питанием от Arduino.
Рисунок 2. Схема подключения шагового двигателя (через драйвер) с питанием от Arduino.
Рисунок 3. Схема подключения шагового двигателя (через драйвер) с внешним  питанием.
Рисунок 3. Схема подключения шагового двигателя (через драйвер) с внешним питанием.
#include<AccelStepper.h>
#include <SoftwareSerial.h>

#define HALFSTEP 8   
 
// Определение пинов для управления двигателем
#define motorPin1  2 // IN1 на 1-м драйвере ULN2003
#define motorPin2  3 // IN2 на 1-м драйвере ULN2003
#define motorPin3  4 // IN3 на 1-м драйвере ULN2003
#define motorPin4  5 // IN4 на 1-м драйвере ULN2003

// Инициализируемся с последовательностью выводов IN1-IN3-IN2-IN4 
// для использования AccelStepper с 28BYJ-48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
String str = "START";

const int buttonPin = 12;     // Номер пина кнопки

const int minMaxSpeed = 800;
const int maxMaxSpeed = 1300;
const int minAcceleration = 500;
const int maxAcceleration = 700;
const int minSpeed = 700;
const int maxSpeed = 1000;
const int move = 600; // примерная длина одного перемещения
const int minPause = 1; // Минимальная пауза между группами прокруток (секунды)
const int maxPause = 3*60; // Максимальная пауза между группами прокруток (секунды)

long pos = 0;
int smove = move;
int sMaxSpeed = maxMaxSpeed;
int sAcceleration = maxAcceleration;
int sSpeed = maxSpeed;
unsigned msec = 1000;
bool PREV = false;
int dir = 50;
int count = 5;


void setup(){
  pinMode(LED_BUILTIN, OUTPUT); // Светодиод (красный) для сигнализации (светит - стоп, не светит - работа)
  
  Serial.begin(9600);
  Serial.println("start");
 
  stepper1.setMaxSpeed(sMaxSpeed);
  stepper1.setAcceleration(sAcceleration);
  stepper1.setSpeed(sSpeed);

  pinMode(buttonPin, INPUT_PULLUP); // Настройка кнопки
  stepper1.move(move);
}

int inputHandler(){ // Чтение команд из порта и отслеживание нажатия кнопки
  int res = 0;
    if (Serial.available() > 0) {
      str=Serial.readString();
      str.trim();
      Serial.println(">>>>>>>>>>>>>>>>>");
      Serial.println(str);
      res = 1;
    }

    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW && PREV == HIGH ) {
        if (str=="START") {
          str = "STOP";
          Serial.println("Press button to 'STOP'");
          stepper1.move(0);
          res = 1;
        } else {
          str = "START";
          Serial.println("Press button to 'START'");
          res = 1;
        }
        delay(150);
    } 
    if (str!="START") {
      digitalWrite(LED_BUILTIN, HIGH);
    } else {
      digitalWrite(LED_BUILTIN, LOW);
    }     
    PREV = buttonState;
    return res;
    
}


int delayWithRead(unsigned ms){ // Пауза с обработкой ввода
  Serial.print("Delay = ");
  Serial.print(ms);
  Serial.println(" msec.");
  int time = 0;
  while (time<ms) {
    delay(100);
    if (inputHandler() == 1) {
      Serial.println("Press Key");
      delay(2000);
      return 1;
    }
    time += 100;
  }
  return 0;
}


 void printData(){ // Вывод данных в порт
    Serial.print("sMaxSpeed=");
    Serial.println(sMaxSpeed);
    
    Serial.print("sAcceleration=");
    Serial.println(sAcceleration);

    Serial.print("sSpeed=");
    Serial.println(sSpeed);

    Serial.print("count=");
    Serial.println(count);

    Serial.print("pos=");
    Serial.println(pos);

    Serial.print("smove=");
    Serial.println(smove);
}

void goNewPosition(){ // Обработик перехода на следующую позицию
    sMaxSpeed = random(minMaxSpeed, maxMaxSpeed);
    sAcceleration = random(minAcceleration, maxAcceleration);
    sSpeed = random(minSpeed, maxSpeed);
    stepper1.setMaxSpeed(sMaxSpeed);
    stepper1.setAcceleration(sAcceleration);
    stepper1.setSpeed(sSpeed);
    msec = random(100,500); // Пауза между скроллами в одной группе
    delayWithRead(msec); // Задержка с обработкой ввода
    count--;
    if (count<0) {
      Serial.println("*************************************");// Разделитель групп скроллов
      msec = random(minPause*10,maxPause*10)*100; // Пауза между группами скроллов
      delayWithRead(msec);
      dir = random(0,100);
      count = random(1,5);
    } else {
      Serial.println("_________________________________________");// Разделитель скроллов в одной группе
    }
    if (dir<35) { // Скролл назад с вероятностью 35%
      smove = 0 - move + (random(move/8) - move/16);
    } else {
      smove = 0 + move + (random(move/8) - move/16);
    }        
    pos = pos + smove; // Счетчик общего скролла
    
    printData();// Вывод данных в порт

    if (pos>100){ // Крутить только если чуть ниже стартовой позиции
      stepper1.move(smove); // Задать поворот относительно текущей позиции
    }
  
}


void loop(){ // Основной цикл
    inputHandler(); // Обработка ввода
    if(stepper1.distanceToGo()==0) { // Если поворот закончили
      if (str=="START") goNewPosition(); // Получаем следующую позицию
    }

    if (str=="START"){ // Если нет команды стоять то
      stepper1.run();  // Крутим движок 
    }
}

Из картона сделал футляр для мыши, к которому прикрепил Arduino и двигатель с ведущим колесом которое ложится на колесико мыши и вращает его.

Рисунок 4. Вид гаджета с одной стороны.
Рисунок 4. Вид гаджета с одной стороны.
Рисунок 5. Вид гаджета с другой стороны.
Рисунок 5. Вид гаджета с другой стороны.
Рисунок 6. Гаджет с подопытной мышью:)
Рисунок 6. Гаджет с подопытной мышью:)
Рисунок 7. Мышь в гаджете.
Рисунок 7. Мышь в гаджете.

Как работает устройство можно посмотреть в видео.

 Теперь, когда жене надо отлучиться, она вкладывает мышь в футляр и просто включает этот девайс.

Источник: https://habr.com/ru/post/593697/


Интересные статьи

Интересные статьи

Роботизация с каждым годом все глубже проникает в разные сферы жизни. С помощью роботов можно быстро сделать работу, которая слишком опасна, сложна или требует больших трудозатрат. В этой...
В этой статье мы расскажем, как оптимизировать крупный проект в «Битрикс24» и увеличить его производительность в 3 раза, изменяя настройки MySQL и режим питания CPU. Дано Корпоративн...
Мне посчастливилось участвовать в проекте SOLUT, который стартовал в ЛАНИТ около года назад. Проект развивается благодаря активному участию Центра компетенции больших данных ЛАНИТ (ЦК...
Анимированные гистограммы, которые можно встроить прямо в публикацию на любом сайте, становятся все более популярными. Они отображают динамику изменений любых характеристик за определенное в...
Тема статьи навеяна результатами наблюдений за методикой создания шаблонов различными разработчиками, чьи проекты попадали мне на поддержку. Порой разобраться в, казалось бы, такой простой сущности ка...