October 21, 2019

디바이스마트 미디어:

[28호]ICT 융합 공모전 – 모든 온열기에 범용적으로 연결할 수 있는 추가적인 안전장치

ICT 융합 프로젝트 공모전 입선작

모든 온열기에 범용적으로 연결할 수 있는 추가적인 안전장치


심 사 평

싱크웍스 실험 결과가 있었으면 좋았을 뻔했다. 결과를 알 수 없었으므로 완성도를 평가하기 어렵다.
JK전자 보고서를 읽으면서 지금까지 온열기에 왜 이런 장치가 없었나 하는 생각을 하게 되었다. 구현 방법이 어려운 것은 아니지만 작은 아이디어로 실제 제품에도 쉽게 바로 적용도 가능할 것 같은 생각이 들어서 창의성과 실용성에 높은 점수를 주고 싶다.
뉴티씨 온풍기와 같은 온열기로 인한 화재사고로 사망하거나 다치는 것 또는 재산을 잃는 사람들의 수가 해마다 많이 있다. 조금 따뜻해 보려고 쓰던 것이 부주의하게 사용하여 문제가 많이 생기는 경우인데, 이러한 점의 일부분을 개선하여 안전을 높이는 좋은 시도인 것 같다. 온풍기 회사에서 이러한 내용을 참조하여 온풍기의 기능 개선하여 판매한다면, 좋은 반향을 불러일으킬 것 같다. 다만, 거리나 설정 온도 등이 얼마가 되어야 하는지는 실내인지, 실외인지 현지의 상황마다 많이 다를 것으로 예상된다. 따라서, 설정 옵션을 두어 간편 설정, 사용자 세부설정 등과 같이 설정할 수 있도록 하는 것도 중요하리라 생각된다. 이러한 부분이 좀 더 고려되었으면 하는 아쉬움이 있으나, 전체적으로 학생의 입장에서 매우 잘 만든 작품이라 생각된다.
펌테크 실용성이 돋보이는 아이디어 작품입니다. 창의성과 작품 구성상의 난이도는 높지 않으나 아이디어에는 높은 점수를 주고 싶습니다.

1. 작품 개요
온열기 ( 열풍기, 온풍기, 스탠드식 난로 등)는 생각보다 열이 높아서, 춥다고 가까이 있거나, 책상이나 의자 앞에 놓게 되면 화재의 위험 및 화상의 위험이 있다. 실제로 우리 학교에서도 온열기 때문에 화재사고가 날 뻔 하거나 화상을 입은 경우가 적지 않다. 그래서 생각한 것이 모든 온열기에 좀 더 실용적인 안전장치가 있었으면 좋겠다는 것에서 생각해 낸 것이 바로 범용적인 안전장치인 것이다.
이는 온열장치마다 기본적으로 안전장치가 달려있다고는 하지만, 온열기구 자체의 열을 측정하여 적정거리를 그 때 그 때 산출하여 그 이상 접근 시에 경고 메세지를 보낸다거나, 전원을 꺼버리는 온열장치는 찾기 힘들다. 그래서 우리는 간단하게 탈·부착을 할 수 있고, 내열성도 고려하며, 모든 온열 기구에 사용할 수 있는 범용적이면서 저렴한 장치를 제작하게 되었다.
2. 작품 설명
1. 주요 동작 및 특징

모든 온열기 안전장치

주요 동작으로는 맨 처음 온도센서가 켜지고, 온도를 읽어내어 어느 정도의 거리가 안전한지 계산한다. 이는 실시간으로 이루어지며, 사용자가 열의 세기를 조절함에 따라 안전 거리도 달라질 수 있을 것이란 점에 착안하였다. 그 다음, 초음파 센서를 부착하였다. 초음파 센서는 MCU의 Time Interrupts를 사용하여 매 시간마다 앞에 물체가 있는지 없는지 알아본다. 만약 초음파센서에 물체가 감지되면, 자동으로 MCU의 interrupts 가 실행되고, Beep 소리를 내는 함수를 실행하게 되며, 위험 거리 내로 접근할 경우 일정 시간 이후, AC 콘센트와 연결된 차단회로 (릴레이 스위치)가 작동하여 전력을 차단한다. 만약 위험거리까지 접근하였다가 다시 벗어나게 되면, 회로 차단 알고리즘은 종료가 되며 다시 정상적인 작동을 하게 된다.

