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.

Saturday, June 13, 2020

Capsense Exploration

Using this Youtube Tutorial (https://www.youtube.com/watch?v=stejKa03tdw), I was able to play with the capsense library and which showed the pressure on the wire itself. The capsense library is pretty cool, and I would look for more examples in the future.

Processing Experimentation

For this processing experimentation, I played with the Star code and changed the size and increased the frequency of rotations.

Code for Star:
void setup() {
size(640, 360);
}
void draw() {
background(200,0,0); // background color

pushMatrix(); // left star
fill(204, 102, 0); // not sure how to change individual colors?
translate(width*0.2, height*0.5);
rotate(frameCount / 50.0); // increased rotation
star(0, 0, 20, 70, 6); //increased number of corners
popMatrix();

pushMatrix(); // center star
translate(width*0.5, height*0.5);
rotate(frameCount / 400.0);
star(0, 0, 80, 100, 40);
popMatrix();

pushMatrix(); // right star
translate(width*0.8, height*0.5);
rotate(frameCount / -100.0);
star(0, 0, 50, 70, 8);
popMatrix();
}
void star(float x, float y, float radius1, float radius2, int npoints) {
float angle = TWO_PI / npoints;
float halfAngle = angle/2.0;
beginShape();
for (float a = 0; a < TWO_PI; a += angle) {
float sx = x + cos(a) * radius2;
float sy = y + sin(a) * radius2;
vertex(sx, sy);
sx = x + cos(a+halfAngle) * radius1;
sy = y + sin(a+halfAngle) * radius1;
vertex(sx, sy);
}
endShape(CLOSE);
}

Code for Hue
int barWidth = 50; // increase width of the bar
int lastBar = -1;
void setup()
{
size(640, 640); // change canvas size
colorMode(HSB, height, height, height);
noStroke();
background(0);
}
void draw()
{
int whichBar = mouseY / barWidth; //mouse moves up and down and changes color
if (whichBar != lastBar) {
int barX = whichBar * barWidth;
fill(mouseY, height, height);
rect(barX, 0, barWidth, height);
lastBar = whichBar;
}
}

Analog Output Experimentation

For this analog output experimentation, I learnt how to use a sensor to control an output. I couldn’t really figure how to use the map function though and got confused with the previous voltage divider assignment. However, this exercise would prove useful for my final SPA prank.

Final SPA Documentation: A Rick Roll Box


For the final SPA project, I wanted to use Arduino to create a surprise box prank that would play Never Give You Up by Rick Astley to prank my brother. This is the link to the Arduino project that I would like to replicate: https://create.arduino.cc/projecthub/slagestee/rickroll-box-3c2245 (I just didn’t want an output to be created). 

It took a little bit of finicking as the tone wouldn’t play on the piezo speaker (in an ideal world with no pandemic, I would’ve tried this with an mp3 speaker but couldn’t get one in time). I had to use a toneMelody code to check if the piezo speaker would work and also had to check if each part was working. 

As seen in the video, the tone plays when the photoresistor is uncovered but stops when it is covered. I still have to play with the photoresistor values to have made it less finicky (take in the shadows in the environment). I also took out the potentiometer as it was causing my prank more problems.

To develop this further, it would be nice to attach a servo to it and with it, I would attach a photo of Rick Astley to take the prank even further. 

Here is my code adapted from the tutorial:


#define  a3f    208     // 208 Hz
#define  b3f    233     // 233 Hz
#define  b3     247     // 247 Hz
#define  c4     261     // 261 Hz MIDDLE C
#define  c4s    277     // 277 Hz
#define  e4f    311     // 311 Hz    
#define  f4     349     // 349 Hz 
#define  a4f    415     // 415 Hz  
#define  b4f    466     // 466 Hz 
#define  b4     493     // 493 Hz 
#define  c5     523     // 523 Hz 
#define  c5s    554     // 554 Hz
#define  e5f    622     // 622 Hz  
#define  f5     698     // 698 Hz 
#define  f5s    740     // 740 Hz
#define  a5f    831     // 831 Hz 

#define rest    -1

int piezo = 7;
int led = 9;
int button = 2;
int sensor = A0;

volatile int beatlength = 100; // determines tempo
float beatseparationconstant = 0.3;

int threshold;

int a; // part index
int b; // song index
int c; // lyric index

boolean flag;

// Parts 1 and 2 (Intro)

int song1_intro_melody[] =
{c5s, e5f, e5f, f5, a5f, f5s, f5, e5f, c5s, e5f, rest, a4f, a4f};

int song1_intro_rhythmn[] =
{6, 10, 6, 6, 1, 1, 1, 1, 6, 10, 4, 2, 10};

// Parts 3 or 5 (Verse 1)

int song1_verse1_melody[] =
{ rest, c4s, c4s, c4s, c4s, e4f, rest, c4, b3f, a3f,
  rest, b3f, b3f, c4, c4s, a3f, a4f, a4f, e4f,
  rest, b3f, b3f, c4, c4s, b3f, c4s, e4f, rest, c4, b3f, b3f, a3f,
  rest, b3f, b3f, c4, c4s, a3f, a3f, e4f, e4f, e4f, f4, e4f,
  c4s, e4f, f4, c4s, e4f, e4f, e4f, f4, e4f, a3f,
  rest, b3f, c4, c4s, a3f, rest, e4f, f4, e4f
};

int song1_verse1_rhythmn[] =
{ 2, 1, 1, 1, 1, 2, 1, 1, 1, 5,
  1, 1, 1, 1, 3, 1, 2, 1, 5,
  1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3,
  1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4,
  5, 1, 1, 1, 1, 1, 1, 1, 2, 2,
  2, 1, 1, 1, 3, 1, 1, 1, 3
};


int song1_chorus_melody[] =
{ b4f, b4f, a4f, a4f,
  f5, f5, e5f, b4f, b4f, a4f, a4f, e5f, e5f, c5s, c5, b4f,
  c5s, c5s, c5s, c5s,
  c5s, e5f, c5, b4f, a4f, a4f, a4f, e5f, c5s,
  b4f, b4f, a4f, a4f,
  f5, f5, e5f, b4f, b4f, a4f, a4f, a5f, c5, c5s, c5, b4f,
  c5s, c5s, c5s, c5s,
  c5s, e5f, c5, b4f, a4f, rest, a4f, e5f, c5s, rest
};

int song1_chorus_rhythmn[] =
{ 1, 1, 1, 1,
  3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
  1, 1, 1, 1,
  3, 3, 3, 1, 2, 2, 2, 4, 8,
  1, 1, 1, 1,
  3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
  1, 1, 1, 1,
  3, 3, 3, 1, 2, 2, 2, 4, 8, 4
};


void setup()
{
  pinMode(piezo, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  pinMode(sensor, INPUT);
  attachInterrupt(digitalPinToInterrupt(button), getFaster, FALLING);
  digitalWrite(led, LOW);
  Serial.begin(9600);
  flag = false;
  a = 4;
  b = 0;
  c = 0;
  threshold = analogRead(sensor) + 0;
}

void loop()
{
  //play();
  int sensorreading = analogRead(sensor);
  if (sensorreading < threshold) { // if bright, play
    flag = true;
  }
    else if (sensorreading > threshold) { // if dark, pause
    flag = false;
  }

  //play next step in song
  if (flag == true) {
    play();
  }
}

void play() {
  int notelength;
  if (a == 1 || a == 2) {
    // intro
    notelength = beatlength * song1_intro_rhythmn[b];
    if (song1_intro_melody[b] > 0) {
      digitalWrite(led, HIGH);
      tone(piezo, song1_intro_melody[b], notelength);
    }
    b++;
    if (b >= sizeof(song1_intro_melody) / sizeof(int)) {
      a++;
      b = 0;
      c = 0;
    }
  }
  else if (a == 3 || a == 5) {
    // verse
    notelength = beatlength * 2 * song1_verse1_rhythmn[b];
    if (song1_verse1_melody[b] > 0) {
      digitalWrite(led, HIGH);
      //Serial.print(lyrics_verse1[c]);
      tone(piezo, song1_verse1_melody[b], notelength);
      c++;
    }
    b++;
    if (b >= sizeof(song1_verse1_melody) / sizeof(int)) {
      a++;
      b = 0;
      c = 0;
    }
  }
  else if (a == 4 || a == 6) {
    // chorus
    notelength = beatlength * song1_chorus_rhythmn[b];
    if (song1_chorus_melody[b] > 0) {
      digitalWrite(led, HIGH);
      //Serial.print(lyrics_chorus[c]);
      tone(piezo, song1_chorus_melody[b], notelength);
      c++;
    }
    b++;
    if (b >= sizeof(song1_chorus_melody) / sizeof(int)) {
      //Serial.println("");
      a++;
      b = 0;
      c = 0;
    }
  }
  delay(notelength);
  noTone(piezo);
  digitalWrite(led, LOW);
  delay(notelength * beatseparationconstant);
  if (a == 7) { // loop back around to beginning of song
    a = 1;
  }
}

void getFaster() { // decrease beat length in order to increase tempo
  beatlength = beatlength / 2;
  if (beatlength < 20) { // loop back to original tempo
    beatlength = 100;
  }
}

Final Prank Documentation

Ultimately, I couldn't finish my final prank. I had completed the main part of my project that would alert me when my cat was on the counter by flashing the LED and playing an alarm whenever he covered up the LDR. After this, I tried to connect a servomotor in the hopes that I could use it to drop a small cup of water onto my cat in addition to alerting me.

This didn't go well. When I first researched how to connect the servo motor to my existing project, I was told to connect to GND and 5V. Unfortunately, I was already using 5V to connect to the LDR so I was unsure of what to do. In the hopes of making this work, I tried connecting the servomotor to the other available GND and 3.3V rather than 5V. I learned that this was a mistake, as after I moved away I accidentally grazed the Arduino board and electrocuted my finger.

Overall, I was unable to connect the servomotor but I am still very happy with the alarm system that I created using Arduino. It was a really fun experiment and interesting to watch my cat interact with it. In a way, getting electrocuted felt like karma for trying to splash water on my cat.



The final set up with the servomotor that hurt me


The final

Analog Output Experimentation

I had a lot of issues with this experimentation. In the end, the only thing I was able to figure out was having the LED fade constantly and turn off when something was covering the LDR. What I was hoping to do with this project was to have the LDR control the brightness of the LED and then have another button that determines whether or not the LED is on or off.

I'm still trying to figure out this project, but hopefully I learn my mistake soon!


const int ledPin = 9;
const int ldrPin = A0;
int brightness = 0;
int fadeAmount = 5;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(ldrPin, INPUT);
 
}

void loop() {
  int ldrStatus = analogRead(ldrPin);

  if (ldrStatus <= 400) {
    analogWrite(ledPin, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);;
  }
  else {
    digitalWrite (ledPin, LOW);
   
  }
}

Capsense Library Experimentation

After following the YouTube video and the Instructables video, I was able to successfully create a capacitive sensor using the Arduino. I was actually surprised by how simple it was. I first tried putting my wire against the metal portion of my scissors before closing my fist over the wire and seeing the serial monitor respond to that. I think that the capacitive sensor is a really useful tool and I plan to try using it in the future.

The code I used was the Capacitive Sensor Sketch example from the Capsense Library.


Final Prank Documentation

Annabel Lee
DES 325 

My computer just shut down and I can't seem to reopen Arduino; I keep getting a popup message that says that the application is not responding and forces me to quit the program. I also tried to use the browser version but still could not connect to my Arduino port. Arduino and I have a love-hate relationship... However, due to the sake of time, I will continue to share what I had in mind and my potential plan. 

Capsense Library

Capacitive Sensing


This was quite interesting as I got to understand the value of capacitive sensing and can recognize the technologies that possibly use this type of sensing. I used a 1M ohm resistor and connected it to my x-acto knife. The serial monitor was still confusing to read because of the unstable grounding but I was able to witness the changes in the readings so I'm happy it was evidently working. 

My code:

#include <CapacitiveSensor.h>

CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2); // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

