MHeironimus / ArduinoJoystickLibrary

An Arduino library that adds one or more joysticks to the list of HID devices an Arduino Leonardo or Arduino Micro can support.
GNU Lesser General Public License v3.0
2.06k stars 403 forks source link

Device always immediately wakes PC after going to sleep #242

Closed hapklaar closed 1 year ago

hapklaar commented 1 year ago

Description of Issue

I built a simple 1 axis controller using your library and it works great. Problem is that when it is connected to USB and I put my PC to sleep, it wakes my computer after a couple of seconds.

Technical Details

Sketch File that Reproduces Issue

#include <FastLED.h>
#include <Joystick.h>

#define ENABLE_ANALOG1 true

#define PIN_SLIDE_POT_A A0 // input pin of the slide pot
#define MAX_SLIDE_POT_ANALGOG_READ_VALUE 690 // maximum voltage as analog-to-digital converted value, depends on the voltage level of the VCC pin. Examples: 5V = 1023; 3.3V ~700

#define NUM_LEDS 10 // add number of LEDs of your RGB LED strip
#define PIN_LED 6 // digital output PIN that is connected to DIN of the RGB LED strip
#define LED_COLOR CRGB( 150, 0, 0)
#define LED_IDLE_COLOR CRGB( 0, 10, 20)

CRGB rgb_led[NUM_LEDS]; // color array of the LED RGB strip

int X1 = A0;
int Y1 = A1;

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 0, 0, 
  true, false, false, false, false, false, false, false, false, false, false);

void setup() {
  pinMode(PIN_SLIDE_POT_A, INPUT);
  FastLED.addLeds<WS2812B, PIN_LED, GRB>(rgb_led, NUM_LEDS);  

  Joystick.begin();
  if (ENABLE_ANALOG1) {
    Joystick.setXAxisRange(512, -512);
  }
}

void JButtonStates() {
  if (ENABLE_ANALOG1) {
    Joystick.setXAxis(analogRead(X1) - 512);
  }  
}

void loop() {
  JButtonStates();
  delay(50);

    // 1) Analog value of slide pot is read
  int value_slide_pot_a = analogRead(PIN_SLIDE_POT_A);

  // 2) Analog value is mapped from slide pot range (analog input value) to led range (number of LEDs)
  int num_leds_switchedon = map(value_slide_pot_a, 0, MAX_SLIDE_POT_ANALGOG_READ_VALUE, 0, NUM_LEDS);  

  // 3) Light up the LEDs
  // Only LEDs are switched on which correspond to the area left of the slide knob
  for (int i = 0; i < num_leds_switchedon; ++i) {
    rgb_led[i] = LED_COLOR;
  }  
  // LEDs are switched off which correspond to the area right of the slide knob
  for (int i = num_leds_switchedon; i < NUM_LEDS; ++i) {
    rgb_led[i] = LED_IDLE_COLOR;
  }
  FastLED.show();
}

Wiring Details

Probably not relevant.

Additional context

MHeironimus commented 1 year ago

I have not had a chance to test this theory, but it appears you are sending a message to the host computer on every loop, even when the state of the joystick has not changed. To fix this you will need to only call setXAxis (or any other library function) when the value is different from the last time you called the function. The FunduinoJoystickShield.ino example shows how this can be done.

hapklaar commented 1 year ago

Thanks for following up! I added a value check to only send updates when the new value was at least 8 higher or lower than previous (the value jumps around a bit) and can see it now doesn't send updates anymore when the pot is not touched:

...
void loop()
{
  bool sendUpdate = false;
  const int currentXAxisValue = analogRead(X1);
  int difference = lastXAxisValue - currentXAxisValue;
  Serial.println(difference);

  if (difference > 8 || difference < -8)
  {
    controller.setXAxis(currentXAxisValue - 512);
    lastXAxisValue = currentXAxisValue;
    sendUpdate = true;
    Serial.println("Sending update!");
  }

  if (sendUpdate)
  {
    controller.sendState();
  }
...

But unfortunately, the device still immediately wakes the PC when connected :(

MHeironimus commented 1 year ago

If you just load one of the sample applications to the device (like the blink example or the Keyboard Message example) does the device keep the PC awake or only when you have a program that uses the Joystick library?

hapklaar commented 1 year ago

or only when you have a program that uses the Joystick library?

This was it! I still had the 'Game Controllers' app open. After closing that the PC no longer woke up.

The same is happening when I leave the serial monitor open and have constant serial output from the Arduino. Didn't know this was a thing :)

Thanks!

Triodes commented 11 months ago

Better late than never. I had the same problem when I wrote some joystick software for my own project. Never could figure out a solution. Now several years later I decided to update the code a bit after some modifications to the hardware and I stumble across this post. I feel like an idiot. 3 lines of extra code to check if the value has actually changed solves this issue. And to think I spent almost a week on debugging this all those years ago. Thanks for posting for me to find!