Как исправить задержку курсора мыши на голосовой и двигательной головной мыши в беспроводных настройках?

Для моего проекта head mouse, который основан на модуле распознавания голоса V3.1 для операций левого клика, двойного клика, правого клика, я столкнулся с проблемой. Я использую радиочастотный односторонний приемопередатчик 433 МГц для отправки данных. Когда я использую акселерометр MPU 6050 и гироскоп для перемещения курсора мыши и модуль распознавания голоса вместе только на одной плате Arduino, курсор мыши движется плавно, а голосовые команды работают плавно. Но когда я использую радиочастотный односторонний передатчик 433 МГц для одной платы Arduino, чтобы рассчитать движение мыши и выяснить голосовую команду, чтобы отправить ее беспроводным способом и получить значения и голосовые команды, используя модуль приемника rf433 МГц, курсор мыши начинает отставать. Он не движется гладко. Пожалуйста, помогите мне решить эту проблему. Код и принципиальная схема приведены ниже:

RF 433 Mhz Transmitter Circuit of Arduino Micro with Elechouse Voice Recog Module V3.1 and MPU6050 motion gyro-accel IMU with

RF 433Mhz receiver circuit using Arduino micro

Передатчик.ино

  /*433 MHz RF Module Transmitter Demonstration 1
  RF-Xmit-Demo-1.ino
  Demonstrates 433 MHz RF Transmitter Module
  Use with Receiver Demonstration 1
 
  DroneBot Workshop 2018
  https://dronebotworkshop.com
*/
 
// Включить библиотеку амплитудной манипуляции RadioHead
#include <RH_ASK.h>
// Включить зависимую библиотеку SPI
#include <SPI.h>
#include <SoftwareSerial.h>
#include "VoiceRecognitionV3.h"
#include <Mouse.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>

VR myVR(8,9);    // 9: RX 8: TX

uint8_t records[7]; // сохранить запись
uint8_t buf[64];

MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz, oax, oay, oaz, ogx, ogy, ogz;
int16_t vx, vy;
//
#define leftRecord    (0)
#define rightRecord   (1)
#define doubleRecord  (2)

/**
  @brief   Print signature, if the character is invisible,
           print hexible value instead.
  @param   buf     --> command length
           len     --> number of parameters
*/
void printSignature(uint8_t *buf, int len)
{
  int i;
  for(i=0; i<len; i++){
    if(buf[i]>0x19 && buf[i]<0x7F){
      Serial.write(buf[i]);
    }
    else{
      Serial.print("[");
      Serial.print(buf[i], HEX);
      Serial.print("]aurav");
    }
  }
}

/**
  @brief   Print signature, if the character is invisible,
           print hexible value instead.
  @param   buf  -->  VR module return value when voice is recognized.
             buf[0]  -->  Group mode(FF: None Group, 0x8n: User, 0x0n:System
             buf[1]  -->  number of record which is recognized.
             buf[2]  -->  Recognizer index(position) value of the recognized record.
             buf[3]  -->  Signature length
             buf[4]~buf[n] --> Signature
*/
void printVR(uint8_t *buf)
{
  Serial.println("VR Index\tGroup\tRecordNum\tSignature");
  Serial.print(buf[2], DEC);
  Serial.print("\t\t");

  if(buf[0] == 0xFF){
    Serial.print("NONE");
  }
  else if(buf[0]&0x80){
    Serial.print("UG ");
    Serial.print(buf[0]&(~0x80), DEC);
  }
  else{
    Serial.print("SG ");
    Serial.print(buf[0], DEC);
  }
  Serial.print("\t");

  Serial.print(buf[1], DEC);
  Serial.print("\t\t");
  if(buf[3]>0){
    printSignature(buf+4, buf[3]);
  }
  else{
    Serial.print("NONE");
  }
  Serial.println("\r\n");
}

struct dataStruct{
  int16_t moveX;
  int16_t moveY;
  int flag;
  }myData;

byte tx_buf[sizeof(myData)] = {0};
 
// Создать объект амплитудной манипуляции сдвигом
RH_ASK rf_driver;
int flag = 15;
 
void setup()
{


   /** initialize */
  
  Wire.begin();
  mpu.initialize();
  if (!mpu.testConnection()) {
    while (1);
    }
    
  myVR.begin(9600);
  Serial.begin(115200);
  Serial.println("Elechouse Voice Recognition V3 Module\r\nControl LED sample");
  
    
  if(myVR.clear() == 0){
    Serial.println("Recognizer cleared.");
  }else{
    Serial.println("Not find VoiceRecognitionModule.");
    Serial.println("Please check connection and restart Arduino.");
    while(1);
  }
  
  if(myVR.load((uint8_t)leftRecord) >= 0){
    Serial.println("leftRecord loaded");
  }
  
  if(myVR.load((uint8_t)rightRecord) >= 0){
    Serial.println("rightRecord loaded");
  }

  if(myVR.load((uint8_t)doubleRecord) >= 0){
    Serial.println("doubleRecord loaded");
  }
  
  
    // Инициализация объекта ASK
    rf_driver.init();
    if(!rf_driver.init()) Serial.println("Init failed");
    

    
}
 
