메이커 Maker

마음까지 따뜻해지는 난로 暖心爐(난심로) 작품 보고서

지구빵집 2022. 1. 19. 09:12
반응형

 

 

마음까지 따뜻해지는 난로는 곰 인형이 트래킹 로봇 위에 앉아있는 형태로 디자인하였으며, 사람이 있는 곳으로 이동하여 충전 배터리의 열기로 온기를 전해주고 따뜻한 말을 스피커로 이야기해 마음까지 위로해 주는 난로입니다. 

 

Brain Storming & Design Thinking 기법을 활용한 회의 

 

저희 팀은 이번 프로젝트에서 21세기 핵심 역량으로 떠오른, 4C를 적용하고자 했습니다. 4C는 Communication, Collaboration, Critical Thinking, Creativity를 의미합니다. Communication의 가치를 실현하기 위해 저희는 즉각 단체 채팅방을 만들어 자유로운 분위기 속에서 Brain Storming 기법을 활용하여 작품 논의를 시작했습니다. 논의 끝에 선정된 아이디어 외에도 좋은 아이디어가 많아 의견 차이로 인한 갈등이 있을 법도 했지만, 꾸준한 소통 덕에 갈등이 없었습니다.

 

Collaboration의 가치를 실현하기 위해 팀원 개인의 역량에 주목했습니다. 개개인의 역량 차이가 우리 팀 프로젝트 활동에 장애가 되지 않도록 각자가 잘하는 것을 하되, 부족한 부분은 함께 공부하며 채우는 방향으로 프로젝트를 진행했습니다. 이를 통해 지적 향상을 이룰 수 있었습니다.

 

마음까지 따뜻해지는 난로 暖心爐(난심로)

 

Critical Thinking의 가치를 실현하기 위해 저희 팀은 브레인스토밍 과정에서 나온 아이디어를 토론을 거쳐 간소화하고 토의를 통해 구체화하여 최종 아이디어를 선정했습니다. 특히 상대방을 설득하는 과정을 거치며 논리적인 사고를 기를 수 있었습니다. Creativity의 가치를 실현하기 위해 일상생활에서 보는 사물이나 현상을 새로운 관점으로 보려고 노력했습니다. 다소 엉뚱한 생각을 하며 새로운 의미를 발견하거나, 기존의 생각과 개념을 새롭게 조합하려고 노력했습니다. 그 결과 물리적인 따뜻함을 주는 난로와 심리적인 따뜻함을 연결하여 마음도 따뜻해지는 난로를 주제로 정하게 되었습니다. 

 

작품명

 

작품명을 팀명과 같은 JAK3로 정했습니다. 왜냐하면 이번 프로젝트에서 한 뜻으로 활동을 이어가자는 우리 팀의 의지를 우리 작품에게 투영하고 싶었기 때문입니다. 팀명을 JAK3로 정한 이유는 이것이 우리 팀원 모두를 아우를 수 있는 상징적인 문자열이기 때문이었습니다. JAK3는 정지호의 ‘J’, 안의찬의 ‘A’, 김철순, 김익제 그리고 개인적인 사정으로 이번 어드벤처 디자인 1 팀 활동에 참여하지 못하게 된 권혁인 총 3명의 ‘K’를 따서 만든 팀명입니다.  

 

마음까지 따뜻해지는 난로 暖心爐(난심로) 디자인

 

디자인 배경

 

JAK3는 곰 인형이 트래킹 로봇 위에 앉아있는 형태로 디자인 했습니다. 저희 팀이 만들고 싶었던 JAK3는 물리적인 따뜻함과 따듯한 말을 동시에 하는 로봇이었습니다. 그러나 일반적으로 우리가 생각하는 로봇은 따뜻함과 거리가 멀어 우리의 의도를 JAK3가 잘 드러낼 수 있을지 의문이었습니다. 그래서 저희는 어떤 부분에서 인간이 따듯함을 느낄 수 있을 지에 대해 고민하던 중 가장 인간 친화적이고 포근함을 상징할 수 있는 것이 바로 곰과 같은 동물이라는 결론을 내렸고, JAK3의 외관을 곰의 형태를 정했습니다.  

 

