Arduino micro - all 20 digital pins for joystick buttons?

Description of Issue
I'm making a game controller consisting of 12 buttons and 8 switches. The Arduino Micro I'm using has 20 pins that should be able to be used as digital input, which is just perfect.
The "JoystickButton" example works as intended for pins 9-12. I extended the example to use all 20 pins, however only pins 0-13 work, no response from pins 14-19.

Technical Details

  • Arduino Board: Arduino Micro
  • Host OS: Windows 7
  • Arduino IDE Version: 1.8.7

Sketch File that Reproduces Issue

#include <Joystick.h>

Joystick_ Joystick;

void setup() {
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);

  Joystick.begin();
}

const int pinToButtonMap = 0;

int lastButtonState[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void loop() {

  for (int index = 0; index < 20; index++)
  {
    int currentButtonState = !digitalRead(index + pinToButtonMap);
    if (currentButtonState != lastButtonState[index])
    {
      Joystick.setButton(index, currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }

  delay(50);
}

Wiring Details
using internal pullup resitor, all buttons/switches are connected GND->button->pinX


After some more testing I found the analog pins A0-A5 actually do work, but only alone and when adressed as A0-A5, not 14-19 as in following example:

...
void setup() {
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(A5, INPUT_PULLUP);

  Joystick.begin();
}

const int pinToButtonMap = A0;

int lastButtonState[6] = {0,0,0,0,0,0};

void loop() {

  for (int index = 0; index < 6; index++)
...

Using both 0-13 and A0-A5 gives randomly blinking or lit buttons, using 0-19 ignores 14-19.

What am I doing wrong?

What am I doing wrong?

You expect that A0 must be equal 14 but on the Micro pin 14 is MISO, 15 is SCKL and 16 is MOSI. So the integer numbering is simply not as you expected it.
The pins are labeled A0 and not 14 so why do you expect this pin to be pin 14?

I did not just assume that. Although the official pinout does not contain digital pin numbers for pins A0-A5 (surprisingly), there is plenty of images on the internet.

Official pinout:

Images I found for Arduino Micro layout:


Hmm ... I had a look at pins_arduino.h in the IDE folder. The version for micro doesn't contain anything, except it includes a leonardo version of pins_arduino.h

// Mapping of analog pins as digital I/O
// A6-A11 share with digital pins
#define PIN_A0   (18)
#define PIN_A1   (19)
#define PIN_A2   (20)
#define PIN_A3   (21)
#define PIN_A4   (22)
#define PIN_A5   (23)
#define PIN_A6   (24)
#define PIN_A7   (25)
#define PIN_A8   (26)
#define PIN_A9   (27)
#define PIN_A10  (28)
#define PIN_A11  (29)

This also corresponds with Leonardo pinout here.

According to this, the Arduino Micro should use pin 18-23. I'll test this and report.

Confirmed - analog pins A0-A5 are numbered 18-23! (on Arduino Micro)

Now my problem moved somewhere else - from what I understand , the script is designed to read pins in increments of 1.

Reading pins 18-22 works fine, if I only read those. Same for pins 0-13. However, if the script uses all - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,18,19,20,21,22}, it leads to perma-lit buttons again.

Any way out of this?

Since you haven't posted the "script" I'm not even going to try to guess what might be wrong with it.

Steve

slipstick:
Since you haven't posted the "script" I'm not even going to try to guess what might be wrong with it.

Steve

Perhaps you would notice it in my original post.

Anyway,... I tried to rename the pins to use contiguous naming, but to no good ...

// modified sketch
// by Matthew Heironimus
// 2015-11-20

#include <Joystick.h>

Joystick_ Joystick;

//redefining pins to use contiguous pin numbers
#define PIN_01 0
#define PIN_02 1
#define PIN_03 2
#define PIN_04 3
#define PIN_05 4
#define PIN_06 5
#define PIN_07 6
#define PIN_08 7
#define PIN_09 8
#define PIN_10 9
#define PIN_11 10
#define PIN_12 11
#define PIN_13 12
#define PIN_14 13
#define PIN_15 18
#define PIN_16 19
#define PIN_17 20
#define PIN_18 21
#define PIN_19 22

void setup() {
  // Initialize Button Pins
  pinMode(PIN_01, INPUT_PULLUP);
  pinMode(PIN_02, INPUT_PULLUP);
  pinMode(PIN_03, INPUT_PULLUP);
  pinMode(PIN_04, INPUT_PULLUP);
  pinMode(PIN_05, INPUT_PULLUP);
  pinMode(PIN_06, INPUT_PULLUP);
  pinMode(PIN_07, INPUT_PULLUP);
  pinMode(PIN_08, INPUT_PULLUP);
  pinMode(PIN_09, INPUT_PULLUP);
  pinMode(PIN_10, INPUT_PULLUP);
  pinMode(PIN_11, INPUT_PULLUP);
  pinMode(PIN_12, INPUT_PULLUP);
  pinMode(PIN_13, INPUT_PULLUP);
  pinMode(PIN_14, INPUT_PULLUP);
  pinMode(PIN_15, INPUT_PULLUP);
  pinMode(PIN_16, INPUT_PULLUP);
  pinMode(PIN_17, INPUT_PULLUP);
  pinMode(PIN_18, INPUT_PULLUP);
  pinMode(PIN_19, INPUT_PULLUP);

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

// Constant that defines the starting (lowest) pin#
const int pinToButtonMap = PIN_01;

// Last state of the button [number of buttons]
int lastButtonState[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void loop() {

  // Read pin values
  for (int index = 0; index < 19; index++)
  {
    int currentButtonState = !digitalRead(index + pinToButtonMap);
    if (currentButtonState != lastButtonState[index])
    {
      Joystick.setButton(index, currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }

  delay(50);
}

I'm no programmer and I'm spending hours (10+) trying to figure out what's wrong and how some basic functions work. Maybe I just misunderstood how some things work.

As far as I can tell the Joystick library only allows for the buttons all to be on contiguously numbered pins. So it won't work easily for what you want to do.

Maybe you could get away with telling it that you have 0-23 buttons and adding a bit of code to ignore (i.e. don't do the Joystick.setButton()) for the values of 14-17? Is there actually anything connected to those pins?

Steve

slipstick - that sketch only allows for buttons on consecutive pins, but that has nothing to do with the library....

Just use an array instead of a constant offset to map the button numbers to pins.

You can also ditch the PIN_## variables and replace the million pinMode() calls with a loop through this array....

//Outside of any functions, add:

const int buttonToPinMap[19] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,18,19,20,21,22}; (or whatever the pin numbers should be). 

//Change this
int currentButtonState = !digitalRead(index + pinToButtonMap);
//to this
int currentButtonState = !digitalRead(buttonToPinMap[index]);

//and delete 
const int pinToButtonMap = PIN_01;

Hi,

You need to read the individual pin numbers into an array.

int ButtontoPinMap[19] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,18,19,20,21,22};

Then use the array ButtontoPinMap[index] instead of index to load your pin numbers.
I think your for loop needs

for (int index = 0; index <= 19; index++)

As it it won't look at location 19.
Hope it helps... Tom... :slight_smile:
Beat me to it @DrAzzy, "great minds think alike", then again "fools never differ" :slight_smile:

Or, even better...

const int NumButtons = 19;
int ButtontoPinMap[NumButtons] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3,A4};

And then use NumButtons everywhere you had 19 before.

Thank you everyone for the help!

Final code that works:

// modified sketch
// by Matthew Heironimus
// 2015-11-20

#include <Joystick.h>

Joystick_ Joystick;

void setup() {
  // Initialize Button Pins
  // for digitalRead pins A0-A5 = 18-23
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, INPUT_PULLUP);
  pinMode(22, INPUT_PULLUP);

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

// defining the total [#] of buttons and their pins
const int ButtonToPinMap[19] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,18,19,20,21,22};

int lastButtonState[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void loop() {

  for (int index = 0; index < 19; index++)
  {
    int currentButtonState = !digitalRead(ButtonToPinMap[index]);
    if (currentButtonState != lastButtonState[index])
    {
      Joystick.setButton(index, currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }

  delay(50);
}

So now my panel is finally working :slight_smile:

Now I'll only meddle with the libraries if I can limit the number of buttons displayed and remove the axis/hat/thruster from the game device panel, but that's just cosmetics.

Once again, thank you all for the help! Karma added.

Read up on button matrix. 10 pins can handle 25 buttons with 25 diodes and if you debounce in hardware, 25 capacitors.

Analog pins are better used for stick axes, rotaries and sliders.

This was my very first project with Arduino, so I'm happy it works as intended. I also designed the box to utilize the Arduino Micro with 20 digital I/O. I'll be smarter next time :wink:

StrasnyLada:
This was my very first project with Arduino, so I'm happy it works as intended. I also designed the box to utilize the Arduino Micro with 20 digital I/O. I'll be smarter next time :wink:

That's the way to do it and a good attitude to do it with!