Introduction: Responsive LED Panel

About: Electronics Enthusiast. I enjoy Embedded Hardware and software design. The STM32 family of microcontrollers are my favorite.

This is a tutorial on how to build your own responsive panels that can be used to build an interactive table, wall, or any other surface. The table works on infrared light so no touch or pressure is required. I've also made custom PCBs to drastically reduce build time. My first build took 40+ hours. With the custom PCB it can be done in 1 hour give or take.

Step 1: Parts List

These are the parts you'll need for one panel

You can purchase this as a kit on my Tindie

  • (16) WS2812 Addressable LEDs size 5050
  • (16) 10k Ohm resistors
  • (16) 220 Ohm resistors
  • (16) 1N4007 Diodes
  • (16) 0.1uF Capacitor 0603 size
  • (16) IR LEDs
  • (16) IR Photoresistors
  • (1) Custom PCB
  • (1) 220uF electrolytic capacitor
  • (4) 2N2222 Transistors
  • (1) Breadboard
  • (1) Arduino
  • Jumper Wire

Step 2: Board Assembly

Hardware assembly is pretty simple. The 2 SMD components will be pre-soldered if you order from the link I shared. You just solder the components as they appear on the board. Be careful not to get the diodes or LEDs backwards. Observe the graphic lines on the PCB. Notice that one side of the LEDs is flat. That flat side is the the cathode or GND leg of the LED. Make sure you solder the LED to match the graphic. The physical LED has a flat side on it as well, to help prevent mistakes. Once you've soldered all the main components you can optionally solder pin headers for easy connection to Arduino.

Step 3: Breadboard Assembly

Now that the Panel is populated you can connect your Arduino in the configuration pictured above. The Wires labeled on the Fritzing diagram should be soldered to the corresponding through holes on the panel as pictured. Include a filter capacitor between PWR and GND to filter the voltage. The manufacturer recommends 1000uF but I'm using 220uF and have had no problems because my desktop supply is not noisy.

Step 4: Code

I've added plenty of comments to the code to make it easy to read and understand. If you don't care to understand it then just upload and go. Make sure you have the Adafruit_NeoPixel.h Library installed. You can follow and contribut to any updates via this GitHub Link

led_panel.ino

/*
Resposive LED Panels
This sketch controls Interactive LED panels designed by Rodney Trusty
Instagram: @Rodneytrusty
Created September 18, 2019
by Rodney Trusty
*/
#include<Adafruit_NeoPixel.h>
/*Set Defines for Row and Column control pins*/
#defineROW_18
#defineROW_210
#defineROW_311
#defineROW_412
#defineNUM_ROWS4//Number of rows in IR array
#defineCOLUMN_12
#defineCOLUMN_23
#defineCOLUMN_34
#defineCOLUMN_45
#defineNUM_COLUMNS4//Number of columns in IR array
/*Defines for Analog read pins*/
#defineREAD_1 A0
#defineREAD_2 A1
#defineREAD_3 A2
#defineREAD_4 A3
#defineNUM_READ4//Number of analog reads in IR array
#defineLED_SIGNAL9//Addressable LED Signal Pin
#defineNUM_PIXELS (NUM_ROWS * NUM_COLUMNS)
#defineLED_BRIGHTNESS20
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, LED_SIGNAL, NEO_GRB + NEO_KHZ800);
byte red = 80;
byte green = 255;
byte blue = 125;
byte rows[8] = {ROW_1, ROW_2, ROW_3, ROW_4};
byte columns[8] = {COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4};
byte readVal[8] = {READ_1, READ_2, READ_3, READ_4};
short value_with_ir = 0;
short value_difference = 0;
short calibration_values[16] = {0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0};
unsignedshort threshold = 60; //Threshold to activate LEDs. Lower value = more sensitivity
byte pixel_num = 0;
voidsetup(){
Serial.begin(9600); //Set up Serial for debugging
pinMode(LED_SIGNAL, OUTPUT); //Set LED Signal pin to output.
//This pin controls the addressable LEDs
for(byte x = 0; x < NUM_ROWS; x++) //Set Row pins to output
{
pinMode(rows[x], OUTPUT);
}
for(byte x = 0; x < NUM_COLUMNS; x++) //Set Column pins to output
{
pinMode(columns[x], OUTPUT);
}
for(byte x = 0; x < NUM_READ; x++) //Set Analog Read pins Input
{
pinMode(readVal[x], INPUT);
}
strip.begin(); //Initialize Addressable LED library
strip.setBrightness(LED_BRIGHTNESS); //Set Addressable LED Brightness
strip.show(); //Initialize all Pixels to off
ir_calibrate(); //Calibrate IR Sensors
//Make sure no objects are present during calibration
}
voidloop(){
for(byte x = 0; x < NUM_COLUMNS ; x++) //Begin Loop through Columns
{
digitalWrite(columns[x], HIGH); //Set current Column pin HIGH
for(byte y = 0; y < NUM_ROWS; y++) //Begin Loop through Rows
{
digitalWrite(rows[y], HIGH); //Set Current Row HIGH
delayMicroseconds(100); //Mandatory Delay
value_with_ir = analogRead(readVal[y]); //Read analog value of IR Detector "WITH" IR Emitter
digitalWrite(rows[y], LOW); //Set Current Row LOW
pixel_num = (x*NUM_COLUMNS)+(NUM_ROWS - (y+1)); //Calculate the corresponding LED
if(value_with_ir > calibration_values[pixel_num])
{
value_difference = value_with_ir - calibration_values[pixel_num];
}
else{
value_difference = 0;
}
if(value_difference > threshold)
{
//Change the values of red, green and blue as you wish anywhere in the program for cool effects
strip.setPixelColor(pixel_num,red, green, blue); //Turn ON the corresponding LED
}
else{
strip.setPixelColor(pixel_num,0,0,0); //Turn OFF the corresponding LED
}
}
digitalWrite(columns[x], LOW); //Turn OFF Current ROW
}
strip.show(); //Display Changes made to addressable LEDs
}
voidir_calibrate(void)
{
short ir_averages[NUM_PIXELS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for(byte h = 0; h < 10; h++)
{
for(byte i = 0; i < NUM_COLUMNS; i++)
{
digitalWrite(columns[i], HIGH); //Set current Column pin HIGH
for(byte j = 0; j < NUM_ROWS; j++)
{
digitalWrite(rows[j], HIGH); //Set current Row HIGH
delayMicroseconds(100); //Mandatory Delay
value_with_ir = analogRead(readVal[j]); //Read analog value of IR Detector "WITH" IR Emitter
digitalWrite(rows[j], LOW); //Set current Row LOW
pixel_num = (i*NUM_COLUMNS)+(NUM_ROWS - (j+1)); //Calculate the corresponding LED number
ir_averages[pixel_num] += value_with_ir; //Add read value to total for position
}
}
for(byte m = 0; m < NUM_PIXELS; m++){
calibration_values[m] = (ir_averages[m]/10); //take average of accumulated detector reads
}
}
}
view rawled_panel.ino hosted with ❤ by GitHub

Step 5: Why the Custom PCB Is Worth It

These pictures show the insane amount of soldering I had to do before I developed the custom PCB. As you can see, building these without the PCB is tedious and time consuming.