난로가 사람을 따라 이동하는 코드

 

8X8 픽셀의 센서로 물체를 감지해서 섭씨 25도 초과거나 섭씨 0도 미만일 때, 물체와 사람 사이의 거리가 20cm 이상이면 직진하고 20cm 미만이면 정지하는 코드입니다. 한 번 물체를 감지해 동작을 멈추면 다시 실행되지 않습니다. 

 

#include<NewPing.h>                           // NewPing이라는 라이브러리를 불러온다.
#define TRIGGER_PIN A2                        // 초음파 센서의 송신부를 아날로그 2번 핀에 지정한다.
#define ECHO_PIN A3                           // 초음파 센서의 수신부를 아날로그 3번 핀에 지정한다.
#define MAX_DISTANCE 100                      // 초음파 센서의 최대 길이를 100으로 하기 위해 변수 MAX_DISTANCE를 선언하고 초기화해준다.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing라이브러리의 함수를 이용한다.

#include <DynamixelShield.h>                  // DymamixelShield라는 이름의 라이브러리 불러오기

#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560)           // 아두이노 우노보드나 메가보드이면 아래 코드를 실행한다.
  #include <SoftwareSerial.h>                                           // SoftwareSerial이라는 라이브러리를 불러온다.
  SoftwareSerial soft_serial(7, 8);                                     // DYNAMIXELShield UART RX/TX 통신을 위해 7, 8번 핀을 사용한다.
  #define DEBUG_SERIAL soft_serial
#elif defined(ARDUINO_SAM_DUE) ||dxl.setGoalVelocity(1, 100);
  #define DEBUG_SERIAL SerialUSB
#else
  #define DEBUG_SERIAL Serial
#endif

const uint8_t DXL_R = 1;                  // 오른쪽 모터를 ID 1을 가진 모터로 지정한다.
const uint8_t DXL_L = 0;                  //   왼쪽 모터를 ID 0을 가진 모터로 지정한다.
const float DXL_PROTOCOL_VERSION = 2.0;   //  다이나믹셀을 사용하기 위한 통신 규약의 버전을 2.0으로 한다.

DynamixelShield dxlL;
DynamixelShield dxlR;

using namespace ControlTableItem;

#include <Wire.h>                             // Wire라는 라이브러리를 불러온다.
#include <Adafruit_AMG88xx.h>                 // 열화상 센서를 사용하기 위한 라이브러리를 불러온다.

Adafruit_AMG88xx amg;

//INT pin from the sensor board goes to this pin on your microcontroller board
#define INT_PIN 3                             // INT 핀을 디지털 3번 핀에 연결한다.

//interrupt levels (in degrees C) 섭씨 단위
//any reading on any pixel above TEMP_INT_HIGH degrees C, or under TEMP_INT_LOW degrees C will trigger an interrupt
//30 degrees should trigger when you wave your hand in front of the sensor
#define TEMP_INT_HIGH 25
#define TEMP_INT_LOW 0

volatile bool intReceived = false;
uint8_t pixelInts[8]; // 8열 배열
/******* 
we can tell which pixels triggered the interrupt by reading the
bits in this array of bytes. Any bit that is a 1 means that pixel triggered
         bit 0  bit 1  bit 2  bit 3  bit 4  bit 5  bit 6  bit 7
byte 0 |  0      1      0      0      0      0      0      1
byte 1 |  0      0      0      0      0      0      0      0
byte 2 |  0      0      0      0      0      0      0      0
byte 3 |  0      0      0      1      0      0      0      0
byte 4 |  0      0      0      0      0      0      0      0
byte 5 |  0      0      0      0      0      0      0      0
byte 6 |  0      0      0      0      0      1      0      0
byte 7 |  0      0      0      0      0      0      0      0
*****/
void go_straight(int vel, int del); // 직진 함수 원형 정의

