As computing becomes more ubiquitous in our objects, designers need to be more aware of how to design meaningful interactions into electronically enhanced objects. At the University of Washington, a class of junior Interaction Design majors is exploring this question. These pages chronicle their efforts.

Friday, December 13, 2019

tranSIT

Clara Too, Sasha Noerdin
DES 325 Physical Computing, Fall 2019



What is TranSIT?

TranSIT is a unique public transit seating experience. It is more solitary and private than your usual bus/subway seats, and TranSIT will play music that reacts to audible knocks from the sitter, and adjusts according to the ambient noise of the light rail car.


Background & Our Situation

Our initial idea was to enhance the public transit experience and make it more interesting and exciting, compared to the normally 'sterile-esque' environment of public transit. Originally, we wanted to create public transit chair that would encourage people to interact with each other and potentially share their music with each other. However, based on a survey we did with 33 people, we found that commuting is normally a time of reflection and many people don't want to interact with each other on public transit.
















Thus, we changed our idea to become a 'privacy/reflective chair' that can play music based on the current 'mood' of the environment - which is based on sound levels (more on how that works later!)


Our goals(things we specifically wanted to detect) with TranSIT was:
• Sound levels (decibels) of the train environment.
• Motion/pressure to find out if anyone is nearby and/or sitting in the chair.

From this we created our pseudocode / logic diagram before we began coding and building the chair:




















We ended up changing the logic for the final design to address the concerns people brought up in the survey, and in order to make it more manageable. People who took the survey were concerned about being forced to listen to music they didn’t want to listen to. In the end, we decided to give the person sitting in the chair more control over what music they would listen to by adding a ‘knock’ function - one knock would change the music, and two knocks would stop it. And instead of trying to detect the presence of one person versus multiple people, in order to evaluate and reflect the mood of the room, we used the electret microphone to listen for the ambient volume and adjust the type of music accordingly. We had two playlists - 1 ‘baseline’ playlist that would play at quiet or normal volumes and 1 ‘hype’ playlist that would play at higher volumes.




Ideation & Chair Design





Building Phase

We ended up using wood to create a frame of the chair, and then sewing white cloth to create pseudo-upholstery on the chair and to give the impression of solid sides in the chair where one could lean on. Previously we built some chair mockups using cardboard to test out what sizes would be comfortable to sit on.























Arduino Setup

Sensors: 
• PIR Motion Sensor
• Electret Microphone Amplifier
• Aideepen Uart MP3 Player
• Piezoelectric Contact Microphone

Other components used:
• 1 extra breadboard
• AUX to AUX cable
• Bose Speaker
• Telephone wire to elongate the PIR and Piezoelectric sensors' reach.




Code

Over the course of figuring out the code, there were two major issues we ran into. The first was in trying to figure out how to record two knocks. After quite some struggle involving trying to create multiple sample windows, we were finally able to use the millis() function to record the time of the knocks and figure out whether two knocks were close enough in succession to be registered as a pair of knocks. The other pain point was getting the mp3 player to work like we wanted it to; it was a bit of a learning curve to understand how the code for it should be formatted. At first we were using random() to play songs, but it turned out to not be very random at all, as only 3 out of our 20+ songs were playing. When we used the shuffle command from the mp3 library, we got a much better variety of songs, so we stuck with that instead.

#include <SoftwareSerial.h>

#define ARDUINO_RX 5//should connect to TX of the Serial MP3 Player module ***RX connects to 6, TX connects to 5
#define ARDUINO_TX 6//connect to RX of the module


SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial wich pins are TX and RX

static int8_t Send_buf[8] = {0} ;//The MP3 player understands orders in a 8 int string
                                 //0X7E FF 06 command 00 00 00 EF;(if command =01 next song order)
#define NEXT_SONG 0X01
#define PREV_SONG 0X02

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED
               
#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output

#define SHUFFLE_FOLDER 0X28


int ledPin = 9;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

const int sampleWindow = 50; // Sample window width in mS (250 mS = 4Hz)
unsigned int sample;
unsigned int ambient;

void setup() 
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);//Start our Serial coms for serial monitor in our pc
  mySerial.begin(9600);//Start our Serial coms for THE MP3
  delay(500);//Wait chip initialization is complete
   sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card 
  delay(200);//wait for 200ms
}


 void sendCommand(int8_t command, int16_t dat) 
delay(20); 
Send_buf[0] = 0x7e; //starting byte 
Send_buf[1] = 0xff; //version 
Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte 
Send_buf[3] = command; // 
Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback 
Send_buf[5] = (int8_t)(dat >> 8);//datah 
Send_buf[6] = (int8_t)(dat); //datal 
Send_buf[7] = 0xef; //ending byte 
for(uint8_t i=0; i<8; i++)// 
  mySerial.write(Send_buf[i]) ;//send bit to serial mp3 