2. 전체 시스템 구성
(1) 초음파센서
여러 초음파 센서가 있었지만, 우선 시스템에서 요구하는 사양은 1~2미터 사이까지만 측정할 수 있으면 충분하였고, 모듈을 온열 기구에서 열이 나오는 부분이 아닌 부분에 부착을 하는 것이기 때문에 작동 허용범위가 80도 안팎이어야 했으며, 가격을 고려하여 HC- SR04 모델을 채택하였다. 이 초음파 센서는 각각의 입출력 포트를 MCU의 Timer Interrupt Port에 연결하였다.

(2) 온도센서
온도 역시 열이 나오는 곳에 놓긴 하지만, 공중에 놓는 형식이라 작동 허용 범위가 80도 안팎인 것이 필요하였고, 가격 면에서 저렴한 것을 고르다가, LM35라는 제품을 쓰게 되었다. 이는 ADC를 써야하는 부품으로, MCU의 ADC Port에 연결을 하였다.

모든 온열기 안전장치 (1)

(3) 스피커
사용자에게 위험을 알리기 위한 용도로, 간단한 부저음을 요하고, MCU의 GPIO에서 나오는 전압이 3V인 것을 감안하고, 가격 면에서 고려하였을 때, BTM-0327을 쓰게 되었다.

(4) 차단회로 (릴레이 스위치)
릴레이 스위치는 가격 면으로 따져봤을 때, JS1 5V (입력 전압 5V, 스위칭 전압 220V도 되는 소자)로 선택하였다.

(5) MCU
MCU는 우리의 시스템에서 요구하는 사항으로, 저전력, 저렴, 뛰어난 퍼포먼스를 지녀야 한다. 그래서 택한 것이 바로 MSP430G2553을 채택하였다. 이 MCU는 한국에선 잘 알려지지 않은 MCU라 프로그래밍이나 구조 자체가 매우 생소하지만, 요구하는 성능을 만족하기 때문에 사용하게 되었다. 그러나 우리는 MCU에 프로그래밍을 해야하기 때문에, Msp430g2553이달려있는 Launch Pad의 에뮬레이터, 다운로더를 같이 썼다.

(6) LCD + 가변저항
LCD는 원래는 없어도 되는 것이지만, 어떠한 정보 값을 받는지 직접 눈으로 확인하기 위해 구매하였다. 캐릭터 LCD로 만들었으며, 가격이 가장 저렴한 MC1602-13을 구매하였다. LCD 밝기 조절을 위한 가변저항은 Hongxing H3362P Series를 썼다.

3. 개발환경
(1) CCS ( Code Composer Studio v5)
이는 Ti에서 만드는 MCU를 프로그래밍 하여 MCU에 다운로드 할 수 있게끔 만든 Tool이다. 기본적으로 각 모델마다 특화된 레지스터 및 코드를 제공하고, 예제코드까지 바로 볼 수 있는 매우 특이한 툴이다. 게다가 이 툴은 기본적으로 타겟 보드를 각 MCU의 Launch Pad 로 삼고 있는데, 이 보드엔 기존의 PIC 같은 경우는 다운로더만 있어서 실질적으로 디버깅할 때 에뮬레이터가 따로 필요한 상황이 많았다. 하지만 Ti에서 제공하는 개발 보드엔 매우 저렴한 에뮬레이터가 기본적으로 달려있기 때문에 이 Tool을 이용하여 실시간 디버깅을 할 수 있다. 심지어는 MCU의 어떤 레지스터에 어떤 값이 들어가는지 Memory Browser 라는 기능까지 있다. 개발 언어로는 C를 사용하며, USB에 타겟 보드를 연결하여 다운로드, 디버깅을 할 수 있게끔 만들어 놓았다.

모든 온열기 안전장치 (2)

4. 단계별 제작 과정

모든 온열기 안전장치 (3)

위 사진은 MSP430G2553으로 제작한 보드에 한꺼번에 다 꽂을 수 있게 만든 기판이다.

① 초음파 센서를 온열기구 위에 부착하기 위하여 핀으로 빼서 쓸 수 있게끔 하였다.

② 온도센서 역시 온열기구 앞에 위치하게끔 해야 하기 때문에 핀으로 만들었다.

③ 스피커는 보드 위에 직접 부착을 하였다. 소리가 생각보다 크기 때문에 바로 붙였다.

