Улучшение цикла перемещения мыши для оптимизации скорости.

Код:

#include <Mouse.h>
#include <hiduniversal.h>
#include "hidmouserptparser.h"
#include <USBController.h>

USBController controller;
USB Usb;
HIDUniversal Hid(&Usb);
HIDMouseReportParser Mou(nullptr);
String x;
String y;
boolean isX; 
int recv;

void setup() {
    Mouse.begin();
    Usb.Init();
    delay(200);

    if (!Hid.SetReportParser(0, &Mou))
        ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}

void loop() {
    Usb.Task();
    recv = controller.read();
    if ((recv-48)==29){ // получение = M
        // , : -4
        ///н: -38
        x="";
        y="";
        isX = true; 
        while (true){
            recv = controller.read();
            if (recv!=0 && recv!=2){ // отфильтровываем 0 и 2
                if ((recv-48)==-38){ // -38 — разрыв строки
                    break;
                }
                else if ((recv-48)==-4){ // переключаемся на значение y после запятой
                    isX = false;
                    continue;
                }
            
                if (isX){
                    x+=String(recv-48);
                }
                else{
                    y+=String(recv-48);
                }
            }
        }
        Mouse.move(x.toInt(),y.toInt());
    }
}

void onButtonDown(uint16_t buttonId) {
    Mouse.press(buttonId);
}

void onButtonUp(uint16_t buttonId) {
    Mouse.release(buttonId);
}

void onMouseMove(int8_t xMovement, int8_t yMovement, int8_t scrollValue) {
    Mouse.move(xMovement, yMovement, scrollValue);
}

Я использую Arduino Leonardo с USB-хостом. Моя цель состоит в том, чтобы переместить курсор в определенное место на основе считанных данных. Формат считанных данных: «MX,Y». и разрыв строки.

В основном цикле

  • Я прочитал данные и вычел 48, потому что это настоящее число.
  • Затем я проверяю, является ли первый символ М, потому что именно здесь начинается начало моих данных.
  • Затем я отфильтровываю 0 и 2, потому что эти значения для меня бесполезны и появляются случайным образом.
  • Я добавляю целочисленные значения в виде строк к x, а затем переключаюсь на y после появления запятой.
  • Затем я преобразую значения string в int и mouse.move.

Проблема в том, что движение мыши медленное и нервное, и я думаю, это потому, что методы toInt и String() замедляют его. Как я могу улучшить свой алгоритм?

, 👍2


1 ответ


Лучший ответ:

1

Это:

while (true){
    recv = controller.read();
    // ...
}

является циклом блокировки. Это означает, что при выполнении этой части код, Arduino зависает на неопределенное время и может больше ничего не делай. В частности, он не может запускать Usb.Task(), что может мы будем причиной вашего нервного поведения.

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

// Разбираем и выполняем команду, полученную через USB.
executeCommand(String &command) {
    // Реализация оставлена читателю в качестве упражнения.
}

// Получаем ли мы в данный момент символы из команды.
bool receivingCommand = false;

// Получена команда, может быть неполной.
String command;

void loop() {
    Usb.Task();
    if (controller.available()) {
        char c = controller.read();
        if (!receivingCommand && c == 'M') {  // начало команды
            receivingCommand = true;
        } else if (receivingCommand && c == '\n') {  // конец команды
            executeCommand(command);
            command = "";
            receivingCommand = false;
        } else if (receivingCommand) {  // тело команды
            command += c;  // буферизуем полученный символ
        }
    }
}

Лучше было бы избегать класса String, который не дружелюбен к памяти вашего Arduino и используйте простую строку C, как объяснено в разделе Чтение последовательного порта на Arduino. Это, однако, скорее всего, это не связано с вашей проблемой дрожания.

,

Спасибо! Как бы я использовал строку C для этой программы. Изначально мой ввод представляет собой число с плавающей запятой, и мне нужно добавить его в массив символов. Разве мне не нужно сначала преобразовать его в строку?, @Jake Jin

@JakeJin: Нет, вам не нужна строка. Вы можете преобразовать число с плавающей точкой в массив символов, используя [dtostrf()](https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42)., @Edgar Bonet