Serial.println(); 

unsigned int oldKnock;

void loop() 
{

int baselineTracks1;
int baselineTracks2;
int hypeTracks1;
int hypeTracks2;
baselineTracks1 = random(1,7);
baselineTracks2 = random(8,13);
hypeTracks1 = random(20,23);
hypeTracks2 = random(24,27);
  
  //initial person sensing:

   val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH
    if (pirState == LOW) {
      Serial.println("Person detected! -> music starts playing");
      // We only want to print on the output change, not state
      pirState = HIGH;
      // we have just turned on
      //checking room volume:
      ambient = analogRead(1);
      if(ambient < 2024){
        sendCommand(0x28, 01);
        Serial.print("Baseline: Playing track");
        //Serial.println(baselineTracks1);
        //delay(3000);
        }else if(ambient >= 2024){
        sendCommand(0x28, 02);
        Serial.print("Hype 2: Playing track");
        //Serial.println(hypeTracks2);
        //delay(30000);
      }
      
      
    }
  } else if (pirState == HIGH){
      // we have just turned off
      Serial.println("No person detected");
      // We only want to print on the output change, not state
      pirState = LOW;
    } 


  //knock detection:

 unsigned long start= millis();  // Start of sample window
 unsigned int peakToPeak = 0;   // peak-to-peak level

 unsigned int signalMax = 0;
 unsigned int signalMin = 2024;

  // collect data for 250 miliseconds

 unsigned int curKnock;
 unsigned int spacing = 500;
 bool twoKnocks = false;
 bool oneKnock = false;
  
  while (millis() - start < sampleWindow)
 {
   sample = analogRead(0);
      if (sample < 2024)  //This is the max of the 10-bit ADC so this loop will include all readings
      {
         if (sample > signalMax)
         {
           signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
        {
           signalMin = sample;  // save just the min levels
         }
      }
 }  


    peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
    double volts = (peakToPeak * 5.0) / 2024;  // convert to volts
   // Serial.println(volts);


      if (volts>1.0)
      {
        curKnock = millis();
        Serial.println(curKnock);
        Serial.println(oldKnock);
        Serial.println(curKnock-oldKnock);
        if(curKnock - oldKnock < spacing)
        {
          twoKnocks = true;
        }
        else
        {
          oneKnock = true;
        }
        oldKnock = millis();
      }
      
    
      
 //end of knock detection

     if(twoKnocks == true)
      {
        Serial.println("Two knocks: stop music");
        sendCommand(0x16, 0); //stop music
        twoKnocks = false;
      }
      else if(oneKnock == true)
      {
         Serial.println("One knock: change song");
         oneKnock = false;
         ambient = analogRead(1);
        if(ambient < 2024){
        sendCommand(0x28, 01);
        Serial.print("Baseline: Playing track");
        //Serial.println(baselineTracks1);
        //delay(3000);
        }else if(ambient >= 2024){
        sendCommand(0x28, 02);
        Serial.print("Hype 2: Playing track");
        //Serial.println(hypeTracks2);
        //delay(30000);
      }
      }
    
}


Final Demo Video
https://bit.ly/2Pk9jMh


In the end, the chair ended up functioning just as well as we hoped it would - it would play when the motion sensor detected a person sitting on it, changed songs when the Piezo microphone heard one knock, and stopped playing music when it heard two knocks. In theory, the types of tracks it played depended on the ambient volume in the room - more upbeat songs would play when it was generally louder, as detected by the electret microphone; this function did not work perfectly, however, as the variation between the baseline songs and upbeat songs seemed fairly random when we actually tested it out.


Reflection and Issues we dealt with


We learned many skills from this project. Neither of us had ever worked with wood, sewn, soldered, or had any experience using the Arduino. We were originally most worried about working with wood, but in the wood shop we learned how to use a wood saw and drill. We learned that wood actually is just a bit smaller than the dimensions that it says on the label, and learned how to turn our ideas for a 3D form into 2D diagrams, from which we could build what we wanted. Although neither of us are particularly mathematically inclined, with some patience we were able to figure out the dimensions to know how much of what size wood to buy. We learned how to solder and how to use a sewing machine in the MILL, and we learned how to use the fabric staple gun in the woodshop to secure the fabric to the frame. (One unexpected challenge in building the chair was transporting the wood around, especially after we had drilled the frame together - we ended up having to carry it up and down the stairs quite a few times, which was quite a workout.) We also learned how to print stickers, since we printed a vinyl sticker at the Mill in order to add a signifier for the knocking.

We were not fully satisfied with the final form of the chair - we felt we had strayed too much from the aesthetic of the original Link context. If we were to do another iteration, we would want to make a more rounded form, although this likely would have been quite difficult to do in the time that we had. We may try to do some 3D rendering to imagine other shapes for the final tranSIT product.



No comments:

Post a Comment