December 28, 2024

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[64호] 안정적이고 강력한 산업용 튜브 인쇄프린터 T-6000 출시

마이클

마이클

마이클앤선솔루션

 

안정적이고 강력한 산업용 튜브 인쇄프린터 T-6000 출시

 

산업 현장에는 대용량으로 다양한 튜브, 라벨의 인쇄 출력을 필요로 하지만 합리적인 가격의 튜브 프린터기는 찾기 어렵다. ‘M&S솔루션’은 국내 산업 현장에서 널리 사용될 수 있는 우수한 품질의 튜브 프린터기인 T-6000 생산하여 출시하였다. ‘T6000’은 10년의 기술 경험을 바탕으로 개발 된 안정적이며 강력한 기능과 디자인 및 12개 이상의 디테일한 기능이 업그레이드된 특허 받은 기술의 튜브 프린터이다. 동급 대비 빠른 인쇄 속도와 특별한 튜브 피드 슬롯을 통해 최대 14mm 넓이까지 인쇄가 가능하여 시간 절약과 사용 범위를 한층 더 높여주었으며, 인쇄 중단시 현재 인쇄한 수량을 LCD 화면으로 볼 수 있어서 편리 하다. 이 LCD 스크린은 총 11가지의 다양한 필요 기능을 표시할 수 있다. 또한 특별한 튜브 피드 입구로 쉽고 편리하게 설치가 가능하며, 자동 Back Off로 자칫 헛되게 버려질 수 있는 소모품 을 절약할 수 있게 해준다. 제품 측면에는 USB 포트가 있어 USB를 통해 쉬운 저장과 불러오기가 가능하여 작업을 더 수월하게 도와주며 인쇄가 가능한 튜브가 한정적으로 정해진게 아니며 PVC 튜브, 투명 튜브, 열수축 튜브, 라벨 테이프 또는 플레이트까지 인쇄가 가능하여 원하는 사이즈 및 튜브에 자유롭게 사용이 가능하다. 라벨의 문구는 표준 83-키 키보드로 편리하게 입력이 가능하며 고속 프린터 헤드를 사용하여 정확하며 깨끗한 인쇄효과를 보장한다. 산업 현장에서 빠르고 많은 양의 튜브 인쇄를 실현시켜주는 T6000의 자세한 정보는 디바이스마트에서 확인할 수 있다.

안정적이고 강력한 산업용 튜브 인쇄프린터 T-6000 출시 제품 바로가기

 

[64호] RPLiDAR A1M8-R6 360도 레이저 스캐너 키트

씨드

 

씨드

SEEED

RPLiDAR A1M8-R6 360도 레이저 스캐너 키트

 

RPLiDAR A1M8-R6 360도 레이저 스캐너 키트는 SLAMTEC에서 개발한 360도 2D 레이저 스캐너 (LIDAR) 솔루션으로 초당 8,000 회 이상의 거리 데이터를 측정하며 시계 방향으로 회전 및 스캔을 시작한다. 이때 거리범위는 0.15-12M에 달한다. RPLiDAR는 변조된 저전력 (<5mW) 적외선 레이저 신호를 방출하고 레이저 신호는 감지할 물체에 의해 반사된다. 레이저는 안전 표준에 따라 매우 짧은 시간 내에 방출된다. 2-10Hz에서 구성 가능한 스캔 속도를 겸비한 RPLiDAR A1의 스캐닝 주파수는 매 라운드마다 360포인트를 샘플링할 때 5.5Hz에 도달했고, 최대 10Hz까지 구성 할 수 있다. 제품 패키지는 RPLiDAR A1, USB 어댑터, RPLiDAR A1 통신 케이블로 구성되어 있으며 플러그 앤 플레이 방식이다. 이 제품을 통해 생성된 2D 클라우드 데이터는 홈 서비스, 매핑, 환경 스캐닝 및 3D 리모델링, 스마트 토이의 위치 파악 및 장애물 회피 등에 활용할 수 있다. 4가지 RPLiDAR 비교표, 데이터시트, 사용설명서 등 자세한 정보는 디바이스마트 상세 페이지를 참고하길 바란다.

 

 

주요 스펙

· 거리 범위 : 0.15m -12m

· 측정 분해능 : <0.5mm

· 각도 해상도 : ≤1 °

· 샘플링 속도 : 2000 ~ 8000Hz

 

RPLiDAR A1M8-R6 360도 레이저 스캐너 키트 제품 바로가기

 

[64호] 인기 고공행진 자체 제작 시리즈, 아두이노 LCD 게임 키트 출시!

디바이스마트 아두이노 LCD

디바이스마트 아두이노 LCD

 

 

디바이스마트

인기 고공행진 자체 제작 시리즈, 아두이노 LCD 게임 키트 출시!

최근 디바이스마트는 아두이노 자체 제작 키트 10번째 시리즈인 ‘아두이노 LCD 게임 키트’를 출시했다.  먼저 출시된 9개의 키트(음주 측정, 자동 화 분 물주기, 초음파, 무선 리모컨, 지문인식, 미세먼지, 일산화탄소감지, 가스 센서, 피아노 키트) 모두 연달아 스테디셀러로 등극하며 아두이노 코딩 시리즈 인기를 이어가고 있다. 디바이스마트 자체 제작 키트인 아두이노 DIY 키트 시리즈는 합리적인 가격은 물론 주 제별로 아두이노 코딩을 접할 수 있는 점, 매뉴얼 및 예제 소스코드를 제공하는 점 등 가성비와 퀄리티 모두 잡은 제품군이다. 새로 출시된 아두이노 LCD 게임 키트는 아두이노, 택트 스위치, 수동 부저, LED, 저항 (10K), LCD 쉴드로 구성되어 있으며, 런닝맨 게임기를 만들어 쉽게 아두이노 코딩 기본 개념과 원리를 익힐 수 있다. 해당 키트는 다가 오는 장애물을 점프하여 피하는 방식의 런닝맨 게임으로, 아이들이 뛰어난 몰입감을 느끼면서 친근하고 재미있게 원리부터 실습까지 한번에 경험해볼 수 있다. 특히 이번 키트의 경우, LCD 모듈과 LCD 쉴드를 통해 두 가지 버전으로 제작해볼 수 있어 활용도가 높다. 배선도, 게임키트 작동 영상 등 더 자세한 정보는 디바이스마트 사이트 를 통해 확인할 수 있다. 어떻게 시작해야 할지 다소 막막한 코딩, 남녀노소 누구나 호기심을 갖고 코딩을 즐길 수 있는 구성의 디바이스마트 아두이노 DIY 키트로 시작해 보는 건 어떨까?