void go_backward(int vel, int del); // 후진 함수 원형 정의

void right_turn(int vel, int del); // 제자리 우회전 함수 원형 정의

void left_turn(int vel, int del); // 제자리 좌회전 함수 원형 정의

void AMG88xx_ISR();

void setup(){
  Serial.begin(9600);                   // 9600의 비트레이트로 시리얼 통신 시작
  pinMode(INT_PIN, INPUT);              // INT 핀이 연결된 3번 디지털 핀에서 입력을 받아들인다.
  Serial.println(F("AMG88xx interrupt test"));

  bool status;                          //T나 F의 값을 갖는 bool 형태의 변수를 선언한다.
  
  // default settings
  status = amg.begin();
  if (!status) {
      Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
      while (1);
  }
  
  amg.setInterruptLevels(TEMP_INT_HIGH, TEMP_INT_LOW);

  //set to absolue value mode
  amg.setInterruptMode(AMG88xx_ABSOLUTE_VALUE);

  //enable interrupts
  amg.enableInterrupt();

  //attach to our Interrupt Service Routine (ISR)
  attachInterrupt(digitalPinToInterrupt(INT_PIN), AMG88xx_ISR, FALLING);
 
DEBUG_SERIAL.begin(115200);
  dxlR.begin(57600);
  dxlL.begin(57600);

  dxlR.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  dxlL.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  
  // Get DYNAMIXEL information
  dxlR.ping(DXL_R);
  dxlL.ping(DXL_L);

  // Turn off torque when configuring items in EEPROM area
  dxlL.torqueOff(DXL_L);
  dxlL.setOperatingMode(DXL_L, OP_VELOCITY);
  dxlL.torqueOn(DXL_L);

  dxlR.torqueOff(DXL_R);
  dxlR.setOperatingMode(DXL_R, OP_VELOCITY);
  dxlR.torqueOn(DXL_R);

}

void loop() {

 if(intReceived){ // 25도 초과이거나 0도 미만이면 코드 실행
  while(1) {
    delay(50);    // 50밀리초 멈춤
    unsigned int distance = sonar.ping_cm();  // 함수를 이용해 초음파 센서로 얻은 거리 값 계산
    if (distance > 20) {                      // 거리가 20 이상이면 직진
      go_straight(10, 0);
    }
    else {
      go_straight(0, 0);                      // 거리가 20 미만이면 정지
        while(1);                             // 무한 루프에 들어가며 움직임 정지
    }
  }
 }
 else {
  right_turn(2, 20);
  }
}

void AMG88xx_ISR() {
  //keep your ISR short!
  //we don't really want to be reading from or writing to the sensor from inside here.
  intReceived = true;
}

void go_straight(int vel, int del) { // velocity = 모터 속도, delay = 모터 회전을 유지할 시간
  dxlR.setGoalVelocity(DXL_R, -vel, UNIT_PERCENT); // 우측모터 시계 회전
  dxlL.setGoalVelocity(DXL_L, vel, UNIT_PERCENT); // 좌측모터 반시계 회전
  delay(del); // 모터 회전 유지 시간
  }

void go_backward(int vel, int del) { // velocity, delay
  dxlR.setGoalVelocity(DXL_R, vel, UNIT_PERCENT); // 우측모터 반시계 회전
  dxlL.setGoalVelocity(DXL_L, -vel, UNIT_PERCENT); // 좌측모터 시계 회전
  delay(del);
  }

void right_turn(int vel, int del) { // velocity, delay
  dxlR.setGoalVelocity(DXL_R, -vel, UNIT_PERCENT); // 우측모터 반시계 회전
  dxlL.setGoalVelocity(DXL_L, -vel, UNIT_PERCENT); // 좌측모터 반시계 회전
  delay(del);
  }

void left_turn(int vel, int del) { // velocity, delay
  dxlR.setGoalVelocity(DXL_R, vel, UNIT_PERCENT); // 우측모터 시계 회전
  dxlL.setGoalVelocity(DXL_L, vel, UNIT_PERCENT); // 좌측모터 시계 회전
  delay(del);
  }

 

