Tactile Button Keyboard PCB – Part 2

Here are the build notes for my Tactile Button Keyboard PCB.

IMG_7018

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Bill of Materials

IMG_7009

  • Tactile Button Keyboard PCB (GitHub link below).
  • 12 or 13x tactile buttons.
  • 12 or 13x 1N914 or 1N4148 signal diodes.
  • Optional: 2x 15-way pin header sockets (for the Arduino Nano).
  • If a 74HC138 is to be used, then the following are required.  But note that in the current version of the PCB this DOES NOT WORK without patching!
    • Optional: 1x 74HC138.
    • Optional: 1x 100nF ceramic capacitor (for the 74HC138).
    • Optional: 1x 16-way DIP socket (for the 74HC138).
  • Pin headers.

IMG_7012

Build Steps

Taking a typical “low to high” soldering approach.  The one complication might be the height of the tactile buttons used. If short ones are used, then they should be soldered on before the pin headers. If longer ones are used then it might be easier to solder them on last.

Configuration Options (see later text for more details):

  • Decide if the board is to be used with the ROWS/COLS headers; with the on-board Arduino Nano; or with a 74HC138 – it can’t be used in more than one configuration at any one time.
  • If using a 74HC138 then some cutting of tracks is required before doing anything else!  And the diodes need to be installed with the polarity reversed.
  • Decide if two boards are to be linked and how – i.e. will they require the additional ROWS/COLS header pins or be linked via another means (e.g. cables or direct links).
  • Decide if the additional 5-way header for the 74HC138 or the MIDI link is required.

Then this is the suggested order of assembly:

  • If the PCB needs the 13th button trimming off do that first (using a hacksaw is probably easiest).
  • If traces need to be cut to accommodate the 74HC138 or reversed diodes, do that now (see comments later).
  • Solder all diodes (noting that the direction needs reversing if it is to be used with the 74HC138).
  • DIP socket (if used).
  • Disc capacitor.
  • If using short buttons, this is probably the right time to solder those.
  • Arduino headers (if used).
  • Remaining pin headers.

IMPORTANT: As noted in the design notes, the diodes are the WRONG WAY ROUND for use with a 74HC138 3-in-8 decoder and the HC138 EN pins are the “wrong sense” to work.  The diodes are fine if used either directly or with an on-board Arduino Nano.  The build photos show a board being built for all options, but this was before I realised the problems.  Just to be clear – the HC138 will NOT work with the current version of the PCB without patching.

Regardless, here are the build photos.

Testing

I recommend performing the general tests described here: PCBs.

Configuration Options

Arduino Nano

The simplest way to verify the basic operation is to use an Arduino Nano, which has the following pins connected to the key matrix:

  • 8 ROWS on D2-D9
  • 4 COLS on D10-D13

Assuming the diodes are soldered in the direction indicated on the PCB, then the following code will scan all four columns returning the values read from the rows, which by default will be HIGH (1) if no switch is pressed and LOW (0) if a switch is pressed.

#define NUMSW 8
int sw[NUMSW] = {2,3,4,5,6,7,8,9};
#define NUMCOLS 4
int col[NUMCOLS] = {10,11,12,13};

void setup() {
  Serial.begin(9600);

  for (int c=0; c<NUMCOLS; c++) {
    pinMode(col[c],OUTPUT);
    digitalWrite(col[c], HIGH);
  }

  for (int i=0; i<NUMSW; i++) {
    pinMode(sw[i],INPUT_PULLUP);
  }
}

void loop() {
  for (int c=0; c<NUMCOLS; c++) {
    digitalWrite(col[c], LOW);

    for (int i=0; i<NUMSW; i++) {
      Serial.print(digitalRead(sw[i]));
      Serial.print(" ");
    }
    Serial.print("\t");
    digitalWrite(col[c], HIGH);
  }
  Serial.print("\n");
  delay(100);
}

To use the board with the Arduino Keypad Library, this is the configuration, returning a MIDI note number for each button pressed.