void loop()
{

  int ret;

  ret = myVR.recognize(buf, 50);
    const char *msg = "Welcome to the Workshop!";

  if(ret>0){
  
  switch(buf[1]){
    
    case leftRecord:
    flag = 0;
    break;
    
    case rightRecord:
    flag = 1;
    break;

    case doubleRecord:
    flag = 2;
    break;
            
    default:
    flag=3;
    Serial.println("Record function undefined");
    break;
    }
    /** voice recognized */
    printVR(buf);
  }
  
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
    
  oax = ax+72;
  oay = ay-382;
  oaz = az-505;
  ogx = gx+99;
  ogy = gy-29;
  ogz = gz-50;

  vx = gx/200;  
  vy = -gz/200;
  myData.moveX = vx;
  myData.moveY = vy;
  myData.flag = flag;

  memcpy(tx_buf, &myData, sizeof(myData));
  byte bufSize = sizeof(myData);
  Serial.println("movX\tmovY\tmovZ\toax\toay\toaz\togx\togy\togz\tvx\tvy:");
  Serial.print(myData.moveX, HEX);
  Serial.print("\t");
  Serial.print(myData.moveY, HEX);
  Serial.print("\t");
  Serial.print(myData.flag, HEX);
  Serial.print("\t");
  Serial.print(oax, DEC);
  Serial.print("\t");
  Serial.print(oay, DEC);
  Serial.print("\t");
  Serial.print(oaz, DEC);
  Serial.print("\t");
  Serial.print(ogx, DEC);
  Serial.print("\t");
  Serial.print(ogy, DEC);
  Serial.print("\t");
  Serial.print(ogz, DEC);
  Serial.print("\t");
  Serial.print(vx, HEX);
  Serial.print("\t");
  Serial.println(vy, HEX);

  rf_driver.printBuffer("Buffer values [vx, vy, status flag respectively]: ", tx_buf, bufSize); // каждое значение равно 16 битам. и монитор serail будет отображаться в 8 + 8 = 16 битном формате
    rf_driver.send((uint8_t *)tx_buf, bufSize);
    //Serial.println();
    rf_driver.waitPacketSent();

    flag = 15;
    delay(1);
    
}

Приемник.ино

// Включить библиотеку амплитудной манипуляции RadioHead
#include <RH_ASK.h>
// Включить зависимую библиотеку SPI
#include <SPI.h>
#include <Mouse.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>

#define leftRecord    (0)
#define rightRecord   (1)
#define doubleRecord  (2)
// Создать объект амплитудной манипуляции сдвигом
RH_ASK rf_driver;

struct dataStruct{
  int moveX, moveY, flag;
  }myData;
 
void setup()
{
    // Инициализация объекта ASK
    Wire.begin();
    rf_driver.init();
    // Настройка последовательного монитора
    Serial.begin(115200);
    if(!rf_driver.init()) Serial.println("Init failed");
}
 
void loop()
{
    // Установить размер буфера ожидаемого сообщения
    uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
    uint8_t buflen = sizeof(buf);
    // Проверьте, правильный ли размер полученного пакета
    if (rf_driver.recv(buf, &buflen))
    {
      int i;

      // Получено сообщение с хорошей контрольной суммой, сбросьте его.
  rf_driver.printBuffer("Got:", buf, buflen);
        memcpy(&myData, buf, sizeof(myData));
        Serial.println("");
      
        Serial.print("moveX: ");
        Serial.print(myData.moveX);
      
        Serial.print("  moveY: ");
        Serial.print(myData.moveY);
      
        Serial.print("  Command Status: ");
        Serial.print(myData.flag);
      
      // Сообщение, полученное с действительной контрольной суммой
      Serial.print(" Message Received: ");
      Serial.println((char*)buf);

      Mouse.move(myData.moveX, myData.moveY);

  if(myData.flag!=15){
  
  switch(myData.flag){
    
    case leftRecord:
    Mouse.click(MOUSE_LEFT);
    delay(10);
    break;
    
    case rightRecord:
    Mouse.click(MOUSE_RIGHT);
    delay(10);
    break;

    case doubleRecord:
    Mouse.click(MOUSE_LEFT);
    Mouse.click(MOUSE_LEFT);
    delay(10);
    break;          
    default:
    break;
    }
      
    }
}
}

, 👍2


1 ответ


1

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

Дешевые модули 433 МГц не являются хорошим выбором в случае потоков. им не хватает какого-либо надежного протокола, ACKing и безопасности.

Я бы сделал это, чтобы сделать его лучше:

  • используйте передатчик получше. может быть, дешевые nRF24L01.
  • используйте больший буфер
  • используйте две нити на стороне передатчика. (например, используйте что-то вроде этого, но две нити). один поток для сбора данных и записи их в буфер, следующий - для отправки данных с помощью nrf. к сожалению, nRF24 может отправлять до 32 байт в одном буфере, а интерфейс SPI достаточно быстр, чтобы заполнить его как можно быстрее.
  • если вам нужно, используйте другой поток для расчета перемещений из MPU6050. таким образом, вам не нужно постоянно читать его и отправлять все эти необработанные данные получателю. однако вы можете использовать некоторую интерполяцию на стороне приемника.
,

Но когда я использую nRF24L01, Arduino включается, а затем выключается. Я пробовал это как с Arduino Leonardo, так и с Micro. Как я могу это исправить? Это также иногда вызывает скачки напряжения и перегрев., @Nahian Rifaat

убедитесь, что контакты питания установлены правильно. эта проблема в основном связана с заменой контактов VCC / GND, @Tirdad Sadri Nejad