1

I have an Arduino Micro that is acting as a HID device for a Linux PC.

I use this call to send the HID values:

HID().SendReport(1, _values, sizeof(_values));

This works in principle, but I noticed this issue:

If my Linux PC is not actively reading the events from the Arduino, then the Arduino is slowed down. My rotary encoders are missing signals, is one symptom.

But as soon as I read the events with my Linux PC, the Arduino loop() runs at full speed again.

I suspect that this is due to recv/send time out delays in the USB core code? Because I noticed this in USBCore.cpp:

u8 timeout = 250; // 250ms timeout on send? TODO

Anyway, I tried to solve this issue in the following manners:

Check for configuration and suspension with:

     if (USBDevice.configured())
      if (!USBDevice.isSuspended())
         ...

Which did not work.

I also tried monitoring the increments of the frame number:

  // See if USB shows activity.
  static uint8_t prev_fr_num = UDFNUML;
  static uint8_t num_times_idle = 0;
  uint8_t fr_num = UDFNUML;
  if (fr_num == prev_fr_num )
  {
    if (num_times_idle < 255)
      num_times_idle++;
  }
  else
  {
    num_times_idle = 0;
    prev_fr_num = fr_num;
  }

And then only send if num_times_idle is smaller than a threshold. Again, this did not help.

The only way to make it fast, is by reading the events with linux, like so:

$ jstest /dev/input/js0

or alternatively:

$ evtest /dev/input/event5

How can I have the USB HID stuff not slow down my loop code when the PC is not paying attention?

Thanks!

Bram

Bram
  • 219
  • 2
  • 9

1 Answers1

2

For those that hit the same issue, here is how I solved it:

Expose the USB_SendSpace() information in the HID interface by editing

/usr/local/arduino-1.8.12/hardware/arduino/avr/libraries/HID/src/HID.cpp

u8 HID_::SendSpace(void)
{
        return USB_SendSpace(pluggedEndpoint);
}

And adding the interface to class HID_ in:

/usr/local/arduino-1.8.12/hardware/arduino/avr/libraries/HID/src/HID.h

That way, before calling HID().SendReport() you can check for send buffer space available by calling the HID().SendSpace() method.

If there is no space, just skip the SendReport() calls, and the Arduino loop() will no longer be slowed down by time outs.

Bram
  • 219
  • 2
  • 9