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.1k stars 409 forks source link

Buttons activate itself #175

Open buguniao55555 opened 3 years ago

buguniao55555 commented 3 years ago

Description of Issue

I'm making a control box for car simulation, and there is a big step motor. As long as the step motor is not activated, everything works fine. Every time I start the step motor, the button starts to trigger by itself. My guess is that the EMI cause this, however, I do not see a way to prevent this. Some says the pull_up resistor:

pinMode(2,INPUT_PULLUP);

Will solve this problem. However, I cannot find a way to activate the pull up resistor. Can you give me some help about this?

Technical Details

Sketch File that Reproduces Issue

Sketch file goes here (if applicable)

Wiring Details

wiring is like common button matrix wiring.

15 x x x x x A0 x x x x x A1 x x x x x A2 x x x x x A3 x x x x x 8 9 10 14 16

Additional context

The code is from Amstudio: https://github.com/AM-STUDIO/32-FUNCTION-BUTTON-BOX

include

include

include

//BUTTON BOX //USE w ProMicro //Tested in WIN10 + Assetto Corsa //AMSTUDIO //20.8.17

include

include

define ENABLE_PULLUPS

define NUMROTARIES 4

define NUMBUTTONS 24

define NUMROWS 5

define NUMCOLS 5

byte buttons[NUMROWS][NUMCOLS] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}, {15,16,17,18,19}, {20,21,22,23}, };

struct rotariesdef { byte pin1; byte pin2; int ccwchar; int cwchar; volatile unsigned char state; };

rotariesdef rotaries[NUMROTARIES] { {0,1,24,25,0}, {2,3,26,27,0}, {4,5,28,29,0}, {6,7,30,31,0}, };

define DIR_CCW 0x10

define DIR_CW 0x20

define R_START 0x0

ifdef HALF_STEP

define R_CCW_BEGIN 0x1

define R_CW_BEGIN 0x2

define R_START_M 0x3

define R_CW_BEGIN_M 0x4

define R_CCW_BEGIN_M 0x5

const unsigned char ttable[6][4] = { // R_START (00) {R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN {R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START}, // R_CW_BEGIN {R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START}, // R_START_M (11) {R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START}, // R_CW_BEGIN_M {R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW}, // R_CCW_BEGIN_M {R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW}, };

else

define R_CW_FINAL 0x1

define R_CW_BEGIN 0x2

define R_CW_NEXT 0x3

define R_CCW_BEGIN 0x4

define R_CCW_FINAL 0x5

define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = { // R_START {R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CW_FINAL {R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_BEGIN {R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_NEXT {R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CCW_BEGIN {R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_FINAL {R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW}, // R_CCW_NEXT {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, };

endif

byte rowPins[NUMROWS] = {21,20,19,18,15}; byte colPins[NUMCOLS] = {14,16,10,9,8};

Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS);

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

void setup() { Joystick.begin(); rotary_init();}

void loop() {

CheckAllEncoders();

CheckAllButtons();

}

void CheckAllButtons(void) { if (buttbx.getKeys()) { for (int i=0; i<LIST_MAX; i++)
{ if ( buttbx.key[i].stateChanged )
{ switch (buttbx.key[i].kstate) {
case PRESSED: case HOLD: Joystick.setButton(buttbx.key[i].kchar, 1); break; case RELEASED: case IDLE: Joystick.setButton(buttbx.key[i].kchar, 0); break; } }
} } }

void rotary_init() { for (int i=0;i<NUMROTARIES;i++) { pinMode(rotaries[i].pin1, INPUT_PULLUP); pinMode(rotaries[i].pin2, INPUT_PULLUP);

ifdef ENABLE_PULLUPS

  digitalWrite(rotaries[i].pin1, HIGH);
  digitalWrite(rotaries[i].pin2, HIGH);
#endif

} }

unsigned char rotary_process(int _i) { unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1); rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate]; return (rotaries[_i].state & 0x30); }

void CheckAllEncoders(void) { for (int i=0;i<NUMROTARIES;i++) { unsigned char result = rotary_process(i); if (result == DIR_CCW) { Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0); }; if (result == DIR_CW) { Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0); }; } }

LordPato commented 3 years ago

Do you have a 1k resistor in place? It seems more like a hardware issue than a library issue.

ttait-vantim commented 3 years ago

In your "setup()" routine you should use pinMode() to define your pin modes. If you put "pinMode(<pin #>, INPUT_PULLUP)" there as the OP mentioned it will enable the internal pullup. Or you can add a stronger external pullup. If that isn't good enough a small 0.01uF cap to ground may help. All, make sure you have enough power to handle the steppers. A big cap 100uF or more across the power supply feeding the steppers could help.

Tim

buguniao55555 commented 3 years ago

In your "setup()" routine you should use pinMode() to define your pin modes. If you put "pinMode(<pin #>, INPUT_PULLUP)" there as the OP mentioned it will enable the internal pullup. Or you can add a stronger external pullup. If that isn't good enough a small 0.01uF cap to ground may help. All, make sure you have enough power to handle the steppers. A big cap 100uF or more across the power supply feeding the steppers could help.

Tim

Can you give some details about how to put the pinMode in the setup? Since I didn't find out how he defines the pins. Also, how should I connect the resistors? Should I connect every pin to the ground?

Thanks for reply

ttait-vantim commented 3 years ago

The key matrix decoding library may already be enabling them for the relevant pins, I think that's what the "#define ENABLE_PULLUPS" is meant to do.

Otherwise, in the setup() function add lines like so:

void setup() {
  // switches
  pinMode(7, INPUT_PULLUP);
}

See: https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/

The internal pullups are a bit weak though. If you want to try an external pullup, connect a 1K resistor from the GPIO pin the appropriate voltage (3.3V or 5V depending on your Arduino). Don't use the wrong voltage it could damage the chip.

Also you can try a small capacitor (0.01uF or 0.001uF) from the GPIO to GND as a filter.

Long wires can pickup noise/generate noise, high power connections like the ones that drive the stepper can couple interference into the low power sensitive GPIO signals. Try to keep the stepper motor wires far away from the switch wires. Don't share any GND wires between the two circuits, they should only connect together back near the power supply, otherwiese the high currents from the stepper can cause "ground bounce" to affect the GPIO.

Are you using a stepper driver? Which one?

Tim

VkTheProgrammer17 commented 3 years ago

If its because of EMI, make a plastic casing for it or cover the stepper motor with plastic wrapping. I know it sounds a little silly but hope it works because i have not tried it myself.

xanderhn commented 2 years ago

i am also struggling because of same issue. is there any confirmed solution ?