MotivationWhat to do you do when you have some Bare Conductive paint and some Philips Hue lightbulbs laying around? You paint a dimmer switch on your wall using conductive paint!
Getting StartedSome things you'll need to get started:
- Arduino Due (or Zero)
- AnduinoWiFi shield (or another WiFi101 enabled Arduino)
The Bare Conductive Touch Board actually contains an Arduino compatible MCU (the ATmega32u4), so although it's stacked like a shield we're actually using two different Arduino boards which communicate over serial UART with each other. There's a touch interface sketch running on the touch board, and then the hueDino Philips Hue API client runs on the anduinoWiFi Due. Eventually this could all be condensed in size to run on a MKR1000 and a MPR121 breakout if size were a concern.
The touch Board is essentially an Arduino Leonardo with an onboard MPR121 capacitive touch sensor, SD card reader, and mp3 player with 1/8" audio out.
You can test out a whole bunch of different painted circuits and touch interfaces using just the touch board. But when it comes time to internet connect your new interface slapping a WiFi shield on the ATmega32u4 isn't quite going to cut it. B.C. also makes a touch interface board for the Raspberry Pi which helps make it a bit easier to internet connect your conductive paint designs.
Since the touch board can't support WiFi this is why we've introduced the second Arduino Due paired with the anduinoWiFi This can now handle the Hue API communication between our Arduino and the local Philips Hue Bridge (which in turn controls the lights). It listens on a serial port for dimmer switch values sent by the touch board.
Let's get things connected up!
Soldering and WiringStep 1To connect the three main components I've soldered a stackable header to the power pins of the B.C. touch board. After removing the LCD screen from the anduinoWiFi shield (just spin off the nylon stand offs and pull up) you can stack it right on top. I've also soldered headers for the touch electrodes and for pins 10 and 11 which we'll use for the Software Serial comms between the touch board and the Arduino Due.
Once you've soldered the headers stack the touch board on top of the anduinoWiFi shield. Before stacking the shields on to the Due plug two wires into pins 18 and 19 Tx1 and Rx1. Either bend the pins or use a 90* degree header so the shield can still rest on top. At this point your boards should look like this:
Lastly it's time to wire up the logic level converter. Since the touch board MCU operates at 5v and the Due at 3.3v we'll need to use a logic level converter to safely UART between the two devices.
Just connect 5v and GND to HV and GND as well as 3.3v to LV and GND on the opposite side. Then use any of the pass through pins HV1 <--> LV1, HV2<-->LV2, etc. Connect Rx and Tx (pins 10 and 11) from the touch board to HV1 and HV2, and Rx1 to LV2 and Tx1 to LV1 from the Due. 3.3v logic on the L side 5v logic on the H side.
Step 5Double check your wiring to make sure you've crossed your Tx <--> Rx connections. Tx on the touch board goes to RX on the Due and vice versa.
For the first prototype I grabbed a sheet of card stock and painted on 6 different traces. Then using some tape and a dab of paint I cold soldered some jumper wires to the ends of the traces. This way you can plug those wires directly into the header that we soldered to the touch board's electrode pins.
Now just connect each trace from top to bottom into electrodes 0 - 5 respectively. After flashing the two sketches you should be ready to test! Speaking of sketches, let's check out the code!
The CodeSo how does it all work? Well, here's the source code! In order for everything to work you'll need a few libraries to be installed first.
Sketch for Touch BoardThis sketch gets flashed to the Bare Conductive touch board.
#include <MPR121.h>
#include <Wire.h>
#define MPR121_ADDR 0x5C
#define MPR121_INT 4
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup(){
Serial.begin(115200);
mySerial.begin(115200);
Wire.begin();
if(!MPR121.begin(MPR121_ADDR)){
Serial.println("error setting up MPR121");
switch(MPR121.getError()){
case NO_ERROR:
Serial.println("no error");
break;
case ADDRESS_UNKNOWN:
Serial.println("incorrect address");
break;
case READBACK_FAIL:
Serial.println("readback failure");
break;
case OVERCURRENT_FLAG:
Serial.println("overcurrent on REXT pin");
break;
case OUT_OF_RANGE:
Serial.println("electrode out of range");
break;
case NOT_INITED:
Serial.println("not initialised");
break;
default:
Serial.println("unknown error");
break;
}
while(1);
}
MPR121.setInterruptPin(MPR121_INT);
MPR121.setTouchThreshold(40); // lower numbers make the board more sensitive
MPR121.setReleaseThreshold(20); // make sure that the release threshold is always
// lower than the touch threshold
MPR121.updateAll();
}
void loop(){
if(MPR121.touchStatusChanged()){
// update our touch data to ensure it is valid
MPR121.updateTouchData();
// run through all electrodes
for(int i=0; i<=5; i++){
if(MPR121.isNewTouch(i)){
// if we have a new touch on this electrode...
digitalWrite(LED_BUILTIN, HIGH);
//Keyboard.press(keyMap[i]);
Serial.print("Brightness: ");
Serial.println(i);
char val=5;
itoa(i, &val, 10);
mySerial.write(val);
}
}
}
}
Sketch for WiFiThis sketch gets flashed to the WiFi enabled Arduino, in this case our Arduino Due with anduinoWiFi shield.
#include "hueDino.h"
#define hueUser "" //ex: "Ur80SKqRKO0ojlFInzdjAZEHy0kjYWznakufY60m"
#define lightId 5
char ssid[] = ""; // your network SSID (name)
char pass[] = ""; // your network password
char hueBridge[] = ""; // hue bridge ip address ex: "192.168.1.3"
WiFiClient wifi;
hueDino hue = hueDino(wifi, hueBridge);
int level = 0;
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
connectToWiFi();
//Start Hue
hue.begin(hueUser);
/*Uncomment the section below if you're unsure of the ID of the
*light you'd like to control
*
*/
/*//Query bridge for available lights
Serial.println(hue.getLightIds()); //most hueDino methods return strings containing the raw json responses
//just encapsulate your function calls inside Serial.print statements to
Serial.println(); //to print them to the screen
Serial.print("hueDino found: ");
Serial.print(hue.numLights);
Serial.println(" connected lights");
Serial.println();
Serial.println("Available Light IDs: ");
for(int i=0; i<hue.numLights; i++)
{
Serial.print(hue.lightIds[i]);
Serial.print(",");
}*/
/*Available attributes/states
*on,off,brightness,hue,saturation,colorTemp,colorLoop,alert,flash
*reference: https://developers.meethue.com/documentation/lights-api
*settings are persistent and will not revert after sketch has run
*/
//On - make surethe light's are on before we try to dimm
hue.lightOn(lightId);
delay(200);
}
void loop() {
if (Serial1.available()) { // If anything comes in Serial1 (pins 0 & 1)
level = Serial1.read();
Serial.println(level);
switch (level) {
case 48: //48 is actually char '0' in dec '1' = 49..other than increased
//readability interpreting these as chars didn't make sense
hue.brightness(lightId, 250);
break;
case 49:
hue.brightness(lightId, 200);
break;
case 50:
hue.brightness(lightId, 150);
break;
case 51:
hue.brightness(lightId, 100);
break;
case 52:
hue.brightness(lightId, 50);
break;
case 53:
hue.brightness(lightId, 1);
break;
default:
hue.alert(lightId, "lselect");
break;
}
}
}
void connectToWiFi()
{
int status = WL_IDLE_STATUS;
while(status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid); // print the network name (SSID);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
}
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
}
Here's the critical piece! If we receive a touch on any of the dimmer switch painted lines:
if(MPR121.isNewTouch(i)){
// if we have a new touch on this electrode...
digitalWrite(LED_BUILTIN, HIGH);
//Keyboard.press(keyMap[i]);
Serial.print("Brightness: ");
Serial.println(i);
char val=5;
itoa(i, &val, 10);
mySerial.write(val);
}
We send a value (0 - 5) over serial to the Arduino Due so it can follow the logic in this switch statement:
switch (level) {
case 48: //48 is actually char '0' in dec '1' = 49..other than increased
//readability interpreting these as chars didn't make sense
hue.brightness(lightId, 250);
break;
case 49:
hue.brightness(lightId, 200);
break;
case 50:
hue.brightness(lightId, 150);
break;
case 51:
hue.brightness(lightId, 100);
break;
case 52:
hue.brightness(lightId, 50);
break;
case 53:
hue.brightness(lightId, 1);
break;
default:
hue.alert(lightId, "lselect");
break;
}
Then depending on which line is touched we send a message to the Philips Hue Bridge indicating that this "lightId" should be set to a specific brightness (1-254).
If you'd like to use this sketch to adjust a group of lights just substitute each
hue.brightness(lightId, 50);
for an...
hue.groupBrightness(groupId, 50);
and be sure to define the correct groupId at the top of the sketch.
That's it!You now have everything you need to start painting your own dimmer switches where ever you see fit! Here are couple quick clips of the switch in action.
Here's the first prototype painted on card stock:
Our dimmer switch we painted on the wall in the office!
These capacitance sensors are great at detecting touch, but they're also capable of detecting proximity! It requires a slightly different painted shape, but in doing so you could adjust the brightness or color of your lights just by waving your hand near the "switch". Stay tuned for a new post with this type of control!
Comments