const byte ROWS = 8;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{48,54,60,66},
{49,55,61,67},
{50,56,62,68},
{51,57,63,69},
{52,58,64,70},
{53,59,65,72},
{ 0,60, 0,72},
{ 0, 0, 0, 0}
};
byte rowPins[ROWS] = {2,3,4,5,6,7,8,9};
byte colPins[COLS] = {10,11,12,13};

Note how only 6 of the row entries are used, as there are only 6 decoded buttons in each row and two rows are required for a full octave.  But the configuration also includes the extra entry for the additional note if used “standalone”.  This configuration will also support two boards linked together to give two full octaves of use. This is why two of the MIDI notes are repeated as the start and end of different “columns”.

Arduino Uno or External Arduino

The same test can be used with an external Arduino connected to the left hand set of headers (COLS 1-4 and ROWS 1-8) using the same pins:

  • D2-D9 – connect to ROWS 1-8
  • D10-D13 – connect to COLS 1-4

Arduino Nano and MIDI

If the Arduino Nano is installed then it can be connected to an external MIDI module via the 5G-GND-TX-RX header.

IMG_7019

This needs to be connected to an external MIDI module as follows:

  • 5V to VCC/5V
  • GND to GND
  • TX to MIDI OUT
  • RX to MIDI IN

There is a version of my Keyboard MIDI Matrix Decode project for use with this PCB on GitHub here.

IMG_7018

Two Octave Arduino Nano Keyboard

IMG_7010

This requires two PCBs and one of them needs the extra “octave” note removed as shown above.

Then the two boards can be made up as before, but only the left hand (shorter) board will need headers for connection to an Arduino (either via the on-board Nano or via the ROWS/COLS headers).

Regardless of the mode used to drive the matrix, the boards need still a way to be linked together via the ROWS/COLS headers.  This could be using header pins/sockets somehow, using jumper wires, or simply using wire links.

The expansion board does not require any other headers to be installed.

IMG_7024

HC138 and External Arduino

Due to a fault in the connections for the EN pins of the HC138, at present, with this version of the PCB, this DOES NOT WORK at all “as is”.  To get the HC138 working the EN1, 2, 3 enable pins need reversing.  This means hooking up EN1 and 2 to GND and connecting EN3 to 5V.

To do this, the 5V track to the two adjacent E1 and E2 pins at the top of the HC138 needs cutting on both sides.  And the GND connections to E3 need cutting top and bottom.

Then these can be reconnected to GND and 5V respectively as shown below.

Important Warning: getting this wrong could end up shorting 5V to GND and that could damage your connected microcontroller and the 74HC138 so be sure to test for continuity (or not) as required to be sure before connecting power.

ButtonKeyboard-pcb2-mod2

This has to be done prior to any soldering and can be seen (untidily) in the photos below.

Then the re-patching can be done on the underside of the board.

IMG_7035

Then the rest of the board can proceed, but remember the polarity of the diodes has to be reversed.  Note, I’ve run out of switches, so am three short, but at the time of writing they are on their way!

IMG_7036

The following code can be used to test the operation of the buttons.  Note that buttons 1 to 6 are scanning using HC138 values 5 to 0 – i.e. the number is reversed when printing out in the code below.  Also, the output is now in groups of 4 showing all “pin 2” buttons, followed by all “pin 3” buttons and so on.

#define NUMSW 4
int sw[NUMSW] = {6,7,8,9};
#define NUMCOLS 8
#define PINS138 3
int pin138[PINS138] = {2,3,4}; // Drive the 74HC138

void hc138select (int op) {
  if (op >= (1<<PINS138))
    return;

  if (op & 1) digitalWrite(pin138[0], HIGH);
    else digitalWrite(pin138[0], LOW);
  if (op & 2) digitalWrite(pin138[1], HIGH);
    else digitalWrite(pin138[1], LOW);
  if (op & 4) digitalWrite(pin138[2], HIGH);
    else digitalWrite(pin138[2], LOW);
}