화면을 터치하여 원하는 노래, 명언을 듣고 JAK3와 대화할 수 있는 코드

아두보이스가 아두보이스에 저장된 ‘피곤해’, ‘힘들다’, ‘짜증 나’,‘어떡하지’라는 말을 인식하면 라즈베리파이가 미리 녹음되었던 음성 파일들을 랜덤으로 들려줍니다.  

 

 

import serial
from  	tkinter import *
from tkinter.filedialog import *
import pygame
import random




def play_music():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 3)

    if track == 1:
        my_music = pygame.mixer.Sound("수고했어오늘도.wav")
    elif track == 2:
        my_music = pygame.mixer.Sound("괜찮아.wav")
    elif track == 3:
        my_music = pygame.mixer.Sound("가장따뜻한위로.wav")
    my_music.play()



def play_idiom():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 3)

    if track == 1:
        my_music = pygame.mixer.Sound("사랑해.wav")
    elif track == 2:
        my_music = pygame.mixer.Sound("오늘도수고했어.wav")
    elif track == 3:
        my_music = pygame.mixer.Sound("피할수없으면즐겨.wav")

    my_music.play()


def stop_all():
    pygame.quit()
    pygame.mixer.init()


def play_tired():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 2)

    if track == 1:
        tired = pygame.mixer.Sound("조급할필요없어.wav")
    elif track == 2:
        tired = pygame.mixer.Sound("좀쉬는거어때.wav")
    tired.play()


def play_hard():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 2)

    if track == 1:
        hard = pygame.mixer.Sound("좀쉬는거어때.wav")
    elif track == 2:
        hard = pygame.mixer.Sound("아이쿠많이힘들구나.wav")
    hard.play()


def play_annoy():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 2)

    if track == 1:
        annoy = pygame.mixer.Sound("무슨일있었어.wav")
    elif track == 2:
        annoy = pygame.mixer.Sound("괜찮아질거야.wav")
    annoy.play()


def play_howdo():
    pygame.quit()
    pygame.mixer.init()
    track = random.randint(1, 2)

    if track == 1:
        howdo = pygame.mixer.Sound("괜찮아그럴수도있지.wav")
    elif track == 2:
        howdo = pygame.mixer.Sound("잘될거야.wav")
    howdo.play()


AdvSerial = serial.Serial('COM8', 9600, timeout=1)

while True:

    line = AdvSerial.readline()
    pygame.mixer.init()

    if line == b'0\r\n':
        # 피곤해
        play_tired()

    if line == b'1\r\n':
        # 힘들다
        play_hard()

    if line == b'2\r\n':
        play_annoy()

    if line == b'3\r\n':
        # 어떡하지
        play_howdo()

    if line == b'4\r\n':
        # 그만
        break

root = Tk()
root.title("JAK3")
root.geometry("800x480")
pygame.mixer.init()

label1 = Label(root, text="JAK3")
label1.pack()

but_idiom = Button(root, width=20, height=1, text="힘이 되는 명언", font=("나눔스퀘어", 50), command=play_idiom)
but_idiom.pack()

but_music = Button(root, width=20, height=1, text="힘이 되는 노래", font=("나눔스퀘어", 50), command=play_music)
but_music.pack()

but_stop = Button(root, width=34, height=1, text="STOP", font=("나눔스퀘어", 30), command=stop_all, fg="white", bg="navy")
but_stop.pack()

root.mainloop()

 

아두보이스에서 시리얼 통신으로 받은 문자열로 작동하는 파이썬 코드  

JAK3가 ‘그만해’라는 말을 들으면, 음성을 인식해서 피드백해주는 코드를 종료하고 사용자가 힘이 되는 명언, 힘이 되는 노래를 선택하여 들을 수 있는 창을 열어줍니다.  

 

 

#include <SoftwareSerial.h>
 
SoftwareSerial voiceSerial(8, 7);   // Rx, Tx
char id;

