13. Skin Electronics¶
Research, References & Inspiration¶
This week I took time to understand how the ATtiny worked, which is a module that can store the Arudino code in a smaller component then the arduino. I had hread many time how it could be intergrated into project but never fully understood how so that was the higlight from this week. After the great lecture from Katia Vega I remembered a lecture I attended in DesginTalk's during Design March in Iceland. It was a couple called Neil Harbisson & Moon Ribas and they are cyborgs. A cyborg is an organism with both artificial and organic components and that is how they allow themselves to sense there environment in new ways, by intergrating sensors into they're bodies. I thought is was interesting learning about skin electronics and see how they have taken it even further and have electronice become a part of themselves, not just an add-on.
Here are two videos about they're work.
This is a project from Embodiment Lab where they are using pressure sensor matrix to map out a surface in the computer. I have also looked at this for my personal project where pressure sensor could be a tool to map a dancers movement.
Refrences¶
Tools¶
- Arduino UNO starter kit
- Attiny 85
- Arduino software
- 3V battery and battery holder
- Multimeter
- Velostat
- Breadboard
- LED light
- Thins insulated wires
- Thin insulated copper
Process and workflow¶
First learned how to opperate and work with the ATtiny but for that we had to download new libraries to arduino to be able to clean the ATtiny from previous coding. Link to add to prefrences and paste it in the additional Board Manager URLs From there in libraries you can find Attiny by Davis A. Mellis and install it.
How to program Attiny¶
From Emma's lectur and Instructables 1. Connect the Attiny to your Programmer: - AVR programmer - Arduino UNO (make sure that the Arduino is uploaded with the ARduinoISP sketch) 2. In Arduino IDE: Select board (attiny85 (internal 8MHz)) and port 3. In Arduino IDE: Select programmer, Arduino as ISP or USBtinyISP 4. In Arduino IDE: If it is the first time YOU use the Attiny => Burn the bootloader 5. On Breadboard: connect the Attiny to your input/output devices 6. In Arduino IDE: Upload the code to the Attiny
ATtiny tutorial by Margrét Katrín Guttormsdóttir
Code 1¶
Led
/* Emma Pareschi, Nov 2019
*
* the led connected to pin 1. it blinks
*/
int led_pin = 1; //pin of the Led
void setup() {
// put your setup code here, to run once:
pinMode(led_pin, OUTPUT); // set the pin 1 as OUTPUT
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(led_pin, HIGH); //turn the Led ON
delay(1000); //wait
digitalWrite(led_pin, LOW); //turn the Led OFF
delay(1000); //wait
}
Code 2¶
/*
Emma Pareschi 2020
the Led turns on when the digital sensor is triggered
*/
// this constant won't change:
int sw_pin = 4; // the pin that the pushbutton is attached to
int led_pin = 1; //pin of the led
// Variables will change:
int sw_status = 0; // current state of the button
void setup() {
// initialize input and output pins:
pinMode(sw_pin, INPUT_PULLUP);
pinMode(led_pin, OUTPUT);
}
void loop() {
// read the pushbutton input pin:
sw_status = digitalRead(sw_pin);
// compare the switch status to its previous state
if (sw_status == LOW) { //if the sw is pressed
digitalWrite(led_pin, HIGH); //turn on the led (5V)
} else { //if the sw is not pressed
digitalWrite(led_pin, LOW); //turn off the Led (0V)
}
}
Pressure sensor matrix¶
Interactive matrix by Margrét Katrín Guttormsdóttir
Processing is a softaware that works with interacting with the matrix I made. I downloaded the software and to start with I found a code on How to get what you want webpage using processing as an output from the interaction with the matrix. more codes are available at the Processing wbsite. I also used Louises documentation, a fabricademy alumni. She has a great documenttation of the different coding you can change and where to do it.
Arduino code for matrix¶
This1 is to code the arduino to further work in processing.
/*
Matrix: Kapton + Copper
A simple pressure sensor matrix made from two Kapton film sheets with
7×7 copper tape traces and a piece of Velostat or Eeonyx piezoresistive
material in between.
parsing through this grid by switching individual rows/columns to be
HIGH, LOW or INPUT (high impedance) to detect location and pressure.
>> http://howtogetwhatyouwant.at/
*/
#define numRows 3
#define numCols 3
#define sensorPoints numRows*numCols
int rows[] = {A0, A1, A2};
int cols[] = {7,6,5};
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);
}
Processing code for matrix¶
This2 is the original code that I found on the kobakant page above. I worked on the code further, changed the shapes and color of the visuals, as you can see further down.
/*
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 rectSize = 0;
int rectY;
void setup () {
size(600, 600); // set up the window to whatever size you want
rectSize = width/rows;
println(Serial.list()); // List all the available serial ports
String portName = Serial.list()[1]; // 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(rectSize * (i%rows), rectY, rectSize, rectSize); //top left
if((i+1) % rows == 0) rectY += rectSize;
}
rectY=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // 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
println(sensorValue[i]); // print value to see
}
}
}
}
Change color¶
You can find the a RGB color you can find codes for different colors on this webpage To change color you have to add numbers ranging from 0-255 in this field: From this being gray colors:
fill(sensorValue[i]);
fill(70,sensorValue[i], 0);
Design by Margrét Katrín
The whole code for color changing from gray to green
/*
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 rectSize = 0;
int rectY;
void setup () {
size(600, 600); // set up the window to whatever size you want
rectSize = width/rows;
println(Serial.list()); // List all the available serial ports
String portName = Serial.list()[1]; // 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(70,sensorValue[i], 0);
rect(rectSize * (i%rows), rectY, rectSize, rectSize); //top left
if((i+1) % rows == 0) rectY += rectSize;
}
rectY=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // 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
println(sensorValue[i]); // print value to see
}
}
}
}
uncentered ellipse¶
Next I changed the form of the visuals from squares(rect) to circles(ellipse) changing every rect-something to ellipse-something.
Design by Margrét Katrín Guttormsdóttir
/*
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 ellipseSize = 0;
int ellipseX;
void setup () {
size(600, 600); // 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()[1]; // 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
ellipseMode(CORNER);
}
void draw () {
for (int i = 0; i < maxNumberOfSensors; i++) {
fill(70,sensorValue[i], 0);
//(rectSize * (i%rows), rectY, rectSize, rectSize); //top left
ellipse(ellipseX + ellipseSize/2, ellipseSize * (i%rows) + ellipseSize/2, ellipseSize*(1-sensorValue[i]/255), ellipseSize*(1-sensorValue[i]/255)); //top left
if((i+1) % rows == 0) ellipseX += ellipseSize;
}
ellipseX=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // 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
println(sensorValue[i]); // print value to see
}
}
}
}
Centered ellipse¶
The codee above as you can see change from the side of the corner but I wanted it to change from the middle. To change that I typed in (CENTER) instead of (CORNER) for the ellipseMode.
Design by Margrét Katrín Guttormsdóttir
ellipseMode(CORNER);
to
ellipseMode(CENTER);
/*
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 ellipseSize = 0;
int ellipseX;
void setup () {
size(600, 600); // 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()[1]; // 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
ellipseMode(CENTER);
}
void draw () {
for (int i = 0; i < maxNumberOfSensors; i++) {
fill(70,sensorValue[i], 0);
//(rectSize * (i%rows), rectY, rectSize, rectSize); //top left
ellipse(ellipseX + ellipseSize/2, ellipseSize * (i%rows) + ellipseSize/2, ellipseSize*(1-sensorValue[i]/255), ellipseSize*(1-sensorValue[i]/255)); //top left
if((i+1) % rows == 0) ellipseX += ellipseSize;
}
ellipseX=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // 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
println(sensorValue[i]); // print value to see
}
}
}
}
final code with different colors¶
After having tested out different colors and shapes I ened up finding colors that I liked for the final code3 as you can see below.
Design by Margrét Katrín Guttormsdóttir
/*
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 ellipseSize = 0;
int ellipseX;
void setup () {
size(600, 600); // 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()[1]; // 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(240,128,128); // set inital background
smooth(); // turn on antialiasing
ellipseMode(CENTER);
}
void draw () {
for (int i = 0; i < maxNumberOfSensors; i++) {
fill(255,sensorValue[i], 0);
//(rectSize * (i%rows), rectY, rectSize, rectSize); //top left
ellipse(ellipseX + ellipseSize/2, ellipseSize * (i%rows) + ellipseSize/2, ellipseSize*(1-sensorValue[i]/255), ellipseSize*(1-sensorValue[i]/255)); //top left
if((i+1) % rows == 0) ellipseX += ellipseSize;
}
ellipseX=0;
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n'); // 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
println(sensorValue[i]); // print value to see
}
}
}
}
Fabrication files¶
-
File: Arduino matrix ↩
-
File: Original processing code ↩
-
File: final processing code ↩