Hackster is hosting Hackster Holidays, Ep. 4: Livestream & Giveaway Drawing. Start streaming on Wednesday!Stream Hackster Holidays, Ep. 4 on Wednesday!
Evan Rust
Published © GPL3+

Capacitive Touch Sensing Grid

Build a 6x6 grid with an MPR121, expanding possible inputs from a mere 12 to 36!

IntermediateFull instructions provided1 hour25,653
Capacitive Touch Sensing Grid

Things used in this project

Hardware components

Capacitive Touch Sensor Breakout - MPR121
Adafruit Capacitive Touch Sensor Breakout - MPR121
×1
Arduino Nano R3
Arduino Nano R3
×1
Copper Tape Strips
×1

Software apps and online services

Arduino IDE
Arduino IDE
VS Code
Microsoft VS Code

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Wiring

Code

Arduino Nano Code

C/C++
#include <Wire.h>
#include "Adafruit_MPR121.h"

Adafruit_MPR121 cap_sense = Adafruit_MPR121();

#define MPR121_ADDR 0x5A
#define PRINT_DELAY 200

uint32_t sensedPoints[6][6];
volatile bool readFlag = false;

// Rows are pin 0-5, cols are pins 6-11
/*

Pin 6 | 7 | 8 | 9 | 10 | 11
0 |   |   |   |   |    |
------|---|---|---|----|---
1 |   |   |   |   |    |
------|---|---|---|----|---
2 |   |   |   |   |    |
------|---|---|---|----|---
3 |   |   |   |   |    |
------|---|---|---|----|---
4 |   |   |   |   |    |
------|---|---|---|----|---
5 |   |   |   |   |    |
------|---|---|---|----|---

*/

void setup()
{
    Serial.begin(115200);
    while(!Serial);
    if(!cap_sense.begin(MPR121_ADDR))
    {
        //Serial.println("Error setting up MPR121");
        while(1);
    }
    attachInterrupt(digitalPinToInterrupt(2), updateSensedFlagSet, FALLING);
    //Serial.println("Ready to sense");
}

void loop()
{
    /*if(readFlag)
    {
        readFlag = false;
        updateSensed();
    }*/
    updateSensed();
    printTable();
    delay(PRINT_DELAY);
}

void printTable()
{
    Serial.println("TABLE");
    for(int i=0; i<6; i++)
    {
        for(int j=0; j<6; j++)
        {
            if(j != 5) Serial.print(String(sensedPoints[i][j]) + " | ");
            else Serial.println(String(sensedPoints[i][j]));
        }
        //if(i == 5) Serial.println("\n-------------------\n");
    }
    
}

void updateSensedFlagSet()
{
    readFlag = true;
}

void updateSensed()
{
    //Serial.println("Reading");
    for(uint8_t i=0; i<6; i++)
    {
        for(uint8_t j=0; j<6; j++) sensedPoints[i][j] = cap_sense.filteredData(i) * cap_sense.filteredData(j + 6);
    }
    //Serial.println("Table updated");
}

Grid Display

Python
import pygame
from pygame.locals import *
from pygame import *

from serial import Serial
import sys

# It's best to have them be multiples of 6
width = 600
height = 600

pygame.init()

serialPort = "COM8"
ser = Serial(serialPort, baudrate=115200)

screen = pygame.display.set_mode((width, height), HWSURFACE | DOUBLEBUF)

def mainLoop():
    if ser.in_waiting > 0:
        byte_str = ser.read_until()
        read_str = byte_str.decode("utf-8")
        print(read_str)
        if "TABLE" in read_str:
            print("table found")
            for row in range(6):
                byte_str = ser.read_until()
                read_str = byte_str.decode("utf-8")
                read_str.replace(" ", "")
                val_list = read_str.split('|')
                print(val_list)
                for col, val in enumerate(val_list):
                    colorVal = map(int(val), 0, 1600, 0, 255)
                    if colorVal > 1600:
                        colorVal = 1600
                    rect = pygame.Rect((col * width / 6, row * height / 6), (width / 6 - 1, height / 6 - 1))
                    pygame.draw.rect(screen, (colorVal, 0, 255 - colorVal), rect)
            pygame.display.update()
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                print("exiting")
                pygame.quit()
                ser.close()
                sys.exit()

def map(val, in_min, in_max, out_min, out_max):
    return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

while(True):
    mainLoop()

Credits

Evan Rust

Evan Rust

122 projects • 1093 followers
IoT, web, and embedded systems enthusiast. Contact me for product reviews or custom project requests.

Comments