인기 고공행진 자체 제작 시리즈, 아두이노 LCD 게임 키트 제품 바로가기

[64호]Dollying

64 ict dollying (6)

64 ict dollying (1)

ICT 융합 프로젝트 공모전 장려상

Dollying (휴대폰 어플리케이션과 연동 가능한 영상 촬영 장비)

글 | 전남대학교 조유진, 이예찬

1. 심사평
칩센 사회적 트렌드를 이해하고, 그것에 적합한 작품을 목표로 한 창의성이 매우 대단해 보입니다. 목표로 한 결과에 얼마나 근접하였는지에 관한 물음이 생겨 실제 구동 화면이 궁금해지네요. 작품에서 스마트폰 어플을 이용하여 구동을 조작하도록 하였으나, 이 부분을 리모콘의 형태로 만들어 쉽게 제어 및 조작을 할 수 있다면 더 좋을 듯 합니다.
펌테크 세심한 관찰력과 아이디어가 반영된 실생활과 밀접한 작품이라고 생각합니다. 단 출품작의 경우 스마트폰용 APP 구현내용은 확인이 되었으나 스마트폰을 고정하고 구동하게될 하드웨어관련 부분은 초기개발 단계로 판단됩니다. 추후 보완을 통해 상업적으로도 충분한 가치가 있는 제품이 되리라 생각됩니다.
위드로봇 실제 촬영한 수준이 어떠한지 확인할 수 있으면 더 좋은 보고서가 될 것 같습니다.

2. 작품 개요
2.1. 개발배경

64 ict dollying (2)

대한민국 기준, 하루 평균 유튜브 시청 시간은 58.8분으로 다른 프로그램에 비해 사용 시간면에서 월등히 높다. 유튜브 영상 수요의 증가로 유튜브 영상 업로드 시간이 5년 사이에 약 10배 증가하였으며, 업로드 되는 영상 중 42%는 People 카테고리로 Vlog와 같은 개인의 일상에 관련되는 내용을 담고 있다. 이러한 1인 영상 매체가 성장하며 개인 방송장비 매출도 2년 사이에 540% 증가하였다.

2.2. 전동달리

64 ict dollying (1)

영화 촬영 시 사용하는 장비를 최근 소형화, 전동화 시켜서 1인 영상 촬영에 사용되고 있다. 현재 시중에 사용되는 제품은 움직임 설정에 정교함이 없기 때문에 휴대폰 어플을 통해서 섬세한 제어와 다양한 움직임을 가능하게 하는 전동달리 제작을 목표로 하였다.

3. 작품 설명
3.1. 주요 동작 및 특징
외관

64 ict dollying (2)

- 앞바퀴는 방향을, 뒷바퀴는 전진과 후진 기능을 수행한다.
- 윗면의 구멍으로 카메라를 고정한다.

애플리케이션 설명 : UI 디자인

64 ict dollying (3)

① 애플리케이션 시작 화면이다.
② 메뉴화면으로 블루투스 연결과 모드선택(직선 촬영, 원형 촬영, 혼합 촬영)이 가능하다.
③ 직선 촬영 모드 > 이동거리와 이동시간을 입력할 수 있고 기능(순방향, 역방향, 왕복)을 설정이 가능하다.

64 ict dollying (4)

④ 원형 촬영 모드 > 이동반경, 이동시간, 회전각도를 입력 할 수 있고 기능(순방향, 역방향, 왕복)을 설정 가능, 이동반경은 회전 반지름을, 회전각도는 원형으로 회전하는 각도를 의미한다.
⑤ 혼합 촬영 모드 > 직선촬영모드와 원형 촬영 모드를 합친 모드로 직선운동1-원형운동-직선운동2 구조로 구성, 직선운동 1,2구간의 이동거리와 이동시간과 원형운동의 이동반경, 이동시간, 회전 각도를 입력 할 수 있다. 또한 기능(순방향, 역방향, 왕복)을 설정이 가능하다.
⑥ 각 모드에서 실행을 눌렀을 때 넘어가는 화면. 기기 작동 시간이 종료되는 시간을 나타내며 입력 값은 수정이 가능하다.

64 ict dollying (5)

③,④,⑤번 상단의 전동 달리 그림은 설정 값에 따라 움직이며 사용자가 기기 실행 전 움직임을 알 수 있도록 도와준다.
⑥번 상단의 숫자는 기기가 움직이는데 걸리는 시간을 알려주며 시간이 지나면서 감소한다.

3.2 전체 시스템 구성

64 ict dollying (6)

<> 전송의 시작과 끝을 나타내는 구분자
① 촬영 모드(직선 촬영, 원형 촬영, 혼합 촬영)를 결정하는 변수
② 직선 촬영 모드 시 이동거리 변수, 혼합 촬영 모드 시 직선운동 1구간의 이동거리 변수
③ 직선 촬영 모드 시 이동시간 변수, 혼합 촬영 모드 시 직선운동 1구간의 이동시간 변수
④ 원형 촬영 모드 시 이동반경 변수, 혼합 촬영 모드 시 원형운동의 이동반경 변수
⑤ 원형 촬영 모드 시 이동시간 변수, 혼합 촬영 모드 시 원형운동의 이동시간 변수
⑥ 원형 촬영 모드 시 회전각도 변수, 혼합촬영모드 시 원형운동의 회전각도 변수
⑦ 혼합 촬영 모드 시 직선운동 2구간의 이동거리 변수
⑧ 혼합 촬영 모드 시 직선운동 2구간의 이동시간 변수
⑨ 기능(순방향, 역방향, 왕복)을 나타내는 변수