void setup() {
  Serial.begin(9600);

  for (int i=0; i<PINS138; i++) {
    pinMode(pin138[i],OUTPUT);
    digitalWrite(pin138[i], LOW);
  }

  for (int i=0; i<NUMSW; i++) {
    pinMode(sw[i],INPUT_PULLUP);
  }
}

void loop() {
  for (int c=0; c<NUMCOLS; c++) {
    hc138select(NUMCOLS-1-c); // Reverse the scanning...

    for (int i=0; i<NUMSW; i++) {
      Serial.print(digitalRead(sw[i]));
      Serial.print(" ");
    }
    Serial.print("\t");
  }
  Serial.print("\n");
  delay(100);
}

Arduino Nano with Reversed Diodes

This is a more complicated mode, and given the problems with the HC138 support, largely theoretical, but if you would like a board that can be reconfigured once built between the three modes, then to accommodate the 74HC138 (assuming it is patched to be made to work) the diodes must be reversed.  But this poses a problem for the on-board Arduino Nano as the OUTPUTs and INPUTs must be reversed compared to the previous configuration.

Why is this an issue?  It is all down to the use of D13 as one of the “COLS”.  Pin 13 on a Nano connects to the built-in LED so can work fine as an OUTPUT pin.  But if used as an INPUT pin, the connection via the LED and on-board resistor to GND will pull the input continuously LOW even when configured in INPUT_PULLUP mode.

The simplest fix is to disconnect pin 13 and use a different IO pin instead.  A0 is just a few pins away from D13, so if you would like to use the board in this way, this is what I would recommend.

This requires cutting the PCB trace from D13 to the right-hand expansion COL header and soldering on a new wire from A0 to the COL header.  This is shown below – the track is cut as indicated by the orange X and then patched as indicated by the blue/purple wire.

The software configuration for the first test sketch listed above is as follows:

#define NUMSW 4
int sw[NUMSW] = {10,11,12,A0};
#define NUMCOLS 8
int col[NUMCOLS] = {2,3,4,5,6,7,8,9};

Note that once again the output will no longer be in sequence as it is now “COL first” compared to the previous configuration – i.e. the output is now in groups of 4 showing all “pin 2” buttons, followed by all “pin 3” buttons and so on.

PCB Errata

There are the following issues with this PCB:

  • The connections to the 74HC138 EN pins are backwards, meaning this DOES NOT WORK without patching.
  • The diodes are also the wrong way round to support use with the 74HC138 regardless.
  • The HC138 outputs are wired up back to front.
  • The ROWS and COLS indications do not match the terminology used with the Arduino Keypad Library if the diodes are reversed.

Basically trying to use the board with the HC138 is a mess.  Sorry about that.

Enhancements:

  • It could be possible to include MIDI OUT circuitry on the PCB.
  • It might be possible to have a better means to connect two PCBs together.
  • The current PCB “expands to the right” but it might have made more sense to “expand to the left” meaning that the main PCB (on the right, with the extra note) has all the main control links on it, and the expansion PCB (on the left without the extra note) is more of a “dumb” board.

Find it on GitHub here.

Closing Thoughts

As I was effectively rebuilding some of my previous stripboard tactile button keyboards, I thought I”d reuse the switches and diodes. It took a few minutes to do, and then cleaning and reusing the components too longer than using new ones, so I wouldn’t really recommend it.  But in this case these are just hobby boards, I was careful not to overheat the diodes, and the components came off fairly easily.  So I was happy that I wasn’t just throwing the old circuits away!

IMG_7011

So apart from the mess up with the HC138 and the diodes (ok, that’s a pretty big mess up… oh well), in principle this works pretty well otherwise.

These boards have been manufactured using the Seeed Fusion PCB service, which I am happy to continue to recommend. They have been supported with discount vouchers that I’ve been sent by Seeed for my previous projects.

Kevin

Leave a comment