• moawling

STREEEEEEETCH! breathe!! relax! it's PROJECT 2

For our second project, we aimed to create a device that enhances a meditative experience and allows people to do so in tandem with one another.


Meditation is a communal practice, it’s common for people who share a moment of meditation to fall into sync with one another. This phenomena is known as “interpersonal synchrony”, and our device builds upon this idea by illustrating the synchronization of two (or more) bodies via their breath.


Our initial idea was to incorporate a sensor that would detect the meditators’ breath, and create a visualization that reflects the expansion and contraction of the diaphragm. We also wanted our sketch to represent interpersonal synchrony by having two spheres overlap. We thought these gifs conveyed the quality of movement that we would want in our sketch:













Image Description: animated gifs showing two spheres representing two different individual’s breaths, the sizes are rhythmically expanding and shrinking. One sphere is pink and the other is blue. The two individuals’ breathing is out of sync.

Image Description: this animated gif represents the combined meditators' breathing. The two spheres (pink and blue) are overlapping one another. A blending mode allows for the overlapping colours to glow a soft, white colour. The two spheres are expanding and contracting to represent breath. In this gif, the two spheres are out of sync.

Image Description: similar to the previous gif, this image represents the combined meditators' breathing. The two spheres are almost moving as one to represent synchronized breathing.


We decided to use a stretch sensor to capture the expansion and contraction of the abdomen. My collaborator for the project, Eden Chinn, was able to acquire a stretch sensor on the floor! I didn't have one of my own and we were working remotely, so communication and careful coordination was important for troubleshooting this project.


Eden acquired some code and wiring advice from one of our peers, and set up the board accordingly:

Image Description: A small breadboard with an Arduino nano and a stretch sensor. White wires represent power, green wires represent ground, and blue wires represent input.


There were several things set up on the board that didn't fit our vision for the project! Upon closer evaluation, we realized that the board wasn't powered properly and that we needed to wire the stretch sensor differently so that it could work as a voltage divider.


We drafted a schematic to figure our plan for the board. We needed a 10k resistor to properly "pull down" the voltage, and create a voltage gradient, so that we could have a range of values to be read.


Image Description: A drawing of a schematic. A teal rectangle with the letter 'A' represents our microcontroller. A green circle with an X through it represents our stretch sensor.


A red line, representing power, is connected to the 5 Volt pin on our microcontroller, and is connected to the stretch sensor.


A green line, representing input, is connected to an analog pin, which is labeled as A0.


A black line, representing ground, is connected to our stretch sensor, then runs through a 10k resistor, and then runs to ground


We had our schematic drafted out! We decided that I would take a stab at setting up the board this time. I didn't have a stretch sensor myself, but we were able to troubleshoot stuff together over Discord. We even matched colours so that it would help with communicating remotely. Here's a couple of my attempts:

Image Description: A small breadboard with an Arduino nano, a 10k resistor and several green, white, and black, and red wires.

White and red wires represent power, green wires represent an imaginary rubber sensor, and black wires represent ground.


This attempt ended up not working because I misunderstood wire placement. My rubber sensor (represented by green wire), is connected directly to the input and to row 20 on my breadboard. I tried to create a voltage divide by having a wire for power and my pull-down resistor on the same row (row 20).


This wouldn't work, because the sensor would only be powered. It wouldn't register the other components on the board that would be necessary to pull it towards ground.


ATTEMPT #2! THE WINNER!


Image Description: A small breadboard with an Arduino nano, a 10k resistor and several green, white, and black, and red wires.

White and red wires represent power, green wires represent an imaginary rubber sensor, and black wires represent ground.


THE WINNER! Instead of having my imaginary sensor connected to INPUT, I connected it to POWER. The other end of the stretch sensor was moved down to row 27, which had wires connecting to ground and to my INPUT.


This change was important so that the stretch sensor could actually function as a voltage divider.


HOOORAY!!! NOW IT'S TIME FOR THE CODE!


Here is our finished Arduino code! The comments are in blue!

//reference for stretch sensor: https://forum.arduino.cc/index.php?topic=132454.0
//also used smoothing from example arduino code

const int numReadings = 10;
int sensorPin = 0;  // Stretch sensor is connected to analog pin 0

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average


void setup()
{
  Serial.begin(9600);         //initialize the serial port

  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
} 
void loop() // run over and over again
{
// subtract the last reading: this is a ring buffer, only exists inside of the arduino fixed number of slots and a sliding window average of the last 10 slots
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(sensorPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }
  // calculate the average:
  average = total / numReadings;
  //send to computer in ASCII digits

  if(average<750){ //You can change the number here to adjust the threshold.
    Serial.print("Stretch");
  }
  else{
    Serial.print("Rest"); // average is greater thasn 750
  }

  Serial.print("                     Sensor Value: ");

   Serial.println(average);

  delay(100);  // delay for 1/10 of a second
}

