준비물

피지컬 컴퓨팅?

피지컬 컴퓨팅 (물질의 계산?)

물질이 가지는 에너지도 미디어다!

전기 에너지는 여러 에너지를 상호 변환할 수 있는 에너지이다. 일종의 유니버설 에너지. 전기 에너지는 에너지계의 로제타석 이다.

그래서 전기를 컴퓨팅하는 마이크로 콘트롤러(예를 들어 아두이노)를 이용하면 물리적인 에너지도 컴퓨팅 할 수 있게 된다.

인터렉티션 정의

상호간에 듣고, 생각하고, 대답하는 과정. –크리스 크랙포드 (게임프로그래머)

모든 피지컬 컴퓨팅 프로젝트는 역시 '듣기, 생각하기, 대답하기'로 나눌 수 있다. 컴퓨터 용어로 입력, 프로세싱, 출력

해보기

  • 미디어 아트 프로젝트를 선택하여 입력, 프로세싱, 출력으로 구분해서 분석해보자!

1. LED와 전원

LED와 전원(코인건전지 9V)을 연결해보자. LED는 전기 에너지를 빛에너지로 바꾸는 소자이다.

해보기:

2. LED와 USB전원

  1. 헬로보드를 전원으로 사용해보자.
  2. 질문: LED를 5V(+), GND(-) 에 연결하면 잘 동작할까요? (가정-결과관찰-비교-학습)

http://dh8.kr/docs/course/ksad2010/ksad2010helloboard/helloboardpin.png

3. 헬로보드에서 LED켜기 (입력)

LED의 +를 헬로보드의 D13번에 연결 합시다! 전에 LED 터뜨리셨으면 어쩔 수 없습니다! 앞으로 머리속에서 불을 키는겁니다. ㅎㅎㅎㅎ (H 옆에 LED 보이시죠? 이 LED는 D13에 연결되어 있는 LED 입니다.)

그리고 아래의 코드를 헬로보드에 프로그래밍 하자.

준비물

LED 켜기

int ledPin = 13;

void setup() {
  pinMode(ledPin, OUTPUT);      
}

void loop() {
  digitalWrite(ledPin, HIGH);
  delay(1000);
}

해보기:

  • LED를 1초에 한번씩 깜빡이도록 만드세요!

힌트: digitalWrite(ledPin, LOW);

우리는 프로그래밍을 통해 물리적 스위치 없이도 LED를 제어할 수 있습니다 (controlable). 프로그램의 무한루프는 장치가 살이 있는 것처럼 만들수 있지요 (liveness).


스위치 사용 (입력)

int buttonPin = 4;
int ledPin = 13;
boolean value;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);      
}

void loop() {
  value = digitalRead(buttonPin);
  if (value == HIGH) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

해보기:

  • 버튼의 입력을 받아서 LED를 켜보기에서 '프로세싱' 에 해당하는 것은 무엇일까요?

4. 모터 (출력)

LED대신 모터를 연결할 수 있습니다. 모터는 전기에너지를 운동에너지로 바꾸는 장치입니다. 멋지지 않습니까!! 19세기 전기공학자의 승리이지요! 아하하. 모터는 마이클 패러데이가 발명했군요. 네? 패럿이 좀 익숙하시다구요?

int buttonPin = 4;
int ledPin = 13;
int motorAPin = 3;
int motorBPin = 5;
boolean value;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, INPUT);
  pinMode(motorAPin, OUTPUT);   
  pinMode(motorBPin, OUTPUT);   
}

void loop() {
  value = digitalRead(buttonPin);
  if (value == LOW) {
    digitalWrite(motorAPin, HIGH);
    digitalWrite(motorBPin, LOW);
    digitalWrite(ledPin,HIGH);
  } else {
    digitalWrite(motorAPin, LOW);
    digitalWrite(motorBPin, LOW);
    digitalWrite(ledPin,LOW);
  }
}

해보기

  • 모터를 연결하여 동작이 잘되다 멈추지 않나요? 왜 잘 동작 안될까요? 그 이유를 생각해보세요. 힌트: 에너지 보존 법칙!

5. 빛센서로 LED 제어

버튼 대신 빛센서를 사용하여 LED를 제어 해보죠

빛센서와 마이크, 슬라이더는 아날로그 센서이다. 디지털 센서는 0(LOW) 와 1(HIGH)만 가져올 수 있지만, 아날로그 센서는 0부터 1023값까지 가져올 수 있다.