void setup()
{  
  Serial.begin(9600);
  while (!Serial) 
  { 
    delay(500);
    Serial.print("."); 
  }
 
  voiceSerial.begin(9600);
  voiceSerial.listen();
}

void loop()
{  
  if (voiceSerial.available() > 1) 
  {
    id = voiceSerial.read();
    
    switch (id) 
    {
      case '0':
        Serial.println("0"); // 피곤해
        break;
      case '1':
        Serial.println("1"); // 힘들다
        break;
      case '2':
        Serial.println("2"); // 짜증나
        break;
      case '3':
        Serial.println("3"); // 어떡하지
        break;
      case '4':
        Serial.println("4"); // 그만해
        break;
    }
  }
}

 

팀원 인터뷰

 

한 학기 동안 팀으로 함께 프로젝트 활동을 이어온 소중한 팀원들의 인터뷰입니다.

 

Q1: 본인이 팀에 와서 생긴 변화?

 

J: 팀플 활동을 접해본 적이 없던 저는 매우 게으르고 못할 것 같으면 포기해버리는 성격이었는데, 팀원들에게 누가 되지 않기 위해 자연스럽게 책임감이 생기고 계획적으로 변했던 것 같습니다.

 

A: 결과보다 과정 특히나 과정을 통해 배우는 것을 중점으로 프로젝트를 진행하게 되었습니다.

 

K(김철순): 이 팀에서 같이 활동을 하며 저에게 생긴 변화는 팀원들이 정말 의욕적인 모습을 보여서 자극이 많이 되었다는 것입니다.

 

K(김익제): 팀보다 강한 개인은 없다는 것을 직접 느꼈다는 것이 변화된 것들 중 가장 큰 변화입니다. 할 수 없다고 생각했던 일들도 팀원들과 협력하여 하나하나 격파해 나아가면서 끈끈한 유대감을 느꼈습니다.

 

Q2:본인이 생각하는 커뮤니케이션이란?

 

J: 남의 말을 듣고 조율하는 것도 물론 중요한 부분이지만, 제가 가진 생각을 논리 정연하게 상대에게 피력하여, 설득시킬 수 있는 능력을 키우는 것이라고 생각합니다.

 

A: 단순한 정보교환을 넘어 서로가 서로에게 긍정적인 자극을 주고 함께 성장해나가기 위한 소통입니다.

 

K(김철순): 모두가 참여하는 과정 속에서 단순히 그 자리에 있는 것이 아닌 자신의 생각까지 말하는 게 커뮤니케이션이라고 생각합니다.

 

K(김익제): 본인이 옳다고 생각하는 것이라도 이것과 반하는 상대방의 의견들에 귀를 기울이며 타협점을 찾아가는 여정입니다.

 

Q3:우리 팀의 목표는 무엇이라고 생각하는지?

 

J: 기술적인 성장도 있지만, 맡은 일과 직면한 문제들을 조화롭게 풀어나가는 능력을 길러 어른스러운 모습을 갖추는 것이라고 생각합니다.

 

A: 아직 1학년이기 때문에 프로젝트의 성공보다는 앞으로의 프로젝트를 위한 기반 지식을 쌓고 팀원들 간의 소통에 익숙해지는 것입니다.

 

K(김철순): 결과가 좋으면 당연히 더 좋겠지만 결과를 내는 과정 속에서 모두가 더 많이 배우고 성장하는 것입니다.

 

K(김익제): 팀원들이 공동의 목표로 함께 달려가면서 구성원과 함께 성장하는 것입니다.

 

Q4:본인이 생각하는 중요한 의사 결정 기준이 무엇인지?

 

J: 현실적인 한계와 이상적인 아이디어의 타협선이 가장 중요한 결정기준이라고 생각합니다.

 

A: 과정을 통한 배움, 팀원 간의 화합을 증대하는 방향입니다.

 

K(김철순): 모두가 납득 가능하며 반대하는 사람 없이 결정하는 것입니다.

 