3.3 개발 환경(개발 언어, Tool, 사용 시스템 등)
전동 달리 코딩 : C,C++, Arduiono
애플리케이션 개발 : C#, Unity
전동 달리 모델링 : SOLIDWORKS
어플, 로고 디자인 : Adobe Photoshop,Adobe Illustrator

4. 단계별 제작 과정
·  0 단계: 아이디어 선정
·  1 단계: UI디자인 구성, 전동달리 구조 확정, 사용 부품 선정
·  2 단계: 전동달리 코딩 개발, 애플리케이션 개발, 전동달리 모델링 및 3D프린터 출력
·  3 단계: 3D프린터 파트 조립, 기기 시험 작동 후 코드 수정

1단계 : 어플 디자인 구성

64 ict dollying (3)

 

64 ict dollying (7)

사용부품 선정
· 아두이노 우노 x 1ea
· 아두이노 우노 쉴드 x 1ea
· 스텝모터, 모터 드라이버 x 2ea
· 서보모터 x 1ea
· 배터리 x 1ea
· 배터리 충전 모듈 x 1ea
· 바퀴 x 2ea

2단계 : 전동달리 모델링 및 3D프린터 출력

64 ict dollying (4)

전동달리 코드 개발

//헤더파일

//스테핑모터 정보. 모터 스펙에 맞게 설정
const int stepsPerRevolution = 2048; //28BYJ-48는 1회전당 2048스텝

//핀번호
//블루투스 설정
SoftwareSerial BTSerial(BT_RXD, BT_TXD); // change this to fit the number of steps per revolution

//data 읽기 시작, 종료 상태 변수
bool isStart = false; // 읽기 시작
bool isEnd = false; // 읽기 종료
String resultStr = “”; // 최종 Data를 저장할 문자열

//불루투스에서 받은 값을 나눠서 넣을 값.

//서브모터 설정
Servo servo; // Servo 클래스로 servo 객체 생성
int angle = 0; // Servo 모터의 각도 (0~180)
int stAngle = 82; //Servo 모터 직진용 각도, 82도가 직진, 사용하기 전에 기기마다 맞는 설정값을 입력해줘야 함
double ccAngle = 0; // 원형 운동시 서브모터 각도, 어플에서 넘어온 값으로 변경됨
int tnAngle = 0; // 혼합 운동시 서브모터 각도, 어플에서 넘어온 값으로 변경됨

//바퀴 데이터
int wheelRadius = 3; //바퀴 반지름
float wheelCircum = wheelRadius * 2 * 3.141592; // 바퀴 원주
//직선 운동시 필요 데이터를 계산하기 위한 변수
float stTurnNum = 0; //회전수
float stStepPerRevolution = 0; //step per revolution
float stSpeedNeed = 0; //회전속도(rpm)을 구하기 위해 필요한 변수
float stStepSpeed = 0; //회전속도(rpm)

//원형 운동시 필요 데이터를 계산하기 위한 변수
float ccTurnNum = 0; //회전수
float ccDis = 0; //회전 이동거리
float ccStepPerRevolution = 0; //step per revolution
float ccSpeedNeed = 0; //회전속도(rpm)을 구하기 위해 필요한 변수
float ccStepSpeed = 0; //회전속도(rpm)

//직선 운동3에 필요한 데이터를 계산하기 위한 변수
int stTurnNum3 = 0; //회전수
int stStepPerRevolution3 = 0; //step per revolution
int stSpeedNeed3 = 0; //회전속도(rpm)을 구하기 위해 필요한 변수
int stStepSpeed3 = 0; //회전속도(rpm)

//몸체 데이터
float bodylength = 10; // 몸체 세로 길이. 회전각을 구할 때에 필요

//,를 찾아내기 위한 변수

//회전에 필요한 데이터
int turnAngle = 0;
float turnData = 0;
void setup() {
//통신 설정
Serial.begin(9600); //컴퓨터와의 통신속도 설정
BTSerial.begin(9600); //블루투스와의 통신속도 설정

//Servo 모터 핀 설정
servo.attach(servoPin); //servoPin 데이터는 위에 표기
}

