Instruction: One or more 16-key capacitive keypads with Arduino Uno & SPI

Using one 16-key capacitive keypad (TTP229 or 8229) with Arduino Uno and SPI

First of all, verify that your keypad's TTP229- or 8229-chip is marked with "B something", like 8229BSF. This means that you have the SPI version. Some people have been trying to connect to BSF chips with I2C which will not work.

I first tried one of the known-to-work bitbanging methods:
http://forum.hobbycomponents.com/viewtopic.php?f=73&t=1781&hilit=hcmodu0079
since so many people seem to have problems communicating with these keypads. It worked as expected, but all it does is standard SPI communication, in a less efficient way than the SPI bus. (Also it doesn't work for multiple keys.) So I went on to implement the same protocol using the Arduino <SPI.h> library.

The TTP229-BSF or 8229BSF don't accept any incoming data through SPI, so there's no use connecting MOSI (pin 11 on Uno) at all. The obvious drawback of using the SPI bus is that pin 11 can't be used for arbitrary stuff, it's still occupied by the SPI library.

/*
Scanning a 16 key capacitive TTP229-BSF / 8229BSF keypad with SPI
Free to use, 2019 Andreas Gaunitz, 9bit.se

Arduino   Keypad
5v        Vcc
Gnd       Gnd
12 MISO   SDO (Data out)
13 SCK    SCL (Clock in)
*/

#include <SPI.h>

uint16_t key_map_8229;

void setup()
{
  Serial.begin(115200);
  
  SPI.begin();
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE3));
  delay(500); // Allow 500ms for the 8229BSF to get ready after turn-on
}


void loop()
{
  spi_scan_8229();
  
  Serial.println(key_map_8229, BIN);
  
  delay(100);
}


void spi_scan_8229() {
  key_map_8229 = SPI.transfer16(0);
}

Serial monitor output for one, two and three keys pressed simultaneously:

1111011111111111
1111011111111111
1111011111111111
1111011111101111
1111011111101111
1111011111101110
1111011111101110
1111011111101110

TTP229_keypad_scanner_SPI.ino (612 Bytes)

Using multiple 16-key capacitive keypads (TTP229 or 8229) with SPI and a multiplexer

Now, let's connect more keypads.

Normally SPI devices have a CS / CE (Chip Select / Chip Enable) pin, meaning that you can chose which device to talk to, at any time. Unfortunately the TTP229-BSF and 8229BSF don't have that, so you have to isolate them from each other in some other way.

The idea is to send the SPI clock signal to all keypads, but to only listen to the SDO (Serial Data Out?) from one keypad at a time. For this, we need to connect a 4051 multiplexer to the Arduino's MISO pin. Use the 4051 to select which keypad SDO to send to the Arduino MISO.

Overview.jpg

Tip: If you're going to use 4 or less channels on the 4051 you don't need to connect Arduino pin 7 to 4051 C. Instead, just short C to Ground. But in order to use pin 7 for other stuff, you need to remove everything in the code that accesses it.

Uno + Keypad + 4051.jpg

/*
Scanning multiple 16 key capacitive TTP229-BSF / 8229BSF keypads with SPI
Using a 4051 multiplexer to only listen to one data line at a time
Free to use, 2019 Andreas Gaunitz, 9bit.se

Arduino   4051            Keypad
5v        Vdd             Vcc
Gnd       Gnd, INH, Vee   Gnd
5         A
6         B
7         C
12 MISO   Pin 3
13 SCK                    SCL Keypad 0, 1, 2
          Pin 13          SDO (Data out Keypad 0)
          Pin 14          SDO (Data out Keypad 1)
          Pin 15          SDO (Data out Keypad 2)
*/

#include <SPI.h>

const uint8_t MUX_A = 5;  // Used to select mux data channel
const uint8_t MUX_B = 6;
const uint8_t MUX_C = 7;

uint16_t key_map_8229_0;  // The scanned keys
uint16_t key_map_8229_1;
uint16_t key_map_8229_2;


void setup()
{
  pinMode(MUX_A, OUTPUT);
  pinMode(MUX_B, OUTPUT);
  pinMode(MUX_C, OUTPUT);
  
  Serial.begin(115200);
  
  SPI.begin();
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE3));
  delay(500); // Allow 500ms for the 8229BSF to get ready after turn-on
}


void loop()
{
  spi_scan_8229_0(); // Get data frpm the Keypads
  spi_scan_8229_1();
  spi_scan_8229_2();

  // Verify that it works
  Serial.print("0: ");
  Serial.println(key_map_8229_0, BIN);
  Serial.print("1: ");
  Serial.println(key_map_8229_1, BIN);
  Serial.print("2: ");
  Serial.println(key_map_8229_2, BIN);
  Serial.println();
  
  delay(100); // Remove later, this is just to not flood the serial bus
}


void spi_scan_8229_0() {
  // Select MUX channel for 8229_0
  digitalWrite(MUX_A, 0);
  digitalWrite(MUX_B, 0);
  digitalWrite(MUX_C, 0);
  // Get state of all the keys as a 16 bit integer
  key_map_8229_0 = SPI.transfer16(0);
}

void spi_scan_8229_1() {
  // Select MUX channel for 8229_1
  digitalWrite(MUX_A, 1);
  digitalWrite(MUX_B, 0);
  digitalWrite(MUX_C, 0);
  // Get state of all the keys as a 16 bit integer
  key_map_8229_1 = SPI.transfer16(0);
}

void spi_scan_8229_2() {
  // Select MUX channel for 8229_2
  digitalWrite(MUX_A, 0);
  digitalWrite(MUX_B, 1);
  digitalWrite(MUX_C, 0);
  // Get state of all the keys as a 16 bit integer
  key_map_8229_2 = SPI.transfer16(0);
}

Serial monitor output, when pressing one key on Keypad 0 and two keys on Keypad 2:

0: 1111110111111111
1: 1111111111111111
2: 1110111111011111

Uno + Keypad + 4051.jpg

TTP229_multi_keypad_scanner_SPI_MUX.ino (2.05 KB)

Overview.jpg