void setup(){

cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example Serial.begin(9600);

}

void loop(){

long start = millis();

long total1 = cs_4_2.capacitiveSensor(30);

Serial.print(millis() - start); // check on performance in milliseconds

Serial.print("\t"); // tab character for debug window spacing

Serial.println(total1); // print sensor output 1

delay(10); // arbitrary delay to limit data to serial port

}

Knolling a Film Camera


I decided to tear apart a Canon AE-1 film camera. The interesting thing is that a lot of the parts have to do with the processing of light through the lens itself which serves the primary part of the camera. Personally, finding which parts fall under sensor, processing and actuation was a little tough as I didn’t have an object to knoll but finding this teardown image was very helpful. I personally take a lot of film photography (but rely very heavily on my Leica point and shoot) and have never thought of what goes behind my camera. This knolling experience has allowed me to understand my camera better and am able to apply it to my photography.

Analog Output Experimentation

Annabel Lee
DES 325 A
Analog Output Experimentation

Part 1: 

Was able to successfully get the photoresistor to detect a change in light which would directly affect the dimness of the LED. The change in dimness was extremely subtle. I decided to increase the resistance to make the light more sensitive to the photoresistor. From a 220 ohm resistor, I changed it to a 2K ohm resistor and it made a significant difference. I was even able to see the delay more clearly with the new resistor. See below:



Part 2: LED controlled by Joystick

Well, the original plan was to experiment with the joystick to control the LED lights and then try using photoresistors to replace the joystick to turn on certain lights as to mimic current game controllers that use sensors to control movement and the display. Unfortunately... I could not even get the arduino to really work. It is difficult without much guidance even though I had a tutorial. Hopefully I learn my mistake soon. 
Add caption
int UD = 0;

int LR = 0;

/* Arduino Micro output pins*/

int DWN = 13;

int UP = 12;

int LEFT = 11;

int RT = 10;

/*Arduino Micro Input Pins */

int IUP=A0;

int ILR=A1;

int MID = 10; // 10 mid point delta arduino, use 4 for attiny

int LRMID = 0;

int UPMID = 0;

void setup(){

pinMode(DWN, OUTPUT);

pinMode(UP, OUTPUT);

pinMode(LEFT, OUTPUT);

pinMode(RT, OUTPUT);

digitalWrite(DWN, HIGH);

digitalWrite(UP, HIGH);

digitalWrite(LEFT, HIGH);

digitalWrite(RT, HIGH);

//calabrate center

LRMID = analogRead(ILR);

UPMID = analogRead(IUP); }

void loop(){

UD = analogRead(IUP);

LR = analogRead(ILR);

// UP-DOWN

if(UD < UPMID - MID){

digitalWrite(DWN, HIGH);

}else{

digitalWrite(DWN, LOW);

}

if(UD > UPMID + MID)

{ digitalWrite(UP, HIGH);

}else{

digitalWrite(UP, LOW);

} // LEFT-RIGHT

if(LR < LRMID - MID){

digitalWrite(LEFT, HIGH);

}else{

digitalWrite(LEFT, LOW);

}

if(LR > LRMID + MID){

digitalWrite(RT, HIGH);

}else{

digitalWrite(RT, LOW);

}

delay(400);
}