void loop() {

if (BTSerial.available()) {
while (1) {
char val = BTSerial.read(); //블루투스 데이터를 받아와 val변수에 삽입

//데이터 읽기 시작
if (val == ‘<’) {
Serial.println(“start”);
resultStr = “”; // 최종 Data 문자열 초기화
isStart = true;
isEnd = false;
continue; // while문으로 바로 이동
}
// 데이터 읽기 종료
else if (val == ‘>’) {
Serial.println(“end”);
isEnd = true;
break;
}
// 중간 데이터값을 최종 Data 문자열에 추가
else {
resultStr = String(resultStr + val);
}
}

//시작 부호와 종료 부호가 들어왔다면
if (isStart == true && isEnd == true) {
Serial.print(“전송된 데이터 : “);
Serial.println(resultStr);

//컴마 기호 파악
//문자열 나누기

//다음 불루투스 값을 받아들이기 위한 변수 초기화
isStart = false;
isEnd = false;

//직선 운동
if (sep == 2) {
//Serial.println(“직선 운동 모드로 설정되었습니다.”);

//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

//직선운동 스텝모터 작동에 필요한 값 계산
stTurnNum = (float)dis1 / wheelCircum; //회전수
stSpeedNeed = stTurnNum * 60; //계산과정 추후에 정리
stStepPerRevolution = (float)stTurnNum * stepsPerRevolution; //모터 한바퀴가 2048step이기 때문에 stepsPerRevolution을 곱함
stStepSpeed = (float)stSpeedNeed / tim1; //회전속도(rpm)

//직진모드
//후진모드
//왕복모드
else if (mod == 2) {
//Serial.println(“직선운동의 왕복모드가 시작되었습니다.”);
goForward(stStepSpeed, stStepPerRevolution);
goBackward(stStepSpeed, stStepPerRevolution);
}
}

//원형 운동
else if (sep == 3) {

//Serial.println(“원형 운동 모드로 설정되었습니다.”);

// 서보모터 회전각도 계산
// 계산과정은 나중에 따로 정리하겠습니다.
turnData = (float)rad2 / bodylength;
ccAngle = 180 – 2 * atan(turnData);

//서보모터 회전
servo.write(ccAngle); //서보모터 각도 설정
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

//스텝모터 관련 계산
ccDis = (float)0.01756 * ang2 * rad2; //회전 이동거리
ccTurnNum = (float)ccDis / wheelCircum; //회전수. 회전수는 이동거리 나누기 바퀴 원주
ccStepPerRevolution = (float)ccTurnNum * stepsPerRevolution; //step per revolution
ccSpeedNeed = ccTurnNum * 60; //회전속도(rpm)을 구하기 위해 필요한 변수
ccStepSpeed = (float)ccSpeedNeed / tim2; //회전속도(rpm)

//직진모드
//후진모드
//왕복모드
else if (mod == 2) {
//Serial.println(“원형운동의 왕복모드가 시작되었습니다.”);
goForward(stStepSpeed, stStepPerRevolution);
goBackward(stStepSpeed, stStepPerRevolution);
}
}

//회전운동 모드
else if (sep == 4) {

//직선운동1 스텝모터 작동에 필요한 값 계산
stTurnNum = (float)dis1 / wheelCircum; //회전수
stSpeedNeed = stTurnNum * 60; //계산과정 추후에 정리
stStepPerRevolution = (float)stTurnNum * stepsPerRevolution; //모터 한바퀴가 2048step이기 때문에 stepsPerRevolution을 곱함
stStepSpeed = (float)stSpeedNeed / tim1; //회전속도(rpm)

//스텝모터 회전 관련 계산
ccDis = (float)0.01756 * ang2 * rad2; //회전 이동거리
ccTurnNum = (float)ccDis / wheelCircum; //회전수. 회전수는 이동거리 나누기 바퀴 원주
ccStepPerRevolution = (float)ccTurnNum * stepsPerRevolution; //step per revolution
ccSpeedNeed = ccTurnNum * 60; /회전속도(rpm)을 구하기 위해 필요한 변수
ccStepSpeed = (float)ccSpeedNeed / tim2; //회전속도(rpm)

//직선운동3 스텝모터 작동에 필요한 값 계산
stTurnNum3 = (float)dis3 / wheelCircum; //회전수
stSpeedNeed3 = stTurnNum * 60; //계산과정 추후에 정리
stStepPerRevolution3 = (float)stTurnNum * stepsPerRevolution; //모터 한바퀴가 2048step이기 때문에 stepsPerRevolution을 곱함
stStepSpeed3 = (float)stSpeedNeed / tim3; //회전속도(rpm)

//직진모드
if (mod == 0) {
//Serial.println(“회전 운동 직진모드로 설정되었습니다.”);

//직진1
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

//직선운동에서 스텝모터 움직임
goForward(stStepSpeed, stStepPerRevolution);

//회전
// 계산과정은 나중에 따로 정리하겠습니다.
turnData = (float)rad2 / bodylength;
ccAngle = 180 – 2 * atan(turnData);

//서보모터 회전
for (int i = 0; i < ccAngle; i++) {
turnAngle += 1;
servo.write(turnAngle); //서보모터 각도 설정
}

//스텝모터 관련 계산
ccDis = (float)0.01756 * ang2 * rad2; //회전 이동거리
ccTurnNum = (float)ccDis / wheelCircum; //회전수. 회전수는 이동거리 나누기 바퀴 원주
ccStepPerRevolution = (float)ccTurnNum * stepsPerRevolution; //step per revolution
ccSpeedNeed = ccTurnNum * 60; //전속도(rpm)을 구하기 위해 필요한 변수
ccStepSpeed = (float)ccSpeedNeed / tim2; //회전속도(rpm)
goForward(ccStepSpeed, ccStepPerRevolution);

// 직진3
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

goForward(stStepSpeed, stStepPerRevolution);
}

else if (mod == 2) {
//Serial.println(“회전 운동 왕복모드 직진부로 설정되었습니다.”);

//직진1
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

//직선운동에서 스텝모터 움직임
goForward(stStepSpeed, stStepPerRevolution);

//회전
// 계산과정은 나중에 따로 정리하겠습니다.
turnData = (float)rad2 / bodylength;
ccAngle = 180 – 2 * atan(turnData);

//서보모터 회전
for (int i = 0; i < ccAngle; i++) {
turnAngle += 1;
servo.write(turnAngle); //서보모터 각도 설정
}

//스텝모터 관련 계산
ccDis = (float)0.01756 * ang2 * rad2; //회전 이동거리
ccTurnNum = (float)ccDis / wheelCircum;  //회전수. 회전수는 이동거리 나누기 바퀴 원주
ccStepPerRevolution = (float)ccTurnNum * stepsPerRevolution; //step per revolution
ccSpeedNeed = ccTurnNum * 60;  //회전속도(rpm)을 구하기 위해 필요한 변수
ccStepSpeed = (float)ccSpeedNeed / tim2;  //회전속도(rpm)

goForward(ccStepSpeed, ccStepPerRevolution);

// 직진3
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500);  //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

goForward(stStepSpeed, stStepPerRevolution);

//Serial.println(“회전 운동 왕복모드 후진부로 설정되었습니다.”);
//직진1
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

//직선운동에서 스텝모터 움직임
goBackward(stStepSpeed, stStepPerRevolution);

//회전
// 계산과정은 나중에 따로 정리하겠습니다.
turnData = (float)rad2 / bodylength;
ccAngle = 180 – 2 * atan(turnData);

//서보모터 회전
for (int i = ccAngle; i > 0; i–) {
turnAngle -= 1;
}
servo.write(turnAngle); //서보모터 각도 설정

//스텝모터 관련 계산
ccDis = (float)0.01756 * ang2 * rad2; //회전 이동거리
ccTurnNum = (float)ccDis / wheelCircum; //회전수. 회전수는 이동거리 나누기 바퀴 원주
ccStepPerRevolution = (float)ccTurnNum * stepsPerRevolution; //step per revolution
ccSpeedNeed = ccTurnNum * 60; //회전속도(rpm)을 구하기 위해 필요한 변수
ccStepSpeed = (float)ccSpeedNeed / tim2; //회전속도(rpm)

goBackward(stStepSpeed, stStepPerRevolution);

// 직진3
//직선운동에서 서브모터 각도 수정
servo.write(stAngle); //변수 값으로 고정했습니다. 장치 개발 후 수정이 필요합니다.
delay(500); //서브모터가 돌고 바로 스텝모터가 도는 것을 방지하기 위해 잠깐의 텀을 둡니다.

goBackward(stStepSpeed, stStepPerRevolution);
}

}
//변수초기화 혹시 몰라서 넣어봅니다.
turnAngle = 0;
}
}
void goForward(float a, int b) {
rightStepper.setSpeed(a);
leftStepper.setSpeed(a);
for (int i = 0; i < b; i++) {
rightStepper.step(1);
leftStepper.step(-1);
}
}

