Skip to content

12. Skin electronics

This week we experimented with sensors that can function as skin, such as pressure sensors, which allow us to sense the movement of the joints or also information matrices that would even allow us to create artificial skin that has pressure sensitivity.

RESEARCH

REFERENCES & INSPIRATION


SKIN SENSORS FOR VITAL SIGNS

Wearable electronics are growing increasingly more comfortable and more powerful. A next step for such devices might include electronics printed directly onto the skin to better monitor and interface with the human body.

Scientists wanted a way to sinter—that is, use heat to fuse—metal nanoparticles to fabricate circuits directly on skin, fabric or paper. However, sintering usually requires heat levels far too high for human skin. Other techniques for fusing metal nanoparticles into circuits, such as lasers, microwaves, chemicals or high pressure, are similarly dangerous for skin.

In the IEEE Spectrum page you can read more.

I am delighted how we can use the skin as a conductor of valuable information, as shown in the example above, sensors that can tell us how our body feels.



BEAUTY TECHNOLOGY

DuoSkin is a fabrication process that enables anyone to create customized functional devices that can be attached directly on their skin. Using gold metal leaf, a material that is cheap, skin-friendly, and robust for everyday wear, we demonstrate three types of on-skin interfaces: sensing touch input, displaying output, and wireless communication. DuoSkin

CIRCUIT1



BEAUTY AND CONNECTIVITY

DuoSkin is a rapid prototyping and fabrication process using the skin - friendly material gold leaf to create wearable on - skin user interfaces , such as:

( a ) sensing touch input

( b ) displaying the user's mood using a thermochromic tattoo.

( c ) communicating and sharing data with other devices through NFC - all while maintaining body decoration aesthetics.

Here you can read their research DuoSkin Connectivity

CIRCUIT1


EXAMPLES IN LAB

PRESSION SENSOR

In class with our teacher Citlalia Hernandez we were able to learn how to make a pressure sensor. For which we need the following materials.

CONSTRUCTION

To build the sensor it will be necessary to cut two conductive wires, cut some velostate and make a sandwich

Velostat or Linqstat is a pressure sensitive conductive material

1 conductive thread, velostate, 1 conductive thread.

Then we secure with tape so that the components do not move.

TEST

We connect an LED so that when the finger is flexed the pressure sensor sends the signal and the LED turns on. We can see the wiring and operation below.

CIRCUIT1 RESULT


int sensorPin = A0;
int sensorValue = 0;


int pinD = 8;
int b = 0;


void setup() {
  // put your setup code here, to run once:

 pinMode(pinD, OUTPUT);
 Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

b = !b;

digitalWrite(pinD, b);
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
delay(500);

if(sensorValue >= 115){
    digitalWrite(13, HIGH);
  }

  else{
    digitalWrite(13, LOW);
  }
}

MATRIX SENSOR

We build a sensor in the form of a 9-point matrix, occupying the previous sensor logic.

For which we need the following materials.

CONSTRUCTION

For the construction it was necessary to cut a square of paper where we could accommodate our sensors.

  • We cut 3 pieces of conductive tape and glue them on top of the square, trying to keep the same distance between each of the lines.

  • We cut 3 strips of velostate and glued 3 pieces of conductive tape on top.

  • We need to connect wires to the terminals of each conductive tape so we proceed to solder.

  • After them we arrange the strips in the following way.

CIRCUIT1 RESULT


Make sure that the conductive tapes do not touch, that is why we use the velostat, Velostat or Linqstat is a pressure sensitive conductive material

TEST

We make the following connection to the arduino, very similar to the previous example

CIRCUIT1 RESULT


You must pay attention to the connection order of digital and analogue pins to have your data organized and know which box is 0, 1, etc. when you want to analyze this data.

Copy and paste in Arduino IDE the following code:

#define numRows 3
#define numCols 3
#define sensorPoints numRows * numCols

int rows[]= {A0, A1, A2};
int cols[]= {7, 8, 9};
int incomingValues[sensorPoints] = {};

void setup () {

 for (int i = 0; i < numRows; i++) { pinMode(rows[i], INPUT);}
 for (int i = 0; i < numCols; i++) { pinMode(cols[i], OUTPUT);}
 Serial.begin(9600);
}

void loop ()
{
  for (int colCount = 0 ; colCount < numCols; colCount++){
    digitalWrite(cols[colCount], HIGH);
    for (int rowCount = 0; rowCount < numRows; rowCount++){
      incomingValues[colCount * numRows + rowCount] = analogRead(rows[rowCount]);
    }
    digitalWrite(cols[colCount], LOW);
  }
  for (int i = 0; i < sensorPoints; i++){
    Serial.print(incomingValues[i]);
    if( i < sensorPoints - 1)
    Serial.print("\t");
  }
  Serial.println();
  delay(10);
}
The result is this.

VISUAL INTERFACE

Next, we deal with the Processing program, which will help us create a graphical interface with the data collected by the Arduino.

Open processing and paste this code:

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()[2]; // 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++) {
        println("Raw sensor value: " + incomingValues[i]);
        sensorValue[i] = map(incomingValues[i], -50, 1000, 0, 255);
        println("Mapped sensor value: " + sensorValue[i]);
      }
    }
  }
}

