프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

GUI를 통해 LED제어하기

2014-11-25 14:20:30

개요

개요

GUI란 (Graphic User Interface)의 약자로 사용자가 사용하는 시스템을 그래픽으로 나타내어 제어를 가능하게 해주는 환경을 말한다.
GUI의 반대로는 그래픽이 아닌 순전히 글자로만 시스템을 표현하는 환경을 말하는 CUI(Character User Interface)가 있다.

GUI하면 대표적인 것이 모두들 아는 Windows시리즈나 MacOS가 있고 CUI의 대표라 하면 MS-DOS나 Unix가 있다.
GUI가 생기기전에는 모든 컴퓨터의 작업을 명령어로 표현했으며 Command창을 보면 알 수 있듯이 그래픽적인 표현은 순전히 까만 화면의 회색의 글씨가 전부였다.
덕분에 인터페이스는 매우 불편하였고 제대로 사용하기 위해서는 여러 명령어들을 꿰차고 있어야만 했었다.




하지만 GUI의 대표인 Windows시리즈의 등장으로 인해 컴퓨터는 전문가만이 다룰 수 있는 전유물이 아닌 일반사람들도 쉽게 다룰 수 있는 생활가전이 되었고,
모든 시스템들을 눈으로 보고 쉽게 이해할 수 있게 되었다. 
GUI의 가장 큰 장점은 컴퓨터와 사용자간의 인터페이스의 난이도를 확낮췄다는데에 있다.
글로 보고 이해하는 것보다 눈으로 보고 이해하는 것이 빠르며, 키보드로 쳐야할 명령어를 외우고 있는 것보다 마우스 클릭을 통해 디렉토리를 열고 닫고 하는 일련의 단순화된 행동들이 사용자의 편의성을 대폭 증가 시켰다.(키보드는 CUI시대를 이끌었고 마우스는 GUI의 시대를 불러왔다.)

이번에 만든 프로젝트는 예전에 올린 시리얼 모니터로 LED 제어하기의 업그레이드 버전으로 
프로세싱을 통해 GUI를 만들고 GUI를 통해 LED를 제어하는 프로젝트이다.

전공자들은 모르겠지만 대다수의 사람들은 간단하게 값의 입출력을 시리얼모니터나 콘솔창을 통해 센서나 LED의 출력은 쉽게 할 수 있지만
이런 입출력 인터페이스를 그래픽으로 표현하여 만드는 것을 어려워하고
실질적으로도 직접 레이아웃을 짜서 토글, 버튼, 슬라이드, 박스 등을 만드는 것도 초보자들에게는 어려운일이다.

여기서는 이런 GUI를 제공하는 라이브러리를 사용하여 누구나 쉽게 GUI로 여러 모듈을 제어하게 하는것이 목적이다.





이번 프로젝트에서는 간단하게 LED 2개를 프로세싱 GUI를 통해 제어해 보자.

동영상


필요한 사전 지식

시리얼 통신
프로세싱



부품 목록

NO 부품명 수량 상세설명
1 아두이노 우노 1 아두이노
2 7SMD RGB LED 2 DFRobot
3 브레드 보드 1  
4 케이블 2  

부품명 아두이노 우노 7SMD RGB LED 브레드 보드 케이블
부품
사진

하드웨어 making

브레드 보드



전자 회로도





소프트웨어 coding

ControlP5

소스를 소개하기전에 프로세싱에서 쉽게 GUI를 만들수 있는 라이브러리를 소개하려 한다.

이름은 ControlP5이며 사이트는 http://www.sojamo.de/libraries/controlP5/#resources 이곳이다. 아래 링크에서 라이브러리를 받을 수 있다.

ControlP5 내려받기 <- 링크

아는 사람은 아는 이 ControlP5는 프로세싱에서 GUI를 쉽게 제작가능하게 하는 유용한 라이브러리이며
여러 버튼, 슬라이드, 토글, 라디오 버튼 등을 미니멀하고 심플하게 표현한 라이브러리이다.





이 프로젝트에서도 이 ControlP5라이브러리를 사용했으며 프로세싱의 언어가 Java와 유사하기 때문에
Java를 만져본 사람들은 쉽게 예제를 가지고 변형하여 나만의 UI를 만들 수 있다.




위 사진에서 보듯이 다양한 예제들을 제공해 주기 때문에 웬만한 UI들은 예제에서 골라서 쓸 수 있다.
이 프로젝트에서는 제일 상단에 있는 ControlP5accodion을 사용하였다.


프로세싱

import processing.serial.*;
import controlP5.*;

ControlP5 cp5;

Accordion accordion;

Serial myPort;

color c = color(0, 160, 100);

byte colors;

void setup() {
  println(Serial.list());
  println(Serial.list()[0]);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  
  size(400, 600);
  noStroke();
  smooth();
  gui();
}

void gui() {
  
  cp5 = new ControlP5(this);
// group number 1, contains 2 bangs
  Group g1 = cp5.addGroup("Random RGB") //Random RGB 이름을 가진 그룹을 추가
                .setBackgroundColor(color(0, 64)) //배경색을 (0,64)로 지정
                .setBackgroundHeight(150) // 높이를 150으로 지정
                ;
  
  cp5.addBang("bang") //bang이란 이름을 가진 Bang을 추가
     .setPosition(10,20) //bang의 좌상단 좌표를 10,20으로 위치시킨다.
     .setSize(100,100) //너비, 높이를 100,100으로 지정
     .moveTo(g1) //그룹1에 추가
     .plugTo(this,"shuffle"); //shuffle기능을 발동시킨다.
     ;
  // group number 2, contains a radiobutton
  Group g2 = cp5.addGroup("SetColor") //SetColor 이름을 가진 그룹을 추가
                .setBackgroundColor(color(0, 64)) //배경색을 (0,64)로 지정
                .setBackgroundHeight(150) // 높이를 150으로 지정
                ;
  
  cp5.addRadioButton("radio") //radio이름을 가진 Radio버튼을 추가
     .setPosition(10,20) //Radio버튼의 좌상단 좌표를 10,20으로 위치시킨다.
     .setItemWidth(20) //너비 20
     .setItemHeight(20) //높이 20
     .addItem("black", 0) //black이름을 가지고 0의 값을 갖는 버튼 추가
     .addItem("red", 1) //red이름을 가지고 1의 값을 갖는 버튼 추가
     .addItem("green", 2) //green이름을 가지고 2의 값을 갖는 버튼 추가
     .addItem("blue", 3) //blue이름을 가지고 3의 값을 갖는 버튼 추가
     .addItem("gray", 4) //gray이름을 가지고 4의 값을 갖는 버튼 추가
     .setColorLabel(color(255)) //글씨의 색을 흰색(255)로 지정. 0일 경우 검정색 글씨가 뜸
     .activate(2) //시작할때 세번째 버튼(0부터 시작)을 활성화 시킨다. 
     .moveTo(g2) //그룹2에 추가
     ;

  // group number 3, contains a bang and a slider
  Group g3 = cp5.addGroup("SetBrightness") //SetBrightness 이름을 가진 그룹을 추가
                .setBackgroundColor(color(0, 64)) //배경색을 (0,64)로 지정
                .setBackgroundHeight(150) // 높이를 150으로 지정
                ;
  
  cp5.addBang("shuffle") //shuffle이란 이름을 가진 Bang을 추가
     .setPosition(10,20) //shuffle의 좌상단 좌표를 10,20으로 위치시킨다.
     .setSize(40,50) //너비, 높이를 40,50으로 지정
     .moveTo(g3)  //그룹3에 추가
     ;
     
  cp5.addSlider("rgbLED1") //rgbLED1이란 이름을 가진 슬라이드 추가
     .setPosition(60,20) //60,20좌표에 위치시킨다
     .setSize(100,20) //너비 100 높이 20
     .setRange(0,100) //슬라이더가 갖는 값을 최소 0 최대 100으로 지정
     .setValue(100) //초기값을 100으로 지정
     .moveTo(g3) //그룹3에 추가
     ;
     
  cp5.addSlider("rgbLED2") //rgbLED2이란 이름을 가진 슬라이드 추가
     .setPosition(60,50) //60,50좌표에 위치시킨다
     .setSize(100,20) //너비 100 높이 20
     .setRange(0,100) //슬라이더가 갖는 값을 최소 0 최대 100으로 지정
     .setValue(100) //초기값을 100으로 지정
     .moveTo(g3) //그룹3에 추가
     ;

  // create a new accordion
  // add g1, g2, and g3 to the accordion.
  accordion = cp5.addAccordion("acc") //acc란 이름을 가진 어코디언 추가
                 .setPosition(40,40) //어코디언의 좌상단 좌표를 40,40으로 지정
                 .setWidth(200) //너비를 200으로 지정
                 .addItem(g1) //그룹1, 그룹2, 그룹3을 포함시킨다
                 .addItem(g2)
                 .addItem(g3)
                 ;
                 
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.open(0,1,2);}}, 'o');
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.close(0,1,2);}}, 'c');
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.setWidth(300);}}, '1');
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.setPosition(0,0);accordion.setItemHeight(190);}}, '2'); 
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.setCollapseMode(ControlP5.ALL);}}, '3');
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {accordion.setCollapseMode(ControlP5.SINGLE);}}, '4');
  cp5.mapKeyFor(new ControlKey() {public void keyEvent() {cp5.remove("myGroup1");}}, '0');
  
  accordion.open(0,1,2);
  
  // use Accordion.MULTI to allow multiple group 
  // to be open at a time.
  accordion.setCollapseMode(Accordion.MULTI);
  
  // when in SINGLE mode, only 1 accordion  
  // group can be open at a time.  
  // accordion.setCollapseMode(Accordion.SINGLE);
}
  

void radio(int theC) { //라디오버튼을 눌렀을 때 생기는 이벤트 함수
  colors = 20;
  myPort.write(colors);
  switch(theC) { //누르는 버튼에 따라 RGB black,gray설정
    case(0):c=color(0,200);colors = 0;myPort.write(colors);break;
    case(1):c=color(255,0,0,255);colors = 1;myPort.write(colors);break;
    case(2):c=color(0, 255, 0,255);colors = 2;myPort.write(colors);break;
    case(3):c=color(0, 128, 255,200);colors = 3;myPort.write(colors);break;
    case(4):c=color(50,128);colors = 4;myPort.write(colors);break;
  }
} 


void shuffle() { //Bang버튼을 눌렀을때 랜덤하게 색상을 뽑아내는 이벤트 함수
  colors = 10;
  myPort.write(colors);
  int r = (int)random(255);
  println(r);
  int g = (int)random(255);
  println(g);
  int b = (int)random(255);
  println(b);
  myPort.write(r); myPort.write(g); myPort.write(b);
  c = color(r,g,b,200);
}


void draw() {
  background(220);
  
  fill(c); //지정된 색으로 채우기 발동
  
  //버튼으로 조절한 값에 의해 타원의 색과 반지름이 결정되어 그려진다.
  float s1 = cp5.getController("rgbLED1").getValue();
  ellipse(300,400,s1*2,s1*2); 
  byte ch1 = (byte)s1;
  myPort.write(30);
  myPort.write(ch1);
  
  float s2 = cp5.getController("rgbLED2").getValue();
  ellipse(300,100,s2*2,s2*2);
  byte ch2 = (byte)s2;
  myPort.write(40);
  myPort.write(ch2);
}
 

프로세싱에서 ControlP5라이브러리를 설치했을때 보이는 ControlP5accordion예제소스이다.
보기에는 길어서 어려워보이나 막상 하나하나 파고들면 이 함수가 무엇인지 쉽게 이해할 수 있다.

인터페이스의 구성을 보면

상단의 이 그룹은 사각형 버튼을 눌렀을 때 랜덤한 색상이 나오게 하는 버튼이다.
누를때마다 랜덤값을 읽어와 랜덤한 색으로 LED를 빛나게 한다.



Bang버튼은 눌렀을 때 버튼에 외형에는 변화가 없는 버튼이다. 
보통 버튼을 눌렀을때는 눌렀을 때와 안눌렀을때로 나뉘어 지지만 Bang버튼은 누를때마다 특정 이벤트가 계속 발생하도록 한다.
여기서는 눌렀을때 계속적인 랜덤색상을 뽑아내게 된다.



두번째 그룹은 좌측의 5개의 버튼을 누를때마다 그 버튼에 해당하는 색상을 나오게 하는 버튼이다. 
클릭했을 경우 밝은 파란색으로 버튼이 바뀐다.



Radio버튼을 인터넷에서 흔히 볼 수 있는 버튼으로 흔히 회원가입이나 설문조사할때 많이 볼 수 있는 버튼이다.
지정된 목록 중 하나만 체크가 가능하게 하는 버튼이다.




세번째 그룹은 좌측의 사각형 버튼은 첫번째 그룹에 있는 셔플버튼과 같은 기능을 하는 버튼이고
두개의 직사각형 버튼은 슬라이드로 LED의 밝기를 조절하는 버튼이다.



슬라이더는 다들 알듯이 드래그를 통해 값을 조절하는 기능을 한다. 

아두이노

byte index; //그룹별 Index값
byte colors; //Group2의 색상값
byte red,green,blue; //RGB별 색상값을 받는 변수
byte brs1, brs2 = 255; //밝기값

//핀번호 int b2 = 3; int g2 = 5; int r2 = 6;
int b1 = 9; int g1 = 10; int r1 = 11; void setup(){ Serial.begin(9600); //시리얼 통신 초기화 for(int i=9;i<12;i++) pinMode(i,OUTPUT); pinMode(b2,OUTPUT); pinMode(g2,OUTPUT); pinMode(r2,OUTPUT); } void loop(){ if(Serial.available()) { index = Serial.read(); if(index == 10) { //Bang버튼(랜덤색상) while(Serial.available() <=0); //값을 받을 때까지 대기 red = Serial.read(); while(Serial.available() <=0); //값을 받을 때까지 대기 green = Serial.read(); while(Serial.available() <=0); //값을 받을 때까지 대기 blue = Serial.read(); setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } else if(index == 20) { //Radio버튼 while(Serial.available() <=0); //값을 받을 때까지 대기 colors = Serial.read(); if(colors == 0) { //LED off red = 0; green = 0; blue = 0; setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } else if(colors == 1) { //Red 표시 red = 255; green = 0; blue = 0; setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } else if(colors == 2) { //Green 표시 red = 0; green = 255; blue = 0; setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } else if(colors == 3) { //Blue 표시 red = 0; green = 0; blue = 255; setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } else if(colors == 4) { //Gray 표시 red = 200; green = 200; blue = 200; setRGBValue1(red,green,blue); setRGBValue2(red,green,blue); } } else if(index == 30) { //슬라이드를 통해 1번 LED 밝기값 조절 while(Serial.available() <=0); //값을 받을 때까지 대기 brs1 = Serial.read(); setRGBValue1((red*brs1)/100,(green*brs1)/100,(blue*brs1)/100); } else if(index == 40) { //슬라이드를 통해 2번 LED 밝기값 조절 while(Serial.available() <=0); //값을 받을 때까지 대기 brs2 = Serial.read(); setRGBValue2((red*brs2)/100,(green*brs2)/100,(blue*brs2)/100); } } } void setRGBValue1(int R, int G, int B) { //1번 LED 밝기 세팅 analogWrite(r1,R); analogWrite(g1,G); analogWrite(b1,B); } void setRGBValue2(int R, int G, int B) { //2번 LED 밝기 세팅 analogWrite(r2,R); analogWrite(g2,G); analogWrite(b2,B); }
아두이노에서는 시리얼통신으로 프로세싱에서 전달받은 값으로 LED를 켜는 역할을 한다.
누르는 버튼에 따라 if문을 통해 여러 조건으로 나뉘게 되고, red값 green값, blue값 3종류의 값으로 RGB를 세팅하게 된다.

예를들어 프로세싱에서 10이라는 값을 처음에 받게 되면 아두이노에서는 10의 값을 통해 프로세싱에서 Bang버튼의 명령을 인식하게 된다.
그 다음에는 RGB값의 전송을 받아야 하기 때문에 값이 전송될 때까지 대기하게 되고 값이 전송되고 나면 각각의 값을 통해 LED를 제어하게 된다.

수박쨈

아두이노, 프로세싱, LED, 시리얼 통신