void goBackward(float c, int d) {
rightStepper.setSpeed(c);
leftStepper.setSpeed(c);
for (int i = 0; i < d; i++) {
rightStepper.step(-1);
leftStepper.step(1);
}
}

어플리케이션 개발

① BT_connect -
블루투스를 이용하여 개발 어플과 Dollying(기기)을 연동

using TechTweaking.Bluetooth; // BT 제어 모듈
public class BT_connect : MonoBehaviour
{
private BluetoothDevice device;

BT연결 설정
private void Awake()
{
BluetoothAdapter.enableBluetooth(); //Force Enabling Bluetooth
device = new BluetoothDevice();
device.Name = “BT1″; // 내 블루투스 이름
}
public void connect()
{
device.connect();
}

public void disconnect()
{
device.close();
}
}
② 어플 페이지 설정

void Start()
{
ContextChanger(“1Page1″); // 앱 실행시 로고 출력

// 2초 후 2Page2 내용 출력
Invoke(“ShowFirstContext”, 2f);
}
public void ShowFirstContext()
{
ContextChanger(“2Page2″);
}
//콘텐츠 활성화 및 비활성화 처리
/// <param name=”conName”>콘텐츠 활성화 시킬 게임오브젝트 이름</param>
public void ContextChanger(string conName)
{
for (int i = 0; i < contextArr.Length; i++)
{
if (contextArr[i].name == conName)
{
if (i != 5) prevContextName = conName;

contextArr[i].SetActive(true);

if (i < 5) menu = i;
switch (i)
{
case 2:
mode = dirType1;
break;
case 3:
mode = dirType2;
break;
case 4:
mode = dirType3;
break;
default:
break;
}
}
else
{
contextArr[i].SetActive(false);
}
}
}
// 직전 설정 화면으로 이동하는 함수
public void BackToModify()
{
ContextChanger(prevContextName);
}
③ 블루투스로 데이터 전송하기
public void SendDataToBt()
{
if (device != null)
{
string distance1;
string time1;
string distance2;
string time2;
string angle2;
//혼합이동을 위해 나누어 처리
if (menu == 4)
{
distance1 = inputField[7].text; //어플을 통해 사용자로 부터 입력받은 데이터를 변수값에 넣어줌
time1 = inputField[8].text;
distance2 = inputField[9].text;
time2 = inputField[10].text;
angle2 = inputField[11].text;
}
else
{
distance1 = inputField[0].text;
time1 = inputField[1].text;
distance2 = inputField[2].text;
time2 = inputField[3].text;
angle2 = inputField[4].text;
}

string distance3 = inputField[5].text;
string time3 = inputField[6].text;
string menu1 = menu.ToString();
string mode1 = mode.ToString();

//아두이노가 값을 읽어처리하는 형식과 동일하게 구성시켜 데이터를 보내줌
string resultStr = “<” + menu1 + “,” + distance1 + “,” + time1 + “,” + distance2 + “,” + time2 + “,” + angle2 + “,” + distance3 + “,” + time3 + “,” + mode1 + “>”;
device.send(System.Text.Encoding.ASCII.GetBytes(resultStr));
Debug.Log(resultStr);
//t.GetComponent<Text>().text = resultStr;

// 타이머 설정(마지막 페이지(잔여시간 보여주기 기능)를 위해)
timer = 0;
switch (menu)
{
case 2:
timer = int.Parse(time1);
if (mode == 2)
{
timer *= 2;
}
break;
case 3:
timer = int.Parse(time2);
if (mode == 2)
{
timer *= 2;
}
break;
case 4:
timer = int.Parse(time1) + int.Parse(time2) + int.Parse(time3);
if (mode == 2)
{
timer *= 2;
}
break;
default:
break;
}

maxTimer = timer;
timerGuage.fillAmount = 1f;
// 타이머 UI 실행 및 타이머 감소
StartCoroutine(TimerCoroutine());
}

3단계 : 3D프린터 파트 조립

64 ict dollying (5)

기기 시험 작동 후 코드 수정

64 ict dollying (6)

5. 기타
5.1 회로도

64 ict dollying (8)

5.2 플레이스토어 등록

64 ict dollying (9)

5.3 특허 출원

64 ict dollying (10)

 

5.4 계산 과정
스텝 모터가 움직이는 데 필요한 값 계산
계산을 시작하기 전에 알아야 하는 값

1. 스텝모터가 1회전이 몇 개의 스텝으로 이루어져 있는지 여부

2. 바퀴 반지름.
· 왼쪽 모터의 1회전에 필요한 스텝은 8이다.
· 디바이스마트에 나와있는 스텝모터 (SZH-EK060) 사양

64 ict dollying (11)
Step angle이 5.425。이고 감속비는 1/64이므로 1스텝 0.084765625。당 회전한다. 360÷0.084765625 ≒4247이지만 모터드라이버의 full step모드에서는 1/2한 근사치인 2048을 이용한다.

애플리케이션에서 전송받는 값
1. 기기의 이동거리, 2. 기기 이동에 걸리는 시간

구해야 하는 값
1. 스텝모터의 회전속도는 rpm단위이기 때문에 위의 값들을 활용하여 rpm값을 구해야 한다.
2. 해당 거리만큼 이동하는 데 필요한 스텝 수를 알아야 한다.

회전에 필요한 스텝 수 구하기
1. 바퀴의 원주를 알아야 하므로 2πr(r은 반지름)을 통해서 원주를 알아낸다.
2. 이동 거리를 원주로 나누어 바퀴의 회전수를 구한다.
3. 회전수에 스텝 모터 한바퀴 스텝을 곱하여(이번 프로젝트에 사용한 스텝모터의 1회전에 필요한 스텝은 2048) 이동에 필요한 스텝을 알 수 있다.

회전속도 구하기
1.  64 ict dollying (12)을 이용한다.

2. 회전 반지름에 따른 회전 각도 구하기

64 ict dollying (13)
r= 회전 반지름
L= 기기 길이
α=  64 ict dollying (14)

빨간 삼각형과 주황 삼각형은 합동이므로 θ=180-2α이다.

[64호]Fire Guard

64 ICT 파이어가드 (8)

64 ICT 파이어가드 (1)

ICT 융합 프로젝트 공모전 장려상

Fire Guard

글 | 대구카톨릭대학교 한진효, 김현준, 서동운, 최동근

1. 심사평
칩센 화재 등을 방지하기 위한 쓰레기통의 아이디어는 꽤 많이 있는 것이 사실입니다. 여러 가지 센서를 조합하고, 그것을 통하여 화재를 미연에 방지한다는 것 또한 거의 대동 소이한 방식을 취합니다. 다만 지원자께서 취합한 구조를 보면 실제 제품에 적용하기에 용이하게 시제품을 제작하신 것으로 보입니다. 제작된 시제품 영상을 통해 추가적인 아이디어를 고민하게 되네요. 상부 물 보관함을 방화수 또는 담배꽁초 재떨이로 공용 활용하고, Solar cell 패널을 적용하여 배터리를 보완하고, 구현하신 방식으로 화재를 예방할 수 있다면 아이디어 상품으로도 충분히 가능성이 있어 보입니다.
펌테크 실생활에 활용될 수 있는 실용적인 작품이라고 판단됩니다. 출품작에서 중요한 역할을 하는 하우징 구성이 잘 구성되었고, 완성도 또한 높은 작품이라고 생각합니다.

2. 작품 개요 및 필요성
우선 이 화재방지 쓰레기통을 만들게 된 계기는 기차역, 아파트, 음식 가게 주변 등 흡연장이 있는 곳 또는 흡연장이 아님에도 불구하고 흡연을 많이 하는 곳에서 담배꽁초와 화재의 원인이 되는 쓰레기를 버려 그것으로 인한 피해를 막고 화재를 줄이기 위해 만들게 되었습니다.
현재 국외뿐만 아니라 국내에서도 화재는 큰 재산 피해와 사람의 생명을 위협하는 부분으로 이어지고 있는데 화재를 막기 위해 만들어진 해결방안은 항상 부실했으며 그로 인해 화재방지가 되지 않아 초기진압을 하지 못해 큰 화재로 이어지는 경우가 많았습니다.
화재의 원인을 알고 방지하기 위해 모든 부분을 보완하고 대처할 수는 없지만 무엇 때문에 화재가 가장 자주 발생할까? 라는 생각과 동시에 알아 보게 되었습니다.

64 ICT 파이어가드 (2)

기초적으로 그래프와 같이 대부분 화재의 원인은 모두 사람의 부주의로 인해 발생하는 경우가 다른 모든 요인을 합친 값보다 많았고 부주의 중에서도 흡연으로 인한 담배꽁초의 경우가 가장 높았습니다. 물론 다른 화재도 배제할 수는 없지만, 이 화재의 원인을 줄이고, 화재 초기진압으로 큰 화재를 예방할 수 있다면 많은 화재로 인한 생명 피해와 재산 피해를 막을 수 있을 거 같습니다.

2.1. 담배꽁초 및 쓰레기통 화재 사건 피해 사례
1. 국외 화재 피해 사례

64 ICT 파이어가드 (1)
1973년 브라질에서 일어난 비행기 사고의 주요 원인은 화장실 쓰레기통에 던져진 담배꽁초로부터 발생된 화재 때문이었습니다. 이로 인해 정비가 불가할 정도로 비행기가 파손되었으며, 수많은 인명 피해를 입혔습니다. 작은 부주의로 인해 시작된 화재의 결과는 조종수 한 명을 제외한 나머지 모든 승객은 일산화탄소 중독으로 사망했습니다. 초기진압이 빨랐다면 재산의 피해와 많은 생명을 구할 수 있었을 것으로 생각되며 초기 진압의 중요성을 한 번 더 되새길 수 있었습니다.

2. 국내 화재 피해 사례
2014년 경기도 버스정류장에서 일어난 화재 사건의 경우에는 한 시민의 빠른 초기진압으로 큰 화재로 번지지는 않았지만 이 화재 사건의 원인도 사람의 부주의로 담배꽁초를 쓰레기통에 버려 일어난 국내 사건 사례로 들 수 있습니다.

64 ICT 파이어가드 (3)

2018년 부산의 한 고층아파트에서 주민이 쓰레기통에 불이 덜 꺼진 담배꽁초를 버려 일어난 사건입니다. 이 사건으로 아파트 입주민 100여 명이 대피하였고 다행히 아파트의 스프링클러가 작동해 화재를 빠르게 진압할 수 있었습니다. 이 사건은 빠른 화재 진압으로 아파트 복도의 벽면을 태워 30만 원의 재산 피해로 마무리가 되었지만, 초기진압이 되지 않았다면 큰 화재로 번질 수 있는 사건이었습니다.
이 사건에서 들었던 생각은 사건의 장소가 아파트라서 스프링클러가 정상작동하여 빠르게 진압 할 수 있었지만 만일 이 사건의 비슷한 사례로 사람이 적은 곳에서 발생하였다면 재산의 피해와 생명의 위협이 될 수 있었다고 생각합니다.

3. 작품설명
3.1. 주요 동작 및 특징
주요 동작은 쓰레기통 내부에 화재가 발생하거나 의심 사항을 발견했을 때 불꽃감지 센서가 이를 감지한 후 Arduino로 제어하여 불꽃감지 센서를 입력값을 읽고 판단하여 급수펌프의 작동하여 물탱크의 물을 사용하여 화재를 진압합니다. 그 후 화재가 완전히 진압되었다고 판단되면 펌프의 사용을 중단합니다.

3.2. 전체 시스템 구성
시스템 구성은 최대한 간단한 방식을 사용하기로 했다. 코드는 불꽃 센서의 값을 기준으로 if 조건문으로 상황을 제어했습니다. 불꽃감지 센서의 값이 둘 중 하나라도 일정 이하로 내려갈 경우 워터 펌프가 작동합니다. 불꽃감지 센서가 둘 다 일정값 이상이면 워터 펌프를 추가적으로 제어합니다. 이때 이전에 워터 펌프가 작동을 했을 경우 일정 시간을 더 작동하여 화재를 진압하고 일정 시간이 지난 후 작동이 중지하게 설정했습니다.

4. 단계별 제작과정
4.1. 아이디어 도출, 자료조사
미세먼지 감지 창문, 층간소음과 관련된 아이디어 등 여러 아이디어를 내는 도중 대구가톨릭대학교 입구에 ‘火가 모여 炎이 된다.’는 플래카드가 걸려있던 것이 생각났습니다. 그리고 매 학기 쓰레기통에서 담배꽁초로 인해 쓰레기들이 일부 태워지는 사례가 빈번하게 일어났기 때문에 화재와 관련된 아이디어로 해보자는 의견에 모두가 동의하였습니다. 화재를 조사하던중 쓰레기통의 화재로 인해 피해가 발생했던 뉴스 기사가 생각보다 많았습니다. 그렇다면 화재를 방지하는 쓰레기통은 없을까? 의문점이 들어 화재방지를 위한 쓰레기통을 조사해보았습니다.
아이디어를 실현하기 위해서 적재적소에서 불을 감지하여 물을 뿌리는 방식을 생각했고, 어떤 센서를 사용해야 할지 다양한 의견이 나왔습니다. 화재 발생 시 온도를 감지하는 온도 센서, 불이 커지면서 발생하는 연기를 감지하는 센서, 불을 감지하는 불꽃 센서를 사용하자 등 다양한 센서의 종류를 언급했었습니다. 팀 회의를 통해 온도 센서는 외부의 온도로 인해 오작동할 우려와 인식범위가 좁고, 연기 센서의 경우 화재 발생 시 연기가 발생이 안 될 수도 있는 변수를 고려해서 불꽃을 확실하게 인식할 수 있는 불꽃 센서로 결정했습니다, 불꽃 센서는 인식범위는 넓진 않지만 주변 환경의 빛의 차단방법에 따라 범위의 조정이 가능한 장점이 있습니다.

4.2. CATIA 모델링
설계를 위해서는 CAD 프로그램을 사용해야 했습니다. 다양한 설계 프로그램이 있지만, 그중에서 학교교육과정에서 배웠던 CATIA라는 프로그램을 사용하여 설계했습니다.

4.2.1. 문제점 발생과 모델링 수정
처음에는 시중에 판매하는 쓰레기통을 구하여 센서와 모터 등의 부품을 설치하려 하였으나 크기와 재질 등 여러 부분에서 계획했던 생각과 달라 설계를 직접하고 적절한 부품을 이용하여 새로 제작하자는 의견으로 바뀌었습니다. 그렇게 하여 직접 가공을 해야 하는 견해로서 가공의 편의성을 중점으로 설계를 했습니다.

64 ICT 파이어가드 (4)

1안의 장점은 견고함이었습니다. 하지만 그 견고함을 유지하기 위해서는 최소 10t 이상의 알루미늄 Plate를 사용하여야 했으며 이는 Prototype에 큰 비용이 들어가는 문제점에 직면하게 되었고 견고함은 유지하되 비용의 문제를 해결하려 2안에서의 알루미늄 Profile을 적용했습니다.

4.3. Arduino 코딩
하드웨어를 제작하면서 동시에 코딩을 시작했습니다.
우리 팀이 만들려는 화재방지 쓰레기통은 최근 시중의 전자제품에 있는 제어기, 센서, 구동기를 모두 사용하고 있습니다. Arduino는 제어기로서 각종 디지털 신호의 입력 및 출력을 제어하는 MCU의 종류 중 하나로 학생들이 손쉽게 접근할 수 있어 사용했습니다. 센서는 불꽃 센서를 사용하였으며 워터펌프를 구동기로 사용했습니다.
코딩에 대해 간략하게 설명해 드리자면 Arduino가 불꽃에 대한 외부의 정보를 입력받아 코딩한 내용에 따라 워터펌프로 출력 신호를 주어 제어하는 방식입니다.

4.3.1. 설계한 코딩

const int a = 8;
const int b = A0;
const int c = A1;
int x;
//a는 워터펌프 b,c는 센서
//a는 8번핀에 연결 b,c는 각각 A0,A1에 연결

void setup()
{
pinMode(a, OUTPUT);
Serial.begin(9600);
x=0;
}

void loop()
{
int lax1 = analogRead(b);
int lax2 = analogRead(c);
if(lax1<500||lax2<500)
{
digitalWrite(a, HIGH);
Serial.print(lax1);
Serial.print(” “);
Serial.println(lax2);
x=1;
delay(50);
}
else
{
if(x==1)
{
delay(5000); // 센서가 인식범위를 벗어났을때 워터펌프가 일정시간 더 작동하기 위한 시간 1000=1초
x=0;
}
else if(x==0)
{
digitalWrite(a, LOW);
Serial.print(lax1);
Serial.print(” “);
Serial.println(lax2);
}
delay(50);
}
}
// Serial 코딩은 문제를 확인하기 위한 코딩이므로 정상적으로 작동한다 생각시 삭제해도 상관없다
// 센서 인식범위를 늘릴 생각이면 if조건문에 500을 조정하면된다. 숫자가 높아질수록 민감해지고 최대 1023까지 조정 할수 있다

4.3.2. 워터펌프 및 센서의 테스트
제작한 형태에 적용 전 워터펌프, 불꽃 센서, Arduino 보드 등 코딩에 대한 오류는 없는지와 부품의 이상 유무를 확인하기 위해 3번에 걸쳐 작동을 확인했습니다.

64 ICT 파이어가드 (2)

64 ICT 파이어가드 (5)

펌프 테스트 : 펌프의 정상작동 여부를 확인하기 위해 물통에 물을 받고 배터리를 이용하여 전원을 공급하며 물을 끌어오는 것과 분출의 과정을 직접 확인했습니다.
펌프와 불꽃 센서 연결 : 펌프, Arduino 보드, 불꽃 센서 하나를 사진처럼 임의로 연결하여 불꽃 센서가 라이터의 불빛을 정상적으로 감지하는지와 불빛의 감지에 따라 펌프가 정상 작동되는지 확인했습니다.
완전 결합 테스트 : 배터리, 펌프, Arduino 보드, 불꽃 센서 두 개, Bread Board를 완전 결합 후 합판에 고정해 모든 부품이 정상적으로 작동되는지 확인했습니다.

4.4. 제품 제작

4.4.1. 하드웨어 제작부품
알루미늄 Profile : 1안의 알루미늄 Plate의 대체품으로 외형제작에 사용하였으며 지지하는 역할.
M5 볼트 (10mm) : 인서트 너트 또는 스프링 너트와 함께 채결하는 역할.
인서트 너트 : M5 볼트와 함께 체결하는 역할.
스프링 너트 : M5 볼트와 함께 체결하는 역할.
브라켓 : 프로 파일 간의 체결 시 프로 파일이 움직이지 않게 고정하는 역할.

4.4.2. 소프트웨어 제작부품
Arduino UNO 보드 : Arduino UNO는 센서와 액추에이터를 제어하는 장치로 간단한 오픈 소스를 제공하고 일반인이 쓰기 쉬운 MCU 중 하나입니다.
불꽃 센서 : 적외선 LED를 통해 불꽃에서 감지되는 적외선 파장을 감지하여 아날로그 혹은 디지털신호로 변환해주는 역할을 합니다.
워터펌프 : 수조의 물을 끌어 올리고 물을 배출하는 역할을 합니다.
워터펌프 드라이버 모듈 : 아두이노 회로만으로는 펌프에 충분한 전류의 양을 공급할 수 없고 전류의 제어가 어렵다. 드라이버 모듈을 통해 펌프를 쉽게 제어할 수 있게 합니다.
PVC 배관 : 수조-펌프-노즐을 연결함으로 물의 이동에 관여하는 역할.
스프레이 노즐 : PVC 배관으로부터 물을 받아 다방면으로 물을 뿌리는 역할을 합니다.

64 ICT 파이어가드 (3)

2안 제작
1. 브라켓, 너트, 볼트를 이용하여 Profile을 연결했습니다.
2. 쓰레기통에 구멍을 뚫어 아크릴 봉을 연결했습니다.
3. 쓰레기통의 회전반경을 확인합니다.
4. 소프트웨어와 완전 결합된 합판과 센서를 장착합니다.
5.  수조를 설치하여 정상작동 여부를 확인합니다.
▶ 쓰레기통의 회전반경 등 괜찮았으나 쓰레기봉투 교체의 용이성에 불편함을 발견했습니다.

4.5. CATIA 재 모델링 및 제작수정

64 ICT 파이어가드 (6)

쓰레기통을 없애고 4방향과 아래 바닥 방향에 판을 설치하고 한 쪽방형에 경첩을 설치하여 여닫을 수 있는 형태로 새로 CATIA 모델링 하여 수정하였습니다. 이를 통해 쓰레기봉투 교체의 용이성을 기대해 볼 수 있었습니다.

64 ICT 파이어가드 (4)

3안 제작수정 : 3안으로 모델링 수정할 때 기대했던 쓰레기봉투의 교체 용이성을 확보했습니다.

4.6 실 제품 성능 TEST & 문제점 보완
불꽃을 감지하였을 때 불꽃 센서가 불빛을 정상적으로 감지하는지와 불빛의 감지에 따라 펌프가 정상작동되는지 확인하였으며 이상 없이 작동되었음을 확인했습니다.

64 ICT 파이어가드 (5)

5. 기타
5.1. 부품 재료

64 ICT 파이어가드 (7)

5.2. 회로도

64 ICT 파이어가드 (8)
제어를 위한 MCU는 Arduino를 기반으로 두 개의 불꽃감지 센서를 이용하여 입력 값의 크기를 Arduino에서 판단하고 둘 중 하나의 센서값이 일정 이하로 내려가게 되면 워터펌프가 작동되는 간단한 구조로 이루어져 있습니다.