Friday, June 12, 2020

SPA Project: Humidity/Temperature Detector




As I was exploring different components of Arduino, I thought it would be interesting if I could build something that would help me get a sense of the weather. I wanted to use the DHT11 sensor to detect the humidity and temperature of the day so I can figure out what to wear. 

Problem Space: Find a better sense of what to wear depending on the humidity and temperature of the day! 

Following a tutorial from https://how2electronics.com/interfacing-dht11-humdity-temperature-sensor-with-arduino/. I was able to get my LCD to turn on but had a difficult time figuring out how to get any digital display to show up. Many error messages were popping up. 

Unfortunately, I could not figure out how to get my LCD display the text that I want... but this is what I have so far and wish to see if anyone else could figure out what I did wrong here.


My code:
#include <dht.h> //downloaded from online
#include <LiquidCrystal.h>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

LiquidCrystal lcd(7, 6, 5, 4, 3, );
#define dht_dpin 8
dht DHT;
byte degree[8] =
{
0b00011,
0b00011,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};
void setup()
{
lcd.begin(16, 2);
lcd.createChar(1, degree);
lcd.clear();
//lcd.print(” Humidity “);
lcd.setCursor(0,1);
//lcd.print(” Measurement “);
delay(2000);
lcd.clear();
}
void loop()
{
DHT.read11(dht_dpin);
lcd.setCursor(0,0);
//lcd.print(“Humidity:”);
lcd.print(DHT.humidity); // printing Humidity on LCD
//lcd.print(” %”);
lcd.setCursor(0,1);
//lcd.print(“Temp:”);
lcd.print(DHT.temperature); // Printing temperature on LCD
lcd.write(1);
//lcd.print(“C”);
delay(500);
}
}
 Error messages: 