④ LCD는 핀이 총 16개이지만, MCU의 GPIO 개수가 한정적이기 때문에, 8비트 (핀 8개)로 LCD에 띄우고자 하는 내용을 보내는 방법을 쓰지 않고, 4비트씩 나눠서 보내는 방식을 채택하여, 실질적으로 MCU에 꽂히는 핀 개수는 5개 (EN 까지 포함)이다. GND와 VCC는 별도로 붙였다.

⑤ 릴레이 스위치 역시 선을 길게 하여 콘센트에 연결해야 했기에 핀으로 꼽는 방식을 채택하였다.

모든 온열기 안전장치 (4)
⑥ 5V전압 공급은 배터리 홀더 혹은 다른 전원 장치를 쓸 수 있게끔 핀으로 꼽는 방식을 채택하였다.

모든 온열기 안전장치 (5)
⑦ MSP430G2553 보드를 직접 제작하였다. Launch Pad의 에뮬레이터를 쓰기 위해 SBW 포트를 만들었고, 후에 무선통신으로 제어를 할 수 있게끔 UART 포트도 만들어놓았다.

모든 온열기 안전장치 (6)
⑧ LCD를 부착하여 케이스안에 모든 부품을 넣는다

모든 온열기 안전장치 (7)
⑨ 온풍기 위에 부착

모든 온열기 안전장치 (8)
⑩ 릴레이 스위치 연결

모든 온열기 안전장치 (9)

5. 소스코드

Main.c
float temp;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
P2DIR = 0xFF;
lcdinit();
initsona();
readsona();
}
Sona.h
#ifndef SONA_H_
#define SONA_H_
#include <msp430.h>
#include “lcd16.h”
#define P1_ECHO BIT1
#define P1_TRIGGER BIT0
#define P1_LED0 BIT2
#define P1_LED1 BIT3
#define P1_LED2 BIT4
#define P1_LED3 BIT5
#define P1_BUZZER BIT6
#define TH0 5000 /* Distance */
#define TH1 4000
#define TH2 3000
#define TH3 2000
#define TH4 1000
#define TH5 500
void initsona(void);
void readsona(void);
#endif /* SONA_H_ */
Sona.c
#include <msp430.h>
#include “lcd16.h”

 