K(김익제): 팀원들과의 합의입니다. 팀원들과의 교집합이 가장 많으면서 모두가 합의할 수 있는 내용이 제 경험상 프로젝트를 성공적으로 이끌게 했던 강력한 힘이었습니다.

 

Q5:우리 팀의 계획은 무엇이라고 생각하는지?

 

J: 기계의 차가운 이미지를 탈피시킬 수 있는 인간 친화적 기계를 만드는 것입니다.

 

A: 마음까지 따뜻해지는 난로를 제작하는 과정에서 우리의 마음까지 따뜻해지는 것입니다.

 

K(김철순): 기존에 존재하던 평범한 난로에 사람의 마음을 위로해줄 수 있는, 힘이 될 수 있는 기능이 더해진 난로를 제작하는 것입니다.

 

K(김익제): 기존의 난로에서 느낄 수 있었던 따듯함을 포함하여 기계와 인간의 교감을 돕는 로봇을 만드는 것입니다.

 

Q6:팀 프로젝트를 하면서 본인이 담당했던 일?

 

J: 다이내믹 셀모터 제어 조수와 곰 인형과 온열기를 연결하는 작업 및 보고서 작성

 

A: 하드웨어 설계, 센서를 이용한 모터 제어, GUI 프로그래밍, 팀 리딩

 

K(김철순): 라즈베리파이와 아두보이스 간 정보 통신을 위한 코드 작성

 

K(김익제): 센싱 알고리즘을 구성하는 부분 보조,

 

Q7:팀 프로젝트를 진행하면서 어떨 때 보람을 느꼈는지?

 

J: 모두가 하고 있는 작업이 순탄하게 진행되어서 재미있는 분위기 속에서 함께 작업할 수 있을 때 보람을 느꼈습니다.

 

A: 팀원들이 과정을 통해서 몰랐던 것을 배우고 배운 것을 토대로 프로젝트의 진행에 기여를 할 때, 보람을 느낍니다.

 

K(김철순): 다 같이 참여한 회의가 훈훈하게 잘 끝났을 때(한 번도 갈등이 있진 않았지만), 모르는 부분에 대한 해결책을 찾았을 때입니다.

 

K(김익제): 절대 넘지 못할 것 같았던 벽을 팀원들과 협력하며 허물었을 때입니다.

 

Q8:우리 팀 그리고 본인에게 하고 싶은 말?

 

J: 기분 좋은, 그리고 화목하고 이상적인 팀플이 있다면 이런 것이 아닐까 싶습니다. 이 프로젝트 덕분에 한 학기 정말 보람차게 보낸 것 같습니다.

 

A: -팀원들에게: 부족한 팀장인데도 믿고 따라주고 매번 열정적으로 참여해주어서 너무 고마워 다들.

 

- 나에게: 앞으로 더 나은 리더가 되기 위해 넓은 지식을 쌓고 계획적으로 행동하길 바람.

 

K(김철순): 거의 다 왔다 ㅎㅎ 조금만 더 힘내자.

 

K(김익제): 우리 팀원들이 아니었다면 불가능했을 이 프로젝트. 팀원들과 함께해서 너무 좋았습니다.

 

Q9:미래 사용자에게 한 마디.

 

J: 코로나 블루 따뜻한 난로로 잘 극복해봅시다.

 

A: 마음까지 따뜻해지는 난로를 더 가치 있게 만들기 위해 프로젝트 내내 따뜻한 사람이 되기 위해 팀원 모두가 노력했습니다. 부디 저희의 진심이 전해지기를 바랍니다.

 

K(김철순): 기존에 볼 수 없었던 형태의 난로여서 되게 신기할 겁니다. 오래오래 소중하게 다뤄주세요.

 

K(김익제): 우리가 JAK3를 만들면서 느꼈던 모든 따뜻했던 감정들을 사용자 분께서 JAK3와 직접 교감하며 느끼셨으면 좋겠습니다. 우리 작품을 이용해주셔서 정말 감사합니다. 

 

디자인

 

 

 

반응형