Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: Missing serial data

  1. #1
    Junior Member
    Join Date
    Jul 2019
    Posts
    7

    Missing serial data

    The application I am working on reads an 8 byte packet from the serial port. It then translates that to mouse movement.
    Unfortunately what happens is eventually a byte or more gets lost from the serial, which then means my packets don't line up.
    Format is CXXYYW00 where
    C command byte (243 is the mouse move relative function code)
    XX big endian signed int for X
    YY big endian signed int for Y
    W signed byte wheel

    243 0 0 0 14 0 0 243 incrementalMouseMove 0 14 0
    0 0 0 11 0 0 0 243 ????
    this should be:
    243 0 0 0 14 0 0 0 incrementalMouseMove 0 14 0


    So a byte was "lost". Both the reading and writing are dead simple:
    Remote:
    Code:
    	for ( char c : {b1, b2, b3, b4, b5, b6, b7, b8}) {
    		serialPort.write(&c, 1);
    		serialPort.flush();
    	}
    Teensy:
    Code:
    while (COMMAND_PORT.available() >= 8) {
      b1 = COMMAND_PORT.read();
      b2 = COMMAND_PORT.read();
      b3 = COMMAND_PORT.read();
      b4 = COMMAND_PORT.read();
      b5 = COMMAND_PORT.read();
      b6 = COMMAND_PORT.read();
      b7 = COMMAND_PORT.read();
      b8 = COMMAND_PORT.read();
    
      printBytes(b1, b2, b3, b4, b5, b6, b7, b8);
      ...eventually it gets unpacked and calls ...
     incrementalMouseMove(x, y, w);
    }
    The issue seems to be coming from use of delay() in the incrementalMouseMove() function which will move the full distance. https://www.pjrc.com/teensy/td_mouse.html states that "For natural looking motion, many small moves performed slowly are needed." I've found that when dragging the mouse the target environments are particularly sensitive to this, so there is a loop that divides the movement up into smaller increments. This uses delay() because I read somewhere that the HID needs delay between commands. But it seems that this use of delay is causing me to miss bytes on the serial port. When I use a longer delay, or more delays, it gets worse.

    Mouse.move(x,y,w); is limited to +/-127, but I allow larger values in the serial protocol and break it down into smaller increments, because I have to anyway. The goal is for the remote to be able to issue mouseDown(LeftButton), then mouseMove(2048, 0,w)

    So I'm stuck between being HID friendly and getting all the data on the serial port it seems.

    Help?

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,574
    Maybe restructure your program, so you do not use delay(). One approach is to create an elapsedMillis variable which you check in loop(), and usually 1 or more other variable to remember what you will send next.

    Or you could edit serial1.c to increase the serial receive buffer. While not as good as a better program structure without delay(), just editing the file to increase one number may be easier than rewriting your code.

  3. #3
    Junior Member
    Join Date
    Jul 2019
    Posts
    7
    Yeah, I was hoping the unit would be able to keep up, but it just can't.

    I restructured it in a few ways. I have consolidated the mouse move commands, and supplied:
    1. an off-board function that consolidates mouse movements < 25ms apart. This cuts down on the serial chatter substantially.
    2. an on-board function to linear interpolate between the start and end mouse movements. The novelties here are that
    a. you can only move the mouse integer amounts.
    b. you don't exceed +/- 127 on the relative move
    c. it is perceived as a smooth movement, i.e. dragging, and not jumping.

    With those two features, I can move the mouse anywhere in just a few bytes
    Code:
    void incrementalMouseMove(int16_t x, int16_t y, int8_t w1, int responseDelay) {
      int steps = sqrt(x*x + y*y);
      int movedX=0; 
      int movedY=0;
      double rateX = x/(double) steps;
      double rateY = y/(double) steps;
      int currentX = 0;
      int currentY = 0;
      int dx = 0;
      int dy = 0;
    
      for (int i=0; i<=steps; i++){
        currentX = i*rateX;
        currentY = i*rateY;
        dx = currentX - movedX;
        dy = currentY - movedY;
        if (dx || dy) {
          Mouse.move(dx, dy, 0);
          delay(responseDelay);
          movedX = currentX;
          movedY = currentY;
        }
      }
    }
    Edit: I also found out that as a Teensy LC, I only have a soft serial buffer and not a real FIFO.
    Last edited by JasonH; 08-16-2019 at 04:43 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •