13∙ Skin Electronics¶
05th to 12 december 2023
Update
- march 2024
- may 2024
Assignments
- Document the concept, sketches, references also to artistic and scientific publications
- Design a skin circuit:
- Build your own version of the “Skin masquerade party” project or
- Build your own version of the “Twinkle Nails” project
- Document the project and included all source files and all materials used
- Make a video with your skin electronic working
- Make a performance of your project functioning
Ressources of the week
About this week¶
Matrix bracelet to generate patterns
For this week I made it one year later and had the super chance to make it with Marion Guillaud. I was super excited to met her universe. Some part of this documentation will be the same to her.
This week was all about electronics and the skin as interface. Katia Vega, an Associate Professor of Design in California, gave us a very interesting lecture. She invited us to revisit the notion of skin and to think of the body in a different way... like an interface with electronics.
A large part of the research done for this week is largely oriented towards the scientific field like medical, biology or work with bacteria. It was not easy for us to make the link with textiles and fashion.
Marion said so much well about the meeting of our mind during this week: "We both had ideas as farfetched as the other.😆"
References & Inspiration¶
We initially found mostly scientific, medical and biological references, like:
The work of Professors J. Rogers and Y. Huang on health technologies, focused on the search for an ultra-thin health monitor that sticks to the skin, can accompany you everywhere and transmit information to the relevant doctor for regular follow-up. But what about traceability and data transmission?
Like Louise Masssacrier made for her week, we were very interested by the MIT project and their temporary tattoos.
The work of this Australian research laboratory is just as interesting in terms of the use of electronics on the skin as a sensor and data receiver in the prevention of skin cancer.
We also found other informations in alumni works and projects to help us with our assignments:
-
Marion Banon and her matrix
-
Margret Guttormmsdottir and her beautiful final project Moving shapes
-
Jessica Stanley and her skin touch sensor.
Aswell the work of Eldy Lazaro, alumna Fabricademy 2017. Working with electronics and mycomaterials.
Process and workflow¶
First of all, we tested some circuits to understand how it's work with an Attiny and Arduino. We followed the circuit model presented by Emma Pareschi in her tutorial. Then we tested it with the matrix.
Slide 15
ATtiny¶
Materials:
- 5 crocodiles clips
- 5 male male jumpers
- 1 arduino UNO
- 1 USB cable
- 1 Attinyv85
- 1 Electrolytic Capacitor
Software
- Arduino
- Processing
Before testing with the Attiny, it's necessary to prepare the Arduino for being the programmer.
We followed the link of Instructables Website to program the Arduino.
Code example¶
/*Emma Pareschi - Fabricademy 2023
* I turn on a led and I turn it off
* The Led is connected to pin 3
*/
int led_pin = 3; //define the pin where the Led is connected
void setup() {
pinMode(led_pin, OUTPUT); //define pin of the Led as an output
//pinMode(pin, OUTPUT);
//pinMode(pin, INPUT);
//pinMode(pin, INPUT_PULLUP);
}
void loop() {
//turn the Led on
//analogWrite(pin, 0/255);d
digitalWrite(led_pin, HIGH);
delay(500);
digitalWrite(led_pin, LOW);
delay(500);
}
Result¶
Matrix¶
Then we tested the matrix with a piezoresistive pressure sensor, the 3x3 paper matrix made with paper, copper tape and velostat.
Material:
- 6 crocodiles clips
- 6 male male jumpers
- 1 arduino UNO
- 1 USB cable
- 1 3x3 paper matrix
Software
- Arduino
- Processing
Code example with Arduino¶
//Emma Pareschi- Dec 2020
//Modify example from Pressure Sensor Matrix Code
//parsing through a pressure sensor matrix grid by switching individual
//rows/columns to be HIGH, LOW or INPUT (high impedance) to detect
//location and pressure.
//>> https://www.kobakant.at/DIY/?p=7443
#define numRows 3
#define numCols 2
#define sensorPoints numRows*numCols
int rows[] = {A0, A1};
int cols[] = {5,6,7};
int incomingValues[sensorPoints] = {};
void setup() {
// set all rows and columns to INPUT (high impedance):
for (int i = 0; i < numRows; i++) {
pinMode(rows[i], INPUT_PULLUP);
}
for (int i = 0; i < numCols; i++) {
pinMode(cols[i], INPUT);
}
Serial.begin(9600);
}
void loop() {
for (int colCount = 0; colCount < numCols; colCount++) {
pinMode(cols[colCount], OUTPUT); // set as OUTPUT
digitalWrite(cols[colCount], LOW); // set LOW
for (int rowCount = 0; rowCount < numRows; rowCount++) {
incomingValues[colCount * numRows + rowCount] = analogRead(rows[rowCount]); // read INPUT
}// end rowCount
pinMode(cols[colCount], INPUT); // set back to INPUT!
}// end colCount
// Print the incoming values of the grid:
for (int i = 0; i < sensorPoints; i++) {
Serial.print(incomingValues[i]);
if (i < (sensorPoints-1)) {
Serial.print("\t");
}
}
Serial.println();
delay(10);
}
[ Explanations of how piezoresistive sensor works, Screenshot form Kobakant website
Skin Electronics project¶
The main idea is to reuse the pattern machine that Marion created during her week 10. Creating patterns by interactions with the body matrix using a piezoresistive material like Velostat. Diane also tells us about Jessica Stanley's assignments of this week.
Screenshot form Jessica Stanley's assignments
And we found more inspirations with the Kobakant project: Pressure Matrix code + circuit and the Stretchy touchpad
Materials & tools¶
Material | Details |
---|---|
Machine | laser cutter, Brother KH950 knitting machine, pattern machine |
Tools | Velostat,Conductive thread, thread, crocodiles clips, arduino UNO, USB cable, printing pastes and tools |
Software | Illustrator, Arduino, Processing |
Fabrication files | Pattern1 laser cutting, Pattern2 laser cutting, Pattern3 laser cutting |
Process¶
First, we wanted to test it with pieces of silicone left over from my week 9 failed tests, with the idea that it would adhere better to the skin, in a 3x3 version.
But we realized that the copper tape didn't hold despite the glue. The velostat didn't connect properly when pressed between the two layers of silicone.
Then, we did a test to knit a bracelet with connected yarn, like the paper matrix.
The Knitting machine¶
The use of this machine is not in the objectives of the week. But always fun to use it.
Piece 1
21 stitches in stockinette
40 rows in Tension 5 normal color thread
4 rows in Tension 2 conductive thread
6 rows in Tension 5 normal color thread
4 rows in Tension 2 conductive thread
6 in Tension 5 normal color thread
4 rows in Tension 2 conductive thread
Piece 2
4 rows in Tension 2, conductive thread
6 in Tension 5 normal color thread
4 rows in Tension 2 conductive thread
6 in Tension 5 normal color thread
4 rows in Tension 2 conductive thread
Knitting test¶
On the left: Piece 1, on the right: Piece 2
Generative patterns and Processing¶
One of the lines knitted accidentetly with the conductive thread was cut.
We modified our code by notifying the number of rows: only 2 instead of 3.
Circle Code example¶
This is the first code we used to having circles.
//Emma Pareschi- Dec 2020
//Modify example from Pressure Sensor Matrix Code
//parsing through a pressure sensor matrix grid by switching individual
//rows/columns to be HIGH, LOW or INPUT (high impedance) to detect
//location and pressure.
//>> https://www.kobakant.at/DIY/?p=7443
#define numRows 2
#define numCols 3
#define sensorPoints numRows*numCols
int rows[] = {A0, A1};
int cols[] = {5,6,7};
int incomingValues[sensorPoints] = {};
void setup() {
// set all rows and columns to INPUT (high impedance):
for (int i = 0; i < numRows; i++) {
pinMode(rows[i], INPUT_PULLUP);
}
for (int i = 0; i < numCols; i++) {
pinMode(cols[i], INPUT);
}
Serial.begin(9600);
}
void loop() {
for (int colCount = 0; colCount < numCols; colCount++) {
pinMode(cols[colCount], OUTPUT); // set as OUTPUT
digitalWrite(cols[colCount], LOW); // set LOW
for (int rowCount = 0; rowCount < numRows; rowCount++) {
incomingValues[colCount * numRows + rowCount] = analogRead(rows[rowCount]); // read INPUT
}// end rowCount
pinMode(cols[colCount], INPUT); // set back to INPUT!
}// end colCount
// Print the incoming values of the grid:
for (int i = 0; i < sensorPoints; i++) {
Serial.print(incomingValues[i]);
if (i < (sensorPoints-1)) {
Serial.print("\t");
}
}
Serial.println();
delay(10);
}
Result¶
The circle pattern
Ellipse and cross code example¶
We also tested to have cross and ellipse at the same time.
/*
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/
Working with a matrix
*/
String myString = null;
String inString = null;
int lf = 10; // Linefeed in ASCII
Serial myPort; // The serial port
int rows = 2;
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 ellipseSize = 0;
int ellipseX;
void setup () {
size(800, 800); // set up the window to whatever size you want
ellipseSize = width/rows;
//println(Serial.list()); // List all the available serial ports
String portName = Serial.list()[0]; // 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(0, 0, 255); // set inital background
smooth(); // turn on antialiasing
ellipseMode(CENTER); //define the position of the ellipse from its center
//ellipseMode(CORNER); //define the position of the ellipse from its corner
}
void draw () {
background(255);
for (int i = 0; i < maxNumberOfSensors; i++) {
fill(sensorValue[i]-28, sensorValue[i]-28, sensorValue[i]-28); //Define first colour of the ellipse
ellipse(ellipseX + ellipseSize/2, ellipseSize*(i%rows)+ellipseSize/2, ellipseSize*sensorValue[i]/255, ellipseSize*sensorValue[i]/255);
push();
translate(ellipseX + ellipseSize/2, ellipseSize*(i%rows)+ellipseSize/2);
float d = ellipseSize*(1-sensorValue[i]/255)/2;
line(-d, -d, d, d);
line(d, -d, -d, d);
pop();
if ((i+1) % rows == 0) ellipseX += ellipseSize;
}
ellipseX=0;
}
void serialEvent (Serial myPort) {
inString = myPort.readStringUntil(lf); // get the ASCII string
println("test");
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], 0, 1023, 0, 255); // stretch 5×5, because sensor value = 255 at rest (without pressure)
//incomingValue decreases with pressure because it is the resistance
sensorValue[i] = constrain(incomingValues[i], 0, 255); // stretch 5×5
println(sensorValue[i]); // print value to see
}
}
}
}
Result¶
Final Cross code example¶
As we also wanted to try and generate a pattern with different cross sizes in each square, I reviewed the Processing code with the help to Marion husband (The Processing guy!).
Code for processing
/*
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/
Working with a matrix
*/
String myString = null;
String inString = null;
int lf = 10; // Linefeed in ASCII
Serial myPort; // The serial port
int rows = 2;
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[] mins = new int[maxNumberOfSensors];
int[] maxs = new int[maxNumberOfSensors];
float[] Ns = new float[maxNumberOfSensors];
float ellipseSize = 0;
void setup () {
size(1200, 800); // set up the window to whatever size you want
ellipseSize = float(width)/float(cols);
//println(Serial.list()); // List all the available serial ports
String portName = Serial.list()[0]; // 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(0, 0, 255); // set inital background
smooth(); // turn on antialiasing
for(int i = 0; i < maxNumberOfSensors; i++) {
mins[i] = 1023;
maxs[i] = 0;
Ns[i] = random(3, 20);
}
}
void draw () {
background(255);
for (int i = 0; i < maxNumberOfSensors; i++) {
float X = (i % cols) * ellipseSize;
float Y = (i / cols) * ellipseSize;
//stroke(sensorValue[i]-28, sensorValue[i]-28, sensorValue[i]-28); //Define first colour of the ellipse
push();
translate(X, Y);
float N = Ns[i];
float d = ellipseSize/N * (sensorValue[i]/255.)/2.;
for(int y = 0; y < N; y ++) {
for(int x = 0; x < N; x ++) {
push();
translate(ellipseSize/Nfloat(x) + ellipseSize/2./N, ellipseSize/Nfloat(y) + ellipseSize/2./N);
//strokeWeight(1);
//rect(-ellipseSize/N/2.,-ellipseSize/N/2., ellipseSize/N, ellipseSize/N);
strokeWeight(map(d, 0, ellipseSize/N, 0, 30));
line(-d, -d, d, d);
line(d, -d, -d, d);
pop();
}
}
pop();
}
}
void serialEvent (Serial myPort) {
inString = myPort.readStringUntil(lf); // get the ASCII string
//println("test");
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):
if(incomingValues[i] > maxs[i]) maxs[i] = incomingValues[i];
if(incomingValues[i] < mins[i]) mins[i] = incomingValues[i];
sensorValue[i] = map(incomingValues[i], mins[i], maxs[i], 0, 255); // stretch 5×5, because sensor value = 255 at rest (without pressure)
//incomingValue decreases with pressure because it is the resistance
sensorValue[i] = constrain(incomingValues[i], 0, 255); // stretch 5×5
println(sensorValue[i]); // print value to see
}
}
}
}
Code for Arduino
//Emma Pareschi- Dec 2020
//Modify example from Pressure Sensor Matrix Code
//parsing through a pressure sensor matrix grid by switching individual
//rows/columns to be HIGH, LOW or INPUT (high impedance) to detect
//location and pressure.
//>> https://www.kobakant.at/DIY/?p=7443
#define numRows 2
#define numCols 3
#define sensorPoints numRows*numCols
int rows[] = {A0,A1};
int cols[] = {5,6,7};
int incomingValues[sensorPoints] = {};
void setup() {
// set all rows and columns to INPUT (high impedance):
for (int i = 0; i < numRows; i++) {
pinMode(rows[i], INPUT_PULLUP);
}
for (int i = 0; i < numCols; i++) {
pinMode(cols[i], INPUT);
}
Serial.begin(9600);
}
void loop() {
for (int colCount = 0; colCount < numCols; colCount++) {
pinMode(cols[colCount], OUTPUT); // set as OUTPUT
digitalWrite(cols[colCount], LOW); // set LOW
for (int rowCount = 0; rowCount < numRows; rowCount++) {
incomingValues[colCount * numRows + rowCount] = analogRead(rows[rowCount]); // read INPUT
}// end rowCount
pinMode(cols[colCount], INPUT); // set back to INPUT!
}// end colCount
// Print the incoming values of the grid:
for (int i = 0; i < sensorPoints; i++) {
Serial.print(incomingValues[i]);
if (i < (sensorPoints-1)) {
Serial.print("\t");}
// Serial.println("");}
}
Serial.println();
delay(10);
}
Results¶
But there seems to be a problem, perhaps in my code or in the formatting of the two knitting pieces. The starting grid already has patterns, whereas these should appear when the two fibers make contact with the velostat when it's pressed.
We chose to test one of the patterns generated by the bracelet with the cut-out.
Processing view
We used Illustrator for making vectorization, for preparing the file for the laser cutter. Be carefull to be in SVG file.
Laser cutting
Power | Speed |
---|---|
95 | 40 |
More info here
Printing paste
We tried the one with the "best" cut with printing pastes that Marion made for week 10.
Feeling it's a new dialog, story of language.