Arduino: 1.8.12 (Mac OS X), Board: "Arduino Uno"

humidity_sensor:6:1: error: expected unqualified-id before numeric constant
 2
 ^
/Users/annabel/Documents/Arduino/humidity_sensor/humidity_sensor.ino: In function 'void setup()':
humidity_sensor:63:1: error: 'lcd' was not declared in this scope
 lcd.begin(16, 2);
 ^~~
/Users/annabel/Documents/Arduino/humidity_sensor/humidity_sensor.ino: In function 'void loop()':
humidity_sensor:75:1: error: 'lcd' was not declared in this scope
 lcd.setCursor(0,0);
 ^~~
/Users/annabel/Documents/Arduino/humidity_sensor/humidity_sensor.ino: At global scope:
humidity_sensor:86:1: error: expected declaration before '}' token
 }
 ^
exit status 1
expected unqualified-id before numeric constant

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Final Prank Documentation

Surprise Tickle Prank
I decided to try to use Arduino to surprise tickle people when they sit at their desk. How diabolical!

Circuit
I had a couple of ideas for how to sense the pranked person when they sat at their desk, such as light fluctuations and motion detection, but eventually I settled on using light for simplicity's sake. Thus, I began this project by setting up the servo motor and then integrating the photoresistor into the circuit.




Initial Code

#include <Servo.h>

Servo servo1;

void setup() {

  // set the servo pin, pin 9, as a servo output pin
  servo1.attach(9);
}

void loop() {
  //Read the light value from the photoresistor
  int lightValue = analogRead(A0);

  // map the light readings to the angle possible by the servo motor
  lightValue = map (lightValue, 0, 1023, 0, 180);

  // control the servo motor based on the light value read, adjust linearly by angles
  servo1.write(lightValue);

}


Progress!
I was able to successfully use the light values detected by the photoresistor to determine the angle of the servo rotation.



Refinement
I realized that to simulate tickling, the movement of the servo had to be erratic rather than simple and fixed like the above motions (which were determined by the detected light values). Thus, I had to simplify the code further and use the photoresistor solely to determine whether the light detected had dropped below a specified value (instead of reporting back each value). If the photoresistor detected darkness (a person sitting in front of the resistor, blocking light), then the Arduino would actuate servo rotation of a random value until the person got up from the seat (allowed light to be detected again).



In the above video, I taped a bundle of fluffed up q-tips to the servo since I didn't have feathers, but ideally one would use feathers for tickling. I also did not have the means to put together the whole prank set up, but I have included a diagram of what it would look like below. The servo and feathers would have to be positioned in a spot that is inconspicuous but also open enough to easily reach the pranked person. This would likely be at the bottom of the desk leg. Additionally, I would tape a paper towel roll to the photoresistor to point it at where the pranked person would sit so that it would not be affected by nearby light changes. 




Refined Code
#include <Servo.h>

Servo servo1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  // set the servo pin, pin 9, as a servo output pin
  servo1.attach(9);
}

void loop() {
  //Read the light value from the photoresistor
  int lightValue = analogRead(A0);
  Serial.println(lightValue);
  // map the light readings to the angle possible by the servo motor
  // lightValue = map (lightValue, 0, 1023, 0, 180);
  
  if (lightValue < 500) {
    servo1.write(random(30, 360));
    delay(random(10,300));
  }

}


Next Steps?
Rather than using the photoresistor to detect when someone has sat down at their desk, it would be more effective to use a capacitive touch sensor that can discern a person's proximity to the desk. That way, the set up would be unaffected by uncontrolled variables such as ambient light changes due to the time of day. To use the capacitive touch sensor, though, I would have to make sure that the pranked person touched the sensor material in some way. Perhaps I could put a discrete piece of aluminum foil on the desk chair..? This is something that I would look into if I was to continue developing this project.

Thanks for reading!