I am trying to control the mouse of a raspberry pi with orientation data from a sensor (I'm using this one). The sensor is hooked up to an esp32 that sends the data over serial Bluetooth. The problem is that the data seems to process about 30 seconds late on the rpi. Everything is working otherwise. I could not find a way to decrease the serial Bluetooth buffer size because pyserial's set_buffer_size command was raising an error (I think that this is because the Rpi is running Linux) (I am trying to decrease buffer size because, if I'm correct, the buffer being too big can create latency). How can I reduce the latency on this?
EDIT: I realized that I should just slow down the rate at which it sends, so I made the esp32 only send data every x milliseconds (I have it set to 100 right now) and now it works great, even though it kinda sucks to have a low update rate.
Code on rpi:
import serial
import pyautogui
import struct
import time
pyautogui.FAILSAFE = False #allow cursor to go to corner of screen
ser = serial.Serial("/dev/rfcomm0")#start serial Bluetooth
ser.baudrate = 1000000
resolution = pyautogui.size()#get screen size
verticalRatio = resolution.height / resolution.width
viewAngle = 45#horizontal angle bounds of screen
move = False #toggle between x and y values
rot = [0, 0]#raw rotation
percent = [0.0, 0.0]#position as percent of screen
pos = [0, 0]#position to put cursor
while True:
if ser.in_waiting > 0:#when there is serial data
if not move:#x value
rot[0] = struct.unpack('>B', ser.read())[0]-90 #decode data
percent[0] = rot[0]/viewAngle #set as percent
pos[0] = percent[0] * (resolution.width / 2) + (resolution.width / 2) #convert to screen point
else:#y value and move cursor
rot[1] = struct.unpack('>B', ser.read())[0]-90 #decode
percent[1] = rot[1]/(viewAngle*verticalRatio) #percent
pos[1] = percent[1] * (resolution.height / 2) + (resolution.height / 2) #to screen point
print(str(rot) + ' ' + str(time.time())) #for debugging
pyautogui.moveTo(pos[0], pos[1]) #move cursor
move = not move
Code on ESP32:
#include <BluetoothSerial.h>
#include <Wire.h>
#include <Adafruit_BNO055.h>
#include <Adafruit_Sensor.h>
#include <utility/imumaths.h>
const int SAMPLERATE_DELAY = 10; //delay of sensor
Adafruit_BNO055 bno = Adafruit_BNO055(55);//sensor
BluetoothSerial ser;//serial port
imu::Vector<3> EulerCorrect(imu::Vector<3> vec){//prevent looping strait from 360 to 0 (allow negative angles)
if(vec.x()>180){
vec.x() -= 360;
}
if(vec.y()>180){
vec.y() -= 360;
}
if(vec.z()>180){
vec.z() -= 360;
}
return vec;
}
void setup(void) {
Serial.begin(9600);
ser.begin("Gesture Control");
if (! bno.begin()) {
Serial.println("Couldnt start");
while (1) yield();
}
Serial.println("Connected");
bno.setExtCrystalUse(true);
}
void loop() {
unsigned long startTime = millis();
prevPercent = percent;
imu::Vector<3> rot = bno.getVector(Adafruit_BNO055::VECTOR_EULER);//get orientation
rot = EulerCorrect(rot);
//clamp values
if(rot.x() > 90){
rot.x() = 90;
}
if(rot.y() > 90){
rot.y() = 90;
}
if(rot.x() < -90){
rot.x() = -90;
}
if(rot.y() < -90){
rot.y() = -90;
}
//send data
ser.write((byte)(rot.x()+90));
ser.write((byte)(rot.z()+90));
Serial.print(rot.x());
Serial.print(" ");
Serial.println(rot.z());
while ((millis() - startTime) < SAMPLERATE_DELAY){
//wait for sensor
}
}
question from:
https://stackoverflow.com/questions/65861115/serial-bluetooth-latency-is-crazy-high 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…