12. Skin Electronics¶
Research and Inspiration¶
1. NeoTouch - Conceptual idea of touch from far
The Interactive Architecture Lab (The Bartlett, UCL). 2018 Link
2. Power-over-Skin: Full-Body Wearables Powered By Intra-Body RF Energy
Research Team: Andy Kong, Daehwa Kim, Chris Link
3. Simple sewing machine has high-tech role in future 'soft' machines
Matrix¶
A matrix sensor is a grid that lets you read many sensing points using only a small number of wires by combining rows and columns.
I created my Matrix using paper, copper tape, and velostat.
The board used was a Xiao ESP23-S3 on a FabriXiao board
Here is how i attached the Matrix to the board.
I then uploaded the code from Emma Pareschi´s tutorial
int row0 = A0; //first row pin
int row1 = A1; //second row pin
int row2 = A2; //third row pin
int col0 = D7; //first column pin
int col1 = D8; //second column pin
int col2 = D9; //third column pin
int incomingValue0 = 0; //variable to save the sensor reading
int incomingValue1 = 0; //variable to save the sensor reading
int incomingValue2 = 0; //variable to save the sensor reading
int incomingValue3 = 0; //variable to save the sensor reading
int incomingValue4 = 0; //variable to save the sensor reading
int incomingValue5 = 0; //variable to save the sensor reading
int incomingValue6 = 0; //variable to save the sensor reading
int incomingValue7 = 0; //variable to save the sensor reading
int incomingValue8 = 0; //variable to save the sensor reading
void setup() {
// set all rows to INPUT (high impedance):
pinMode(row0, INPUT_PULLUP);
pinMode(row1, INPUT_PULLUP);
pinMode(row2, INPUT_PULLUP);
//set the firt column as output
pinMode(col0, OUTPUT);
pinMode(col1, OUTPUT);
pinMode(col2, OUTPUT);
//open serial communication
Serial.begin(9600);
}
void loop() {
// FIRST BLOCK OF READINGS----------------------------
//set the col0 to low (GND)
digitalWrite(col0, LOW);
digitalWrite(col1, HIGH);
digitalWrite(col2, HIGH);
//read the three rows pins
incomingValue0 = analogRead(row0);
incomingValue1 = analogRead(row1);
incomingValue2 = analogRead(row2);
// --------------------------------------------------
//set the col1 to low (GND)
digitalWrite(col0, HIGH);
digitalWrite(col1, LOW);
digitalWrite(col2, HIGH);
incomingValue3 = analogRead(row0);
incomingValue4 = analogRead(row1);
incomingValue5 = analogRead(row2);
//set the col2 to low (GND)
digitalWrite(col0, HIGH);
digitalWrite(col1, HIGH);
digitalWrite(col2, LOW);
incomingValue6 = analogRead(row0);
incomingValue7 = analogRead(row1);
incomingValue8 = analogRead(row2);
// Print the incoming values of the grid:
Serial.print(incomingValue0);
Serial.print("\t");
Serial.print(incomingValue1);
Serial.print("\t");
Serial.print(incomingValue2);
Serial.print("\t");
Serial.print(incomingValue3);
Serial.print("\t");
Serial.print(incomingValue4);
Serial.print("\t");
Serial.print(incomingValue5);
Serial.print("\t");
Serial.print(incomingValue6);
Serial.print("\t");
Serial.print(incomingValue7);
Serial.print("\t");
Serial.println(incomingValue8);
delay(10); //wait millisecond
}
To visualize the result of the Matrix pressure sensor we used Processing (another code generator for visualization of code)
This was the code I used in Processing and visualizing the Matrix
/*
The sensors values are not calibrated.
*/
/*
Code based on Tom Igoe’s Serial Graphing Sketch
>> http://wiki.processing.org/w/Tom_Igoe_Interview
Reads X analog inputs and visualizes them by drawing a grid
using grayscale shading of each square to represent sensor value.
>> http://howtogetwhatyouwant.at/
*/
import processing.serial.*;
Serial myPort; // The serial port
int rows = 3;
int cols = 3;
int maxNumberOfSensors = rows*cols;
float[] sensorValue = new float[maxNumberOfSensors]; // global variable for storing mapped sensor values
float[] previousValue = new float[maxNumberOfSensors]; // array of previous values
int rectSizeX = 0;
int rectSizeY = 0;
int rectY;
void setup () {
size(1000, 1000); // set up the window to whatever size you want
rectSizeX = width/rows;
rectSizeY = height/cols;
println(Serial.list()); // List all the available serial ports
String portName = Serial.list()[7]; // set the number of your serial port!
myPort = new Serial(this, portName, 9600);
myPort.clear();
myPort.bufferUntil('\n'); // don’t generate a serialEvent() until you get a newline (\n) byte
background(255); // set inital background
smooth(); // turn on antialiasing
rectMode(CORNER);
}
void draw () {
for (int i = 0; i < maxNumberOfSensors; i++) {
fill(sensorValue[i]);
rect(rectSizeX * (i%rows), rectY, rectSizeX, rectSizeY); //top left
if((i+1) % rows == 0) {
rectY += rectSizeX;
}
}
rectY=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // get the ASCII string
if (inString != null) { // if it’s not empty
inString = trim(inString); // trim off any whitespace
int incomingValues[] = int(split(inString, "\t")); // convert to an array of ints
if (incomingValues.length <= maxNumberOfSensors && incomingValues.length > 0) {
for (int i = 0; i < incomingValues.length; i++) {
// map the incoming values (0 to 1023) to an appropriate gray-scale range (0-255):
sensorValue[i] = map(incomingValues[i], 000, 900, 0, 255); // stretch 5×5
sensorValue[i] = constrain(incomingValues[i], 0, 255);
//println(sensorValue[i]); // print value to see
//println(incomingValues[i]);
}
}
}
}
Here is a video of the result
Capacitive Sensors¶
A capacitive sensor senses touch or closeness by measuring tiny changes in electrical charge.
For my Skin cicuit i wanted to exoeriment with making a two touch capacitive sensor with two different outputs.
To make a demo I used a Arduiono Uno and breadboard to make the circuit.
Video of the Capacitive demo
I got familiar with the serial monitor and how to read and understand the numbers and the conversions to LED lights.
I read the motors max and minimums and convert them in the code to LED values from 0 - 255
Here is the code I used
#define TOUCH_PIN D1
#define TOUCH_PIN2 D4
// PWM-capable pins (on Arduino Uno: 3,5,6,9,10,11)
int led1_pin = 8; // changed from 9 to 8 (9 on the board but 8 here)
int led2_pin = 9; // CHANGED from 10 to 9 pins are weird
// ranges you gave:
// total1: 60–22100
// total2: 150–23200
void setup() {
Serial.begin(9600);
pinMode(led1_pin, OUTPUT);
pinMode(led2_pin, OUTPUT);
}
void loop() {
int touchValue = touchRead(TOUCH_PIN);
int touchValue2 = touchRead(TOUCH_PIN2);
// Print raw sensor values for debugging
Serial.print("S1: ");
Serial.print(touchValue);
Serial.print(" S2: ");
Serial.println(touchValue2);
// --- Map sensor 1 to LED 1 brightness ---
// Map 60–22100 to 0–255
long led1_brightness = map(touchValue, 52000, 80000, 0, 255);
// Make sure we stay in 0–255 even if readings go out of range
led1_brightness = constrain(led1_brightness, 0, 255);
// --- Map sensor 2 to LED 2 brightness ---
// Map 150–23200 to 0–255
long led2_brightness = map(touchValue2, 52000, 80000, 0, 255);
led2_brightness = constrain(led2_brightness, 0, 255);
// Write brightness (must cast to int for analogWrite)
analogWrite(led1_pin, (int)led1_brightness);
analogWrite(led2_pin, (int)led2_brightness);
delay(10); // small delay to stabilize readings
}
Skin Circuit¶
For my skin circuit I wanted to continue on the two touch Capacitive Sensor. Instead Of using ArdiunoUno I switched over to FabriXiao and adapted the input and output pins in the code. I also changed the LEDS to NEOPIXELS
I used illustrator to design the touch sensors and cut them out with a Cricut vinyl cutter
The wires were soldered onto all parts of the circuit.
Materials¶
Board - FabriXiao - XiaoESP23-S3
Copperwire
Solderwire
Copper tape
Neo Pixels Link
Code¶
#include <Adafruit_NeoPixel.h>
#define LED_COUNT 3
#define TOUCH_PIN 5
#define TOUCH_PIN2 4
// PWM-capable pins (on Arduino Uno: 3,5,6,9,10,11)
int led1_pin = 7; // 7 is 8 on the board
int led2_pin = 6; // 6 ia 5 on board from 10 to 9 pins are weird
int BRIGHTNESS = 50;
// ranges you gave:
// total1: 60–22100
// total2: 150–23200
Adafruit_NeoPixel strip1(LED_COUNT, led1_pin, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(LED_COUNT, led2_pin, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(9600);
pinMode(led1_pin, OUTPUT);
pinMode(led2_pin, OUTPUT);
strip1.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip1.show(); // Turn OFF all pixels ASAP
strip1.setBrightness(BRIGHTNESS);
strip2.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip2.show(); // Turn OFF all pixels ASAP
strip2.setBrightness(BRIGHTNESS);
}
void loop() {
int touchValue = touchRead(TOUCH_PIN);
int touchValue2 = touchRead(TOUCH_PIN2);
// Print raw sensor values for debugging
Serial.print("S1: ");
Serial.print(touchValue);
Serial.print(" S2: ");
Serial.println(touchValue2);
// --- Map sensor 1 to LED 1 brightness ---
// Map 60–22100 to 0–255
long led1_brightness = map(touchValue, 42000, 120000, 0, 255);
// touchpin 4 on board and s1 in serial og D8
led1_brightness = constrain(led1_brightness, 0, 255);
// --- Map sensor 2 to LED 2 brightness ---
// Map 150–23200 to 0–255
long led2_brightness = map(touchValue2, 40000, 120000, 0, 255);
led2_brightness = constrain(led2_brightness, 0, 255);
// Touch oin 3 on board and S2 in serial D5
// Write brightness (must cast to int for analogWrite)
//analogWrite(led1_pin, (int)led1_brightness);
//analogWrite(led2_pin, (int)led2_brightness);
strip1.setBrightness (led1_brightness);
strip2.setBrightness(led2_brightness);
for(int i=0; i<3; i++) { // For each pixel in strip...
strip1.setPixelColor(i,0,255,0); // Set pixel's color (in RAM)
strip1.show(); // Update strip to match
delay(10); // Pause for a moment
}
for(int i=0; i<3; i++) { // For each pixel in strip...
strip2.setPixelColor(i, 255,0,0); // Set pixel's color (in RAM)
strip2.show(); // Update strip to match
delay(10); // Pause for a moment
}
delay(10); // small delay to stabilize readings
}
Design¶
To hide the NeoPixels I used lasercut flower looking elements. The touch sensors i place oppersite sides of the Neopixel they are lighting up. I played with the colors of the NeoPixels and have one side lighting green and one side red.