#include “temp.h”
#include “sona.h”
unsigned int j;
unsigned int measure = 0;
unsigned int measure_1 = 0;
float temp;
void initsona(void) {
//포트 설정을 해줌
P1DIR |= BIT0 +BIT6 + BIT7;
P1SEL |= BIT1;
P1OUT |= 0×00;
BCSCTL1 |= CALBC1_1MHZ;
DCOCTL |= CALDCO_1MHZ;
BCSCTL2 &= ~SELS;
BCSCTL2 |= DIVS0;
TACCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;
TACTL |= TASSEL_2 + MC_2 + ID_0;
_BIS_SR(GIE);// general interrupt enable
}
void readsona(void) {
while (1) {
long i;
temp = readtemp();
P1OUT |= P1_TRIGGER;
for (i = 0; i < 3; i++)
;
P1OUT &= ~P1_TRIGGER;
for (i = 0; i < 8000; i++)
;
}
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TimerA0(void) {
long i;
if ((P1IN & P1_ECHO)> 0){
measure_1 = TACCR0;
TACCTL0 |= CM_3;
} else {
measure = TACCR0 – measure_1;
TACCR0 = 0;
P1OUT &= ~(BIT0 + BIT1);
if (measure > TH0) {
gotoXy(0, 0);
prints(“safe”);
j=0;
} else if (measure > TH1) {
gotoXy(0, 0);
prints(“safe”);
j=0;
} else if (measure > TH2) {
j++;
if(j>50000&&temp>100&&temp<150)
{
gotoXy(0, 0);
prints(“Too close”);
P1OUT |= (BIT7+BIT6);

> TH3) {
j++;
if(j>48000&&temp>=150&&temp<170)
{
gotoXy(0, 0);
prints(“Too close”);
P1OUT |= (BIT7+BIT6);
}
}
else if (measure > TH4) {
j++;
if(j>46000&&temp>=170)
{
gotoXy(0, 0);
prints(“Too close”);
P1OUT |= (BIT7+BIT6);
}
}
for (i = 0; i < 8000; i++)
;
}
TACTL &= ~TAIFG;
P1OUT &= ~(BIT7+BIT6);
}
#pragma vector= ADC10_VECTOR ; // interrupt vector
__interrupt void ADC10(void) {
gotoXy(0, 1);
integerToLcd(temp);
}
Temp.h
#ifndef TEMP_H_
#define TEMP_H_
#include <msp430.h>
#include “lcd16.h”
float readtemp(void);
#endif
Temp.c
#include “temp.h”
#include “lcd16.h”
float temp;
float readtemp(void) {
ADC10CTL0 |= ADC10SHT_2 + ADC10ON + ADC10IE; //
ADC10ON, interrupt enabled
ADC10CTL1 = INCH_4; // input A1
ADC10AE0 |= BIT4; // PA.1 ADC option
select
ADC10CTL0 |= ENC + ADC10SC; // Sampling and
conversion start
temp = (ADC10MEM * 3.7 / 1023.0) * 100;
ADC10CTL0 &= ~ADC10ON;

return temp;
}
LCD.h
#ifndef LCD16_H_
#define LCD16_H_
#include <msp430.h>
#define LCD_OUT P2OUT
#define LCD_DIR P2DIR
#define EN BIT5
#define RS BIT4
#define EN_1 (P2OUT |= EN)
#define EN_0 (P2OUT &= ~EN)
#define RS_1 (P2OUT |= RS)
#define RS_0 (P2OUT &= ~RS)
void waitlcd(unsigned int x);
void lcdinit(void);
void integerToLcd(int integer);
void lcdData(unsigned char l);
void prints(char *s);
void gotoXy(unsigned char x, unsigned char y);
#endif /* LCD16_H_ */
LCD.c
/*
* lcd16.c
*
* Created on: Dec 1, 2011
* Author: Gaurav www.circuitvalley.com
*/
#include “lcd16.h”
void lcdcmd(unsigned char Data) {
RS_0;
EN_0;
LCD_OUT &= 0×00; //clear all data pin.
LCD_OUT |= ((Data & 0xF0) >> 4);
EN_1;
waitlcd(2);
EN_0;
LCD_OUT &= 0×00; //clear all data pin
LCD_OUT |= (Data & 0x0F); // P1OUT |=BIT
EN_1;
waitlcd(2);
EN_0;
}
void lcdData(unsigned char l) {
RS_1;
EN_0;
LCD_OUT &= 0xF0;
LCD_OUT |= ((l & 0xF0) >> 4);

EN_1;
waitlcd(2);
EN_0;
LCD_OUT &= 0xF0;
LCD_OUT |= (l & 0x0F);
EN_1;
waitlcd(2);
EN_0;
}
void lcdinit(void) {
RS_0;
EN_0;
LCD_OUT = (BIT0 + BIT1);
waitlcd(40);
EN_1;
EN_0;
waitlcd(5);
EN_1;
EN_0;
waitlcd(5);
EN_1;
EN_0;
waitlcd(2);
LCD_OUT = BIT1;
EN_1;
EN_0;
lcdcmd(0×28); // Function set -> set data length 4 bit 2 line
waitlcd(250);
lcdcmd(0x0C); //Display on/off control -> set display on
cursor on blink on
waitlcd(250);
lcdcmd(0×01); // Clear display
waitlcd(250);
lcdcmd(0×06); // Cursor or display shift -> cursor shift
direction
waitlcd(250);
lcdcmd(0×80); //Set DDRAM address -> set ram address
waitlcd(250);
}
void waitlcd(volatile unsigned int x) {
volatile unsigned int i;
for (x; x > 1; x–) {
for (i = 0; i <= 110; i++)
;
}
}
void prints(char *s) {
while (*s) {
lcdData(*s);
s++;
}

}
void gotoXy(unsigned char x, unsigned char y) {
if (x < 40) {
if (y)
x |= 0×40;
x |= 0×80;
lcdcmd(x);
}
}
void integerToLcd(int integer) {
unsigned char thousands, hundreds, tens, ones;

thousands = integer / 1000;
lcdData(thousands + 0×30);
hundreds = ((integer – thousands * 1000) – 1) / 100;
lcdData(hundreds + 0×30);
tens = (integer % 100) / 10;
lcdData(tens + 0×30);
ones = integer % 10;
lcdData(ones + 0×30);
}

6. 회로도

모든 온열기에 10

 

Leave A Comment

*