TransWikia.com

How to Fix mouse cursor lag on voice & movement based head mouse in wireless setting?

Arduino Asked by Nahian Rifaat on September 25, 2021

For my head mouse project which is based on the voice recognition module V3.1 for left click, double click, right-click operations, I am facing a problem. I am using 433Mhz Radio Frequency one-way Transceiver for sending data. When I use the MPU 6050 accelerometer and gyroscope for mouse cursor movement and the voice recognition module together on only one Arduino board, the mouse cursor moves smoothly and the voice commands work smoothly. But when I use the 433Mhz RF one-way transmitter for one Arduino board to calculate the mouse movement and figure out the voice command to send it in a wireless manner and receive the values and voice commands using the receiver module of the rf433 Mhz, the mouse cursor starts to lag. It doesn’t move smoothly. Please help me solve the problem. The code and circuit diagram are given below:

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

Transmitter.ino

  /*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
  
Welcome to the Workshop!
*/ // Include RadioHead Amplitude Shift Keying Library #include <RH_ASK.h> // Include dependant SPI Library #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]; // save record 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 IndextGrouptRecordNumtSignature"); Serial.print(buf[2], DEC); Serial.print("tt"); 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("tt"); if(buf[3]>0){ printSignature(buf+4, buf[3]); } else{ Serial.print("NONE"); } Serial.println("rn"); } struct dataStruct{ int16_t moveX; int16_t moveY; int flag; }myData; byte tx_buf[sizeof(myData)] = {0}; // Create Amplitude Shift Keying Object 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 ModulernControl 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"); } // Initialize ASK Object 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("movXtmovYtmovZtoaxtoaytoaztogxtogytogztvxtvy:"); 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); //each value is 16 bit. and serail monitor will show in 8 + 8 = 16 bit format rf_driver.send((uint8_t *)tx_buf, bufSize); //Serial.println(); rf_driver.waitPacketSent(); flag = 15; delay(1); }

Receiver.ino

// Include RadioHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// Include dependant SPI Library
#include <SPI.h>
#include <Mouse.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>

#define leftRecord    (0)
#define rightRecord   (1)
#define doubleRecord  (2)
// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

struct dataStruct{
  int moveX, moveY, flag;
  }myData;
 
void setup()
{
    // Initialize ASK Object
    Wire.begin();
    rf_driver.init();
    // Setup Serial Monitor
    Serial.begin(115200);
    if(!rf_driver.init()) Serial.println("Init failed");
}
 
void loop()
{
    // Set buffer to size of expected message
    uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
    uint8_t buflen = sizeof(buf);
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {
      int i;

      // Message with a good checksum received, dump it.
  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);
      
      // Message received with valid checksum
      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;
    }
      
    }
}
}

One Answer

In general, you want to stream some data. and the mouse lag is one of the main obstacles in data streams; lag. so many classic causes such as buffer over-runs and timing problems come to mind.

The cheap 433MHz modules are not a good choice in case of streams. they lack any robust protocol, ACKing and security.

I would do this things to make it better:

  • use a better transmitter. maybe the cheap nRF24L01 ones.
  • use a bigger buffer
  • use two threads on the transmitter side. (e.g. use something like this, but two threads). one thread to collect data and writing it to a buffer, the next one to send data using nrf. furtunately, the nRF24 can send up to 32Bytes in one buffer transmission and the SPI interface is fast enough to fill it's buffer as quick as possible.
  • if you have to, use another thread to calculate movements from MPU6050. so you don't have to read it continuouesly and send all that raw data to reciever. you may use some interpolation on the receiver side though.

Answered by Tirdad Sadri Nejad on September 25, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP