본문 바로가기
프로젝트

아두이노 레이더 프로젝트 - 03. 특수효과 및 코드정리

by Bugwhale 2020. 2. 1.

이 글은 아두이노 레이더 프로젝트 - 03. 특수효과 및 코드정리에 대해 설명합니다.

1. 개요

프로젝트 2편에서 레이더에 모든 기능을 추가하였다. 이번 글에서는 레이더 특수효과를 추가하고 코드를 최적화하는 방법에 대해 소개한다. (사실 소스코드의 최적화 보다는 유지보수하기 쉬운 형태로 만든다.)

2. 레이더 특수효과 추가

import processing.serial.*;
 
int iAngle, iDistance;
 
void setup() {
  size(500, 500);
  // 제일 처음 한번만 해줄 것이기 때문에 setup() 으로 보냄
  background(0, 0, 0);
  Serial myPort;
  myPort = new Serial(this, "COM3", 9600);
  myPort.bufferUntil('\n');
}
 
void draw() {
	// 테두리 없애고
	noStroke();
	// 검정 화면에 불투명도는 25%
	fill(0, 25);
	// 500*500 사이즈의 정사각형을 그려준다.
	rect(0, 0, 500, 500);

	//**************************** 레이더 감지값 출력하자
	// 위에서 만들어준 잔상효과때문에 모든 값들이 겹쳐보이게 된다. 레이더 부분은 상관 없으나
	// 감지된 값은 잘 보여야 하니 따로 사각형위에 값을 출력 시킬 생각이다.
	pushMatrix();
	// 5, 5 만큼 좌표 이동 -> 테두리에서 좀 떨어질려고
	translate(5, 5);
	// 검정으로 체우고
	fill(0);
	// 테두리 색은 초록
	stroke(0, 255, 0);
	// 테두리 굵기는 1픽셀
	strokeWeight(1);
	// 80*50 사이즈의 사각형을 그려준다.
	rect(0, 0, 80, 50);

	// 그 위에 초록색으로 설정하고 감지 값들을 써준다.
	// 이전과 다르게 좌표값들이 조금씩 달라졌다.
	fill(30, 255, 30);
	text("Angle : " + iAngle, 5, 15);
	text("Distance : " + iDistance, 5, 30);
	if(iDistance > 60) {
		text("Not Detected", 5, 45); 
	}
	else {
		text("Detected", 5, 45);
	}
	popMatrix(); 
	//**************************** 레이더를 그려주자
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(1);
	stroke(80, 230, 25);
	for(int i = 1; i <= 4; i ++) {
		arc(0, 0, 100*i, 100*i, PI, TWO_PI);
	}
	for(int i = 0; i <= 180; i += 15) {
		line(0,0,-200*cos(radians(i)),-200*sin(radians(i)));
	}
	popMatrix();
	//**************************** 레이더 침을 그려주자
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(4);
	stroke(80, 255, 25);
	line(0, 0, 200*cos(radians(iAngle)), -200*sin(radians(iAngle)));
	popMatrix();
	//**************************** 감지된 물체 그려주자
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(4);
	stroke(255, 0, 0);
	if(iDistance < 60) {
		float objectDis = 200.0*(iDistance/60.0);
		float x = objectDis*cos(radians(iAngle));
		float y = -objectDis*sin(radians(iAngle));
		ellipse(x, y, 5, 5);
	}
	popMatrix();
	//**************************** 레이더 정보 그려주자
	pushMatrix();
	noFill();
	translate(250, 250);
	for(int i = 1; i <= 4; i ++) {
		text(i*15+"cm", (50*i)-5, 20);
	}
	for(int i = 0; i <= 180; i += 15) {
    	text(i+"°", -220*sin(radians(i-90))-9, -220*cos(radians(i-90))+5);
	}
	popMatrix(); 
}
  
void serialEvent(Serial myPort) {
	String sData, sAngle, sDistance;
	sData = myPort.readStringUntil('\n');
	sData = sData.substring(0, sData.length()-1);
	int seperatorIndex = sData.indexOf("a");
	sAngle = sData.substring(0, seperatorIndex);
	sDistance= sData.substring(seperatorIndex+1, sData.length());
	iAngle = int(sAngle);
	iDistance = int(sDistance);
}

draw() 처음 부분에 잔상효과를 추가하였으며 감지값을 출력하는 부분을 따로 구분하였다. 동작시키면 다음과 같이 출력된다. 잔상효과에 부분에 대해 소스코드를 조금 더 자세하게 설명하자면 noStroke() 통해서 테두리는 없애고(항상 도형을 그리면 빨간색으로 테두리가 생기게 되는 현상을 방지), fill(0, 25)로 검정 화면에 25 % 불투명도를 설정한다. 그 뒤에 창의 크기 만큼의 사이즈(500*500)의 정사각형을 그려준다. rect(0, 0, 500, 500) 이후에 레이더 그리기 소스코드는 모두 이 사각형 위에 그려질 것인데 불투명토가 25 % 다보니 잔상효과가 행기게 된다. 게이머라면 모션블러라는 명칭으로 이해하면 된다.

3. 소스코드 정리

필자는 메인함수, 여기서는 draw() 함수가 한눈에 들어오는 코딩 방식을 선호한다. 위의 코드와 기능면에서 다른점은 없다. 레이더 그리기 부분을 각각 함수에 분할하여 메인함수를 보기 편하게 만들었다.

  • drawRadarValueText(); // 레이더 감지값 그리는 부분
  • drawRadar(); // 레이더 그리는 부분
  • drawRadarHand(); // 레이더 침을 그리는 부분
  • drawRadarObject(); // 감지된 물체 그리는 부분
  • drawRadarInfoText(); // 레이더 정보 그리는 부분
import processing.serial.*;
 
int iAngle, iDistance;
 
void setup() {
	size(500, 500);
	background(0, 0, 0);
	Serial myPort;
	myPort = new Serial(this, "COM3", 9600);
	myPort.bufferUntil('\n');
}
 
void draw() {
	noStroke();
	fill(0, 25);
	rect(0, 0, 500, 500);

	drawRadarValueText();   // 레이더 감지값 출력하자
	drawRadar();       // 레이더를 그려주자
	drawRadarHand();     // 레이더 침을 그려주자
	drawRadarObject();     // 감지된 물체 그려주자
	drawRadarInfoText();   // 레이더 정보 그려주자
}
  
void serialEvent(Serial myPort) {
	String sData, sAngle, sDistance;
	sData = myPort.readStringUntil('\n');
	sData = sData.substring(0, sData.length()-1);
	int seperatorIndex = sData.indexOf("a");
	sAngle = sData.substring(0, seperatorIndex);
	sDistance= sData.substring(seperatorIndex+1, sData.length());
	iAngle = int(sAngle);
	iDistance = int(sDistance);
}

void drawRadarValueText() {
	pushMatrix();
	translate(5, 5);
	fill(0);
	stroke(0, 255, 0);
	strokeWeight(1);
	rect(0, 0, 80, 50);
	fill(30, 255, 30);
	text("Angle : " + iAngle, 5, 15);
	text("Distance : " + iDistance, 5, 30);
	if(iDistance > 60) {
		text("Not Detected", 5, 45); 
	}
	else {
		text("Detected", 5, 45);
	}
	popMatrix(); 
}

void drawRadar() {
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(1);
	stroke(80, 230, 25);
	for(int i = 1; i <= 4; i ++) {
		arc(0, 0, 100*i, 100*i, PI, TWO_PI);
	}
	for(int i = 0; i <= 180; i += 15) {
		line(0,0,-200*cos(radians(i)),-200*sin(radians(i)));
	}
	popMatrix();
}

void drawRadarHand() {
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(4);
	stroke(80, 255, 25);
	line(0, 0, 200*cos(radians(iAngle)), -200*sin(radians(iAngle)));
	popMatrix();
}

void drawRadarObject() {
	pushMatrix();
	noFill();
	translate(250, 250);
	strokeWeight(4);
	stroke(255, 0, 0);
	if(iDistance < 60) {
		float objectDis = 200.0*(iDistance/60.0);
		float x = objectDis*cos(radians(iAngle));
		float y = -objectDis*sin(radians(iAngle));
		ellipse(x, y, 5, 5);
	}
	popMatrix();
}

void drawRadarInfoText() {
	pushMatrix();
	noFill();
	translate(250, 250);
	for(int i = 1; i <= 4; i ++) {
		text(i*15+"cm", (50*i)-5, 20);
	}
	for(int i = 0; i <= 180; i += 15) {
    	text(i+"°", -220*sin(radians(i-90))-9, -220*cos(radians(i-90))+5);
	}
	popMatrix(); 
}

4. 마무리 동작 테스트

필자는 3D 프린터가 있어 필요한 부품을 간단하게 디자인하여 출력하였다.

 서보모터와 PSD 센서가 결합될 커넥터 부분과, 서모모터가 안착될 바디부분이다. 혹시라도 모델링 파일을 사용할 분들을 위해 Arduino Radar(Servo Motor)에 업로드 하였다.

4.1 동작 영상

센서 측정 범위가 60 cm 로 설정해버리니 웬만한건 다 감지가 되버린다. 메인 레이더 프로젝트는 여기서 마치고 추후에 스텝모터를 이용하여 360도 회전 레이더를 만들어볼 계획이다.

 

5. 관련 블로그 글

5.1 프로젝트 관련

[series_list_posts] [series_list_related]

5.2 프로젝트 카테고리

프로젝트

6. 참조

아두이노 홈페이지 프로세싱 홈페이지

댓글