int cdsPin = 1;
int ledPin = 13;
int value;

void setup() {
  pinMode(cdsPin, INPUT);
  pinMode(ledPin, OUTPUT);   
}

void loop() {
  value = analogRead(cdsPin);
  if (value > 512) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

해보기:

  • 마이크와 연결해보자. 마이크의 핀번호는 0번이다. analogRead(0);
  • 슬라이더의 핀번호는 2번 이다. 슬라이더를 사용하여 LED를 제어 해보자.

6. 컴퓨터와 아두이노 사이의 통신

arduino는 컴퓨터의 USB를 통해 데이터를 주고 받을 수 있다. 이때 주고받는 통로를 시리얼 포트 라고 한다. 포트는 항구를 의미하여, 데이터를 내리고 받고 하는 곳이다. 주고 받는 데이터는 숫자다!

파이썬으로 프로그램을 버튼으로 사용하여 모터를 제어해보자

아두이노 코드

int ledPin = 13;
int value;

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

void loop() {
  if (Serial.available() > 0) {
    value = Serial.read();
    if (value == '1') { 
    digitalWrite(ledPin, HIGH);
    } else {
    digitalWrite(ledPin, LOW);
    }
  }
}

해보기:

  • 아두이노의 시리얼 모니터에서 1 또는 0의 숫자를 입력한다. 어떻게 될지 예상해보자.
  • pyserial을 설치하고, 파이썬 인터프리터에서 다음과 같이 입력해보자. 어떻게 될지 예상해보자.


시리얼포트의 이름: 코드의 '/dev/ttyUSB0' 는 시리얼포트의 이름으로 플래폼 마다 다르다. 윈도우는 'com1' 이런식이고, 맥은 '/dev/tty.usbserial-AXXXX' 이런식이다. 자신의 플랫폼에 맞추어 시리얼 포트의 이름을 바꾸자.

>>> import serial
>>> s = serial.Serial('/dev/ttyUSB0')
>>> s.write('1')
1
>>> s.write('0')
1
>>> 

GUI 스위치 만들기

from Tkinter import *
import sys

import serial
port = '/dev/ttyUSB0'  # TODO: change port name
speed = 9600

def send(char):
    ser = serial.Serial(port,speed)
    ser.setDTR()
    ser.flushInput()
    ser.write(char)
    ser.close()

def toggle_switch():
    if switch_button["text"] == "Turn On":
        send('1')
        switch_button["text"] = "Trun Off"
    else:
        send('0')
        switch_button["text"] = "Turn On"

root = Tk()
root.title('Switch')
switch_button = Button(root, text="Turn On",command=toggle_switch)
switch_button.pack()

root.mainloop()

프로세싱

import processing.serial.*;

Serial myPort; boolean value;

void setup() { size(200, 200); String portName = Serial.list()1; myPort = new Serial(this, portName, 9600); }

void draw() { background(255); if (value == true) { // If mouse is over square, fill(204); // change color and myPort.write('1'); // send an H to indicate mouse is over square } else { // If mouse is not over square, fill(0); // change color and myPort.write('0'); // send an L otherwise } rect(50, 50, 100, 100); // Draw a square }

void mousePressed() { if (value == true) { value = false; } else { value = ture; } }

이번엔 반대로! 아두이노에서 입력을 받아서 컴퓨터에 출력을 해보자.

아두이노 코드

int switchPin = 4;                       

void setup() {
  pinMode(switchPin, INPUT);             
  Serial.begin(9600);                    
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {  
    Serial.print('1');               
  } else {                               
    Serial.print('0');
  }
  delay(100);                            
}

프로세싱 코드

import processing.serial.*;

Serial myPort;
int value;

void setup() 
{
  size(200, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw()
{
  if ( myPort.available() > 0) {  // If data is available,
    value = myPort.read();         // read it and store it in val
  }
  if (value == '0') {              // If the serial value is 0,
    background(0);
  } 
  else {                       // If the serial value is not 0,
    backgroun(255);
  }
}

** 해보기:
 - 아두이노의 버튼이 눌리면, 채워진 사각형을 그려보자. 

일상에서 유용한 장치 만들기

하이퍼 텍스트 커피포트 조절 장치 http://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol

트위터와 연결

7. 물이 다 끓면 트윗!

사이커피 트위터: http://twitter.com/#!/BYTT2

물이 다 끓면 사이커피 트위터에 트윗이 됩니다!

TODO: 연결 개념도 넣기.

아두이노 코드

int cdsPin = 3;
int ledPin = 13;
int value;

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

void loop() {
  value = analogRead(cdsPin);
  if (value > 700) {
    Serial.print('1');
    digitalWrite(ledPin,HIGH);
  } else {
    Serial.print('0');
    digitalWrite(ledPin,LOW);
  }
}

버튼으로 트윗!

int ledPin = 13;
int buttonPin = 4;
int value;

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

void loop() {
  value = digitalRead(buttonPin);
  if (value == LOW) {
    Serial.print('1');
    digitalWrite(ledPin,HIGH);
  } else {
    Serial.print('0');
    digitalWrite(ledPin,LOW);
  }
}

파이썬 코드

# -*- coding: utf-8 -*-

import tweepy
from tweepy.error import *
import serial, os, random
from time import localtime, strftime

port = '/dev/ttyUSB0'
speed = 9600
coffee = '1'

def random_string():
    word = ''
    for i in range(4):
        word += random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
    return word

def receive():
    ser = serial.Serial(port,speed)
    ser.setDTR()
    ser.flushOutput()
    value = ser.read(1)
    ser.close()
    return value

CONSUMER_KEY = 'OMzEiHX57WxDcgBmqg0vzQ'
CONSUMER_SECRET = 'DdaRA8IfrVjDVr9OzxYh6vtAEHn66ECwzPWgr7Zafg'

auth = tweepy.OAuthHandler(CONSUMER_KEY,CONSUMER_SECRET)
print 'Authorization URL: ' + auth.get_authorization_url()
token = raw_input('Token:')
auth.get_access_token(token)
api = tweepy.API(auth)


while True:
  p_coffee = coffee
  coffee = receive()
  if p_coffee == '0' and coffee == '1':
      try:
          api.update_status(u'여러분, 커피가 다 되었습니다. 커피 마시러 오세요~ 장소는 문지문화원 2층 --커피봇' + random_string() + strftime(" %Y-%m-%d %H:%M:%S", localtime()))
          print 'update successed!'
      except TweepError:
          print 'update failed!'

해보기

  • 이 예제를 응용하여, 일상을 풍요롭게 할 수 장치에 대한 아이디어를 내보자! 짝과 이야기 나눠 보세요.

8. 트위터 메시지로 LED 켜기.

트위터에서 #BYTTBOT 해쉬태그로 'On' 이라는 메시지가 포스팅하면 LED가 켜진다.

아두이노 코드

시리얼포트로 '1' 이 들어오면 LED를 깜박거립니다.

int ledPin = 13;
int value;

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

void loop() {
  if (Serial.available() > 0) {
    value = Serial.read();
    if (value == '1') { 
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
    } 
  }
}

파이썬 코드

트위터에서 #BYTTBOT을 검색하여 그 결과 내용에 'On' 문자열이 있으면 시리얼 포트로 '1' 을 보냅니다.

import simplejson, urllib, sys, re, time
import serial
port = '/dev/ttyUSB0'  # TODO: change port name
speed = 9600

def send(char):
    ser = serial.Serial(port,speed)
    ser.setDTR()
    ser.flushInput()
    ser.write(char)
    ser.close()

params = {'q':"#BYTTBOT"}
query = urllib.urlencode(params)

url = "http://search.twitter.com/search.json?%s" % query
timeline = set()

while True:
    time.sleep(0.5)
    results = simplejson.load(urllib.urlopen(url))['results']
    for entry in results:
        r = re.compile(r'((www\.|(http|https|ftp|news|file)+\:\/\/)[_.a-z0-9-]+\.[a-z0-9\/_:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])',re.I|re.M)
        text = r.sub('<a href="\\1">\\1</a>',entry['text'].encode( "utf-8" ))
        r = re.compile(r'(@)+([_.a-z0-9-]+)', re.I|re.M)
        text = r.sub('<a href="http://twitter.com/\\2">\\1\\2</a>',text)
        from_user = entry['from_user'].encode( "utf-8" )
        if text in timeline:
            continue
        if 'on' in text.lower():
             send('1')
             print text
        else:
             send('0')             
        timeline.add(text)

참고

Footnotes:

1 FOOTNOTE DEFINITION NOT FOUND: 0

Author: <donghee@donghee8.com>

Date: 2011-11-10 09:56:32 KST

HTML generated by org-mode 6.21b in emacs 23