The most exciting thing that I learned about this code was the concept of ring buffers! Our stretch sensor initially gave very varied and inconsistent readings. If we used that flow of data for our p5js sketch, our soothing breathe orbs would be extremely jittery.

Instead of using functions to "smooth" out our values, we used a ring buffer to help average out our values. The ring buffer would take the average of every 10 values, and our code helps organize the array of information! The ring buffer is performed solely by the Arduino, our p5js sketch only receives the averages and never learns of any other values.


Eden collaborated with our peer, Rajshree, to make the foundation of our p5js sketch. You can see her work here! https://editor.p5js.org/edenchinn/sketches/nohdqDcvD


My job was to make the orb change colours! You can see my additions in red! All comments are still in blue.

I had to comment out several sections because I did not have a stretch sensor to test things out. Instead, I included a function so that the circle would change colours according to our computer's internal clock.

// we want this circle to change colours, to do so we need to define two different colours
// the range of our stretch sensor is 705 (low, unstretched) to 805 (high, stretched)

// this is to define our colours and colour values,
let blue // this represents our low, unstretched value
let red // this represents our high, stretched value

let serial;
let portName = '/dev/tty.usbmodem14101'; // fill in your serial port name here
let breathe = 100; // size of the circle))))

function setup() {
  createCanvas(800, 600);
//  serial = new p5.SerialPort();
//  serial.on('data', serialEvent); // callback for when new data arrives
//  serial.open(portName); // open a serial port
}

function draw() {
    data = 600 + 200*(1+sin(millis() / 1000 * 3));
    breathe = 600 - 0.5 * data // this is so we can fake having a sensor and test the code 
  
  red = color(255,0,0);
blue = color(0,0,255); // these are our RGB values, moved down to draw function
  
  background(0);

    // this lerpColor function let's us change colours
  gradient = lerpColor(blue, red, breathe/420) // lerp goes between 0-1
  fill (gradient)
  ellipse(width / 2, height / 2, breathe, breathe)
}

function serialEvent() {
  //let data = serial.read();  
  let data = serial.readLine(); //find in p5serial.js, explains what it does
  if (data) {
    breathe = 600 - 0.5 * int(data.split(':')[1].trim())
    console.log(data);
    //console.log(String.fromCharCode(data));
    //serial.readLine();
  }
}

After making these changes, I then met up with Eden to test it out with the actual sensor! We then modified the code, which meant returning the lines that I had commented out.


Here's the final code!

https://editor.p5js.org/mnk2970/sketches/Fgo_-yAcU


I understood most of the code, but had trouble understanding the serial event function! I went over it with Eden to understand it a bit more. I added additional comments to explain what each line meant.

function serialEvent() {  //this function gets called when data comes in, data comes in one byte at a time
  let data = serial.readLine(); //the sensor value of 800), // The read and print are counterparts between arduino and JS code (this is referred to as a rendezvous)
  if (data) { // data is best read as a complete line, however, we need to tell the code what to do with/without a full line. This states, if we have a complete line, do the thing, if not, wait for more data
    sensorvalue = int(data.split(':')[1].trim()) // data refers to the line of values OR ASCII text that is being communicated, which looks like this: (rest        Sensor Value: 800). We ONLY want the number value, so this code says to split the line where the colon and 'trim' gets rid of spaces
    breathe = 600 - 0.5 * sensorvalue // mapping/calibrating sensor value
  }

HOORAY YAY WOW YEAH this code worked like a CHARM!


CHECK IT OUT HERE:


We weren't able to accommodate multiple devices due to a time constraint, but we we plan on working towards an advanced version of our meditation idea for a future project. We used the rest of our time to theorize the application of the stretch sensor and how it could be worn by a user.


THE TAEKWONDO DOBOK (uniform):

My personal experience with meditation comes from TaeKwonDo. I come from a lineage of strong martial artists and my family runs a TaeKwonDo business. Part of the reason that I'm attending school remotely is so that I can help teach classes during the pandemic.


I was thinking of how this interpersonal synchronous device would be useful for teaching our students to practice meditation. It's often difficult to convince kids to sit still, but I imagine that having a visual will help them understand the significance of breathe.

Outside of meditation, various forms, or poomsae, place special emphasis on breathing when striking or blocking. This is similar to other forms of exercise, where you have to consider your breath when exerting force.


I was thinking that the stretch sensor fit perfectly within the design of the Taekwondo dobok. Within the top of the uniform, or jeogori is an elastic loop that straps across the wearer's abdomen and connects to a button on the other side of the shirt. This is mostly for aesthetic purposes and help the uniform to fit neatly, but I was thinking that it would be the perfect place to fit our stretch sensor!


Eden brought up a good point! We'd have to re-calibrate the stretch sensor, as it would be slightly stretched in this context. I am really excited about this idea and look forward to seeing how we can expand upon it in the future!