Skip to content

12. Skin Electronics

Research and Inspiration

1. NeoTouch - Conceptual idea of touch from far

image.png

The Interactive Architecture Lab (The Bartlett, UCL). 2018 Link

2. Power-over-Skin: Full-Body Wearables Powered By Intra-Body RF Energy

image1.png

Research Team: Andy Kong, Daehwa Kim, Chris Link

3. Simple sewing machine has high-tech role in future 'soft' machines

image2

Link

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.

Matrix_1.jpg

The board used was a Xiao ESP23-S3 on a FabriXiao board

Here is how i attached the Matrix to the board.

Matrix_2.jpg

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.

UNO

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.

Circuit_1.jpg

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.