0

I currently try to build some Drums for the game Clone Hero. The problem that I have is that I can't use both of my Piezo inputs that I have hooked up at the same time. I have a Arduino Pro Micro and use this Library. This is my code that I have so far. I'm pretty new to this Arduino stuff, so I don't understand a ton yet.

Anyway, thanks in Advance. :)

#include <Joystick.h>

const int drum1 = A0;
const int drum2 = A1;
const int drum3 = A2;
const int drum4 = A3;

const int threshold = 100;

int sensorReading = 0;

Joystick_ Joystick;


void setup() {

  // Initialize Joystick Library
  Joystick.begin();
}

// Last state of the button
int lastButtonState = 0;

void loop() {


  sensorReading = analogRead(drum1);

  if (sensorReading >= threshold)
  {
    Joystick.pressButton(0);
    Joystick.releaseButton(0);
  }

  sensorReading = analogRead(drum2);

  if (sensorReading >= threshold)
  {
    Joystick.pressButton(1);
    Joystick.releaseButton(1);

  }
} 

5
  • @Juraj I can use both, but not at the same time.
    – DuddiSuppe
    Aug 5 at 5:07
  • they don't activate at the same time. they activate one after another. here is a video that shows it. imgur.com/a/a6quH5d
    – DuddiSuppe
    Aug 5 at 5:19
  • I think, from your description, that your problem is with your methodology and what you think your code can achieve. Code executes strictly sequentially. If you have simple "if this then that" constructs then yes, things will happen separately, no matter how close you think they are in time. It sounds like you need to introduce the concept of "time slices" and "events" into your design. If these two events happen both within this predefined period of time then activate both buttons.
    – Majenko
    Aug 5 at 11:10
  • An alternative is to separate out the pressing of the buttons from the releasing of the buttons. When the drum is struck press the button, and set a timer running (store a timestamp). When that timer expires (millis() - drum1Time >= 100, for example) then release the button. That way you can have one button being pressed, followed by a second button being pressed, and eventually both buttons being released.
    – Majenko
    Aug 5 at 11:15
  • For that it may be useful to encapsulate all the logic and variables for one drum in a class, then simply instantiate multiple instances with different parameters for each drum pad and joystick button.
    – Majenko
    Aug 5 at 11:17
1

From my interpretation of your problem it seems like you want to be able to press two (or more) joystick buttons at once by striking multiple drum pads. As it stands your code will never be able to do that since you press, then immediately release, each button sequentially.

The simplest way around this is to only press the button when you strike the drum, then release the button at a later time, which gives a chance for another button to be pressed in the meantime. What that "later time" is would be for you to decide.

The simplest thing to do is maintain a "this drum has been struck" flag along with a "this drum was struck at" timestamp (it's possible to combine the two), both of which are set at the moment of striking the drum. Then later in your code you check that timestamp and flag and release the button (and disable the flag) if the required time has expired.

To prevent duplicate code it can be good to encapsulate the logic and state variables for a single drum into a class and then instantiate multiple instances, one for each drum pad. For example, here's some untested code that may or may not work:

class Drum {
    private:
        uint32_t _timestamp;
        uint8_t _button;
        uint8_t _channel;
        int16_t _threshold;

    public:
        Drum(uint8_t channel, uint8_t button, int16_t threshold = 100) {
            _channel = channel;
            _button = button;
            _threshold = threshold;
            _timestamp = 0;
        }

        void process() {
            if (_timestamp > 0) { // Has been struck
                if (millis() - _timestamp >= 100) { // 100ms window - adjust as needed
                    Joystick.releaseButton(_button); // Release the button
                    _timestamp = 0; // Set it as not struck
                }
            }

            if (analogRead(_channel) > _threshold) {
                _timestamp = millis(); // Set it as struck now
                Joystick.pressButton(_button); // Press the button
            }
        }
};

Then you can instantiate multiple drums:

Drum drum1(A0, 0);
Drum drum2(A1, 1);

Then in your loop simply:

void loop() {
    drum1.process();
    drum2.process();
}

Again I reiterate: this code is untested, I don't even know if it compiles.

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