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.07k stars 403 forks source link

How to send only one pulse when the switch is in the UP position? #176

Open delta464 opened 3 years ago

delta464 commented 3 years ago

How can I code a joystick button to send a single pulse when the toggle switch is on? I need to use a toggle switch for flight simulator panel to turn light on and off. The computer needs to think that I press joy button 1 for a second when switch is UP, and joy button 2 for a second when switch is DOWN.

Something like this:

  if (buttonState != lastButtonState) 
  {if (buttonState == LOW) {Serial.println("PRESS KEY 1");delay(1000);Serial.println("STOP 
  PRESSING KEY");}
  if(buttonState == HIGH) {digitalWrite(LED_BUILTIN, LOW);Serial.println("PRESS KEY 2");;delay(1000);Serial.println("STOP 
  PRESSING KEY");}
  delay(50);}
  lastButtonState = buttonState;
ttait-vantim commented 3 years ago

You can use the ezButton library to easily detect a button change (with debounce - that's important!) and set a button event only on the button off-to-on transition, otherwise nothing. This will give a rapid joystick button press.

Does the joystick virtual button really need to be held for a second??? If so then delay() is not your friend as it is blocking so will prevent anything else from being signaled. The ezButton library also can time the duration of a press so you can just clear the joystick button when 1 sec is reached on the switch closure (or its released?). You can of course time it yourself using millis() which is how the ezButton library does it.

https://arduinogetstarted.com/tutorials/arduino-button-library

Tim

laubfrosch42 commented 3 years ago

Hi delta 464, it is actually a difference to measure the state of a toggle switch and to send a command to the PC. You can use this circumstance to first measure then analyze the status and only then send a command to the PC. I.e. you could measure when the toggle switch is changing its status (vs. a 2nd variable keeping the last_status from the previous measurement). When you see a change you send only a self-defined pulse to the PC (like a keyboard-stroke).

I use this for example to measure a linear potentiometer, then process the value by putting a formula on top and then send the updated/changed value to the PC. Like this I come from a linear distribution to an s-curved one.

Does that make sense to you?

Ole

Andreas1109 commented 6 months ago

Hi,

i want to customize a panel for my son,. Using a ATMEGA32U4, currently installed with RealRobots. To have it "real" for my son i am using switches instead of buttons. I need to get a single button send whenever the switch position is changed, but i have no idea how that works.. The princip is clear.. But the syntax and where to put in is not clear to me. Maybe anyone can help me here, please? LG Andreas

MHeironimus commented 6 months ago

@Andreas1109 - Can you provide a sample of code you already have? Basically you read the value of the switch on every loop and if it is different from the last time you read it, you send an update to the PC using the library.

Andreas1109 commented 6 months ago

@MHeironimus

Hi Matthew, thanks for your reponse. I am using project 29189463 (https://gitlab.com/jakelwilkinson/rr_controller therefore. Currently without modifications. I am not sure where to put it in. I believe in the input.ino row 531..

// Button inputs
else if (assignedInput > 12 + 31)
{
    // first 11 inputs are reserved for axes
    // button1 is stored as 1+12 but reported HID as 1
    Joystick.setButton(assignedInput - 12 - 32, value);
}

In the preferences.h i found that the values a stored:

Andreas1109 commented 6 months ago

void Store8BitValue(uint16_t idx, uint8_t val) { EEPROM.write(idx, val); }

But i am absoltely beginner. Don´t know the syntax and how to use. :(

Thanks for your help and a Happy New Year :) Andreas

MHeironimus commented 6 months ago

@Andreas1109 - I am not familiar with RealRobots, but I took a look at the code. It seems the existing logic would make the switches work the way I would expect (i.e., a switch in the up position means the button is down and a switch in the down position means the button is up). Are you wanting the button to "pulse" when the switch goes from down to up?

If so, how long do you need the button to be pressed before it goes back up (e.g., 50 ms)?

Andreas1109 commented 6 months ago

@MHeironimus Hi, yes, it works as it is designed. But using switches causes that the button is permanent off or on..

What i need is... If the switch is turned on, i need only one button click send.. 50ms should be fine.. When i turn off the switch, i need again one button click send..

Something like:

If _lastbuttonstate = _currentbuttonstate (do nothing) else if (send button push one time)

I need that for some of the digital pins of the Arduino.. But i don´t know how :(

MHeironimus commented 6 months ago

Since I am not familiar with RealRobots, I can only give you a hint as to what you could try.

I would try adding an array towards the top of the Inputs.ino file, maybe right before the InitInputs function:

...
long lastHatChange = 0;
int lastButtonValue[128];

void InitInputs()
{
...

For wired (Arduino/ATmega32U4) situations, modify the code around line 532 to be something like the following:

    // Button inputs
    else if (assignedInput > 12 + 31)
    {
        // first 11 inputs are reserved for axes
        // button1 is stored as 1+12 but reported HID as 1
        int buttonIndex = assignedInput - 12 - 32;

        if (value != lastButtonValue[buttonIndex]) {
            // Indicate to the PC the Joystick button has been pressed if the switch has changed value
            lastButtonValue[buttonIndex] = value;
            Joystick.setButton(buttonIndex, 1);
        } else {
            // Indicate to the PC the Joystick button has been released if the switch value has not changed
            Joystick.setButton(buttonIndex, 0);
        }
    }
    else

If Bluetooth (ESP32) is being used, you will need to make these modifications to the code around line 629:

    // Button inputs
    else if (assignedInput > 12 + 31)
    {
        // first 11 inputs are reserved for axes
        // button1 is stored as 1+12 but reported HID as 1
        //Joystick.setButton(assignedInput - 12 - 16, value);
        int buttonIndex = assignedInput - 12 - 32;

        if (value != lastButtonValue[buttonIndex]) {
            // Indicate to the PC the Joystick button has been pressed if the switch has changed value
            lastButtonValue[buttonIndex] = value;
            SetButton(buttonIndex, 1);
        } else {
            // Indicate to the PC the Joystick button has been released if the switch value has not changed
            SetButton(buttonIndex, 0);
        }
    }

It is possible the loop is running too fast and the button will not be pressed long enough for the PC to detect it, but this is the simplest code change I could think of and I would try this first and see how it works.

Hope this helps.

Andreas1109 commented 6 months ago

@MHeironimus Hi Matthew,

helps a lot. Need some time to understand.. "long lastHatChange = 0" is already used and if i add "int lastButtonValue[128];" the arduino crashes.. Many thanks for your help :)