You will have this result.

INTERACTIVE TATTOO

Something I wanted to integrate into this assignment was to be able to connect my body to the internet, some variable.

I wanted something portable and beautiful. The analog variable that I will manage will be my body temperature and the actuators will be microLEDs that will be connected to my skin.

STEP 1

I started drawing on my skin trying to arrange and design the connection paths of my electronic components.

CIRCUIT1 RESULT


STEP 2

I needed to use Arduino Cloud since creating the information API there also gave me the tool to be able to create a more attractive user interface than what would be done conventionally with a WEB server on ESP32.

We head to Arduino Cloud and create an account, this is completely free.

Then we proceed to create a new Thing and add the variables.

AC

The variables that I will occupy are 3:

  • Temperature = this is an analog variable so I will save it with data type Float

  • LED1 = Boolean data - Light sequence #1 - this is so that when you press the button and it goes to TRUE state, light sequence #1 begins

  • LED2 = Boolean data - Light sequence #2 - this is so that when you press the button and it goes to TRUE state, light sequence #2 begins

AC

STEP 3

We configure a new board, in my case I will be using the ESP32 WROOM 32 E

PINOUT ESP 32

We need to configure this board and also the wifi network connection

PINOUT ESP 32

After that you just need to go to the network settings and enter your Wi-Fi data.

STEP 4

Automatically when we see the Sketch option we can see that a code has been automatically generated.

PINOUT ESP 32

It will be necessary to install some drivers that you can install by clicking on the LEARN MORE option.

CIRCUIT1

After them, all that remains is to configure some communication data with the esp32 and we will be ready to upload the following code.

CIRCUIT1 RESULT


TEST 1

As a first test I want to see if any analog data goes up and updates correctly, so instead of a thermistor I first use a potentiometer.

I make the following electronic connection.

CIRCUITEST

Copy the following code and upload it to the board from the Arduino Cloud web editor.

In the dashboard configuration we can design the control interface.

DASHBOARD

Download the Arduino Cloud IOT mobile app on your cell phone, enter your account and you can view the data.

The good thing about working with Arduino Cloud is that we have a backup of the data and its visualization in real time.

#include "thingProperties.h"

const int analogPin = 39;
int L1 = 13;
int L2 = 12;
int L3 = 27;
float value;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(115200);
  pinMode(analogPin, INPUT);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);

  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);


  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  onLED1Change();
  onLED2Change();
  // Your code here 
  tEMP = analogRead(analogPin);       // realizar la lectura analógica raw

Serial.println(tEMP);
  delay(500);
}


void onLED1Change()  {
  // Add your code here to act upon LED1 change
  if ( lED1  ) {
    digitalWrite( L1 , HIGH ) ;
    digitalWrite( L2 , HIGH ) ;
    digitalWrite( L3 , HIGH ) ;

    delay(1000);

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;

    delay(500);

  } else {

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;
}
}


/*
  Since LED2 is READ_WRITE variable, onLED2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onLED2Change()  {
  if ( lED2 ) {
    digitalWrite( L1 , HIGH ) ;
    digitalWrite( L2 , HIGH ) ;
    digitalWrite( L3 , HIGH ) ;



  } else {

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;
}
}

FINAL RESULT

After the final test I prepared the connection with the microleds and the thermistor.

DASHBOARD

Update the code as follows

#include "thingProperties.h"


float R1 = 42000;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

float ThermistorPin = 39;
 float Vo;

int L1 = 13;
int L2 = 12;
int L3 = 27;
float value;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(115200);
  pinMode(ThermistorPin, INPUT);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);

  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  onLED1Change();
  onLED2Change();
  // Your code here

   Vo = analogRead(ThermistorPin);
 R2 = R1 * (4095.0 / (float)Vo - 1.0);
 logR2 = log(R2);
 T = 1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2);
 Tc = T - 273.15;
 Tf = (Tc * 9.0) / 5.0 + 32.0;

  tEMP = Tc;       // realizar la lectura analógica raw

Serial.println(tEMP);
  delay(500);
}



/*
  Since LED1 is READ_WRITE variable, onLED1Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onLED1Change()  {
  // Add your code here to act upon LED1 change
  if ( lED1  ) {
    digitalWrite( L1 , HIGH ) ;
    digitalWrite( L2 , HIGH ) ;
    digitalWrite( L3 , HIGH ) ;

    delay(1000);

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;

    delay(500);

  } else {

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;
}
}


/*
  Since LED2 is READ_WRITE variable, onLED2Change() is
  executed every time a new value is received from IoT Cloud.
*/
void onLED2Change()  {
  if ( lED2 ) {
    digitalWrite( L1 , HIGH ) ;
    digitalWrite( L2 , HIGH ) ;
    digitalWrite( L3 , HIGH ) ;



  } else {

    digitalWrite( L1 , LOW ) ;
    digitalWrite( L2 , LOW ) ;
    digitalWrite( L3 , LOW ) ;
}
}

APLICATION

To design the circuit on my skin I used conductive fabric tape

CIRCUIT1 RESULT


FINAL

CIRCUIT1

VIDEO

Fabrication files


  1. File: xxx 

  2. File: xxx 

  3. File: xxx