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

2
  • please reduce the code to smallest code that still exhibits the issue and add the code listing to your question
    – jsotola
    May 6, 2020 at 3:04
  • 1
    USB is actively polled by the host and a client can not initiate communications. Maybe it's a buffer filling up?
    – TwoD
    May 6, 2020 at 19:10

1 Answer 1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.