November 20, 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

[59호]SYZYGY 호환 확장 기능을 갖춘 Zynq-7000 SoC 개발 보드 Eclypse Z7 출시

cd

Digilent

SYZYGY 호환 확장 기능을 갖춘 Zynq-7000 SoC 개발 보드 Eclypse Z7 출시

글로벌 전기 공학제품 브랜드 디질런트 에서는 설계 흐름을 가속화 할 수 있는 최 신 FPGA / SoC 개발 보드인 Eclypse Z7 를 출시하였다. Eclypse Z7은 모듈식 확장 을 위한 고속 Zmod 포트와 Digilent의 Xilinx Zynq®-7020 SoC 및 소프트웨어 API를 특 징으로 빠르고 유연하며 엔지니어와 연구원이 혁신적이고 강력한 고속 계측을 개발하는 데 걸리는 시간을 단축해 준다. 또한, 개방형 소프트웨어 API와 Digilent의 새로운 Eclypse 하드웨어를 결합한 Eclypse 플랫폼 형태인 Eclypse Z7은 기본적으로 Petalinux가 지원되며, 사전 구축 된 Linux 이미지에는 대량 데이터 전송을 위한 API 가 함께 제공된다. 이 시스템을 통해 사용자 는 원하는 Zmod를 연결하고, 원하는 때까지 FPGA와 직접 인터페이스하지 않고도 새로운 고속 측정, 계측 및 제어 시스템 프로토 타이 핑을 시작할 수 있다. Z m o d는 O p a l K e l l y의 오픈 소 스인 SYZYGY 표준을 사용하는 Digilent의 새로운 확장 솔루션이다. 기존 Pmod보다 빠르 며 FMC보다 더 작고 비용 효율적고, 고속 I/ O 대한 사용자 지정 옵션을 개선한다. 이러한 Eclypse Z7은 엣지 컴퓨팅, 의료 및 통신 애 플리케이션을 위한 제어 및 측정 시스템으로 적합하며, 디바이스마트에서는 Eclypse Z7 외에도 다양한 Digilent의 제품들을 만나 볼 수 있다.

주요 특징

· 667MHz 듀얼 코어 Cortex-A9 프로세서

· 1066 MT/s에서 32 비트 버스가 있는 1GiB DDR3L

· SYZYGY 표준 인터페이스 사양에 따른 2개의 포트

· 외부 12V 5A 전원 공급

 Eclypse Z7  바로 확인하기

[59호]초간단 아두이노 음성인식 키트 출시

c

디바이스마트

초간단 아두이노 음성인식 키트 출시

사물인터넷 (IoT) , 인공지능 (AI) 기술이 실 생활에 다양하게 적용되면서 이러한 기술들 을 더욱 편리하게 만들어주는 음성인식 기술 에 관한 관심도 더욱 커지고 있다. 음성인식 기술은 컴퓨터가 마이크와 같은 소리 센서를 통해 얻은 음향적 신호를 단어나 문장으로 변 화시키는 것을 의미하며, 단순한 소리가 기술 을 통해 디지털 정보로 변환되어 여러 분야에 활용할 수 있는 데이터가 된다. 음성인식 기술 이 사용된 대표적인 제품으로는 음성인식 스 피커나, 스마트폰의 음성인식 기능부터 세탁 기, 에어컨 가전제품에도 이러한 기술이 접목 되고 있다. 이처럼 앞으로의 발전 가능성이 무궁무진한 음성인식기술을 학생들이나 엔지니어들이 손 쉽게 이용할 수 있도록 디바이스마트에서는 음성인식 키트를 출시하였다. 이 음성인식 키트는 15개의 음성인식 명령어 저장이 가능한 음성인식 모듈을 이용하여 도트 매트릭스에 음성명령어를 직접 표현해 보며 음성인식 기 술에 대한 원리를 이해하고, 더 나아가 나만의 IoT 프로젝트에 활용해 볼 수 있는 특징이 있 다. 음성인식 기술에 필요한 제품만 모아 편리 하게 사용할 수 있게 구성하였고, 관련 소스 코드, 매뉴얼 또한 제공하고 있기에 처음 접하 는 학생들도 손쉽게 따라 할 수 있다. 오직 디 바이스마트에서만 만나 볼 수 있는 제품으로 IoT, AI, 음성인식에 관심이 있는 고객에게는 가성비 좋은 음성인식 키트를 추천한다. 제품구성은 음성인식 모듈, 아두이노 우노 R3 호환보드, 브레드보드, USB to TTL 컨버 터 모듈, 도트 매트릭스 모듈, 소켓점퍼로 되어있다.

음성인식키트 바로 확인하기 

 

[58호]자동회전, 자동신고 기능이 있는 소화기 거치대 및 소화기 경보기

58 ict 자동화소화전 (1)

58 ict 자동화소화전 (1)

2019 ICT 융합 프로젝트 공모전 참가상

자동회전, 자동신고 기능이 있는

소화기 거치대 및 소화기 경보기

글 | 전남대학교 이정원, 정수연, 정찬환

1. 심사평
칩센 창의적 발상과 시제품의 제작 완성도가 높아 보입니다. 또한 무선 통신을 통한 경보기와 소화기 거치대간의 효율적 사용 부분도 아이디어가 돋보입니다. 개발 작품에 있어 화재시 소방기관에 알려주는 기능에 있어 설명이 부족하여 이 부분에 대하여 구성을 어떻게 진행한 것인지 궁금증이 남아 있네요. 소화기 거치대의 동작과 관련한 시연 동영상등이 있었으면 더 좋았을듯 합니다.
뉴티씨 평소에 직접 뒤집어서 흔들어주고 했었는데, 이것을 자동으로 해줄수 있다니 참 좋은 아이디어 같습니다. 매우 간단하면서도 좋은 아이템으로, 소방기구로 활용이 될 수 있는 가능성이 매우 높다고 생각되며 각 아파트 단지나, 주요한 건물 등에서도 반드시 구비하였으면 좋겠습니다. 이에 높은 점수를 드립니다.
위드로봇 소화기의 수명 연장을 위해 자동 회전 기능을 구현하였기에 부분을 실용성 측면에서 높은 점수를 부여하였습니다. 반면 구현한 결과에 대한 분석이 보고서에 나타나지 않은 점이 아쉽습니다.
펌테크 단순한 구성이지만 세심한 관찰력이 반영된 실생활과 밀접한 아이디어와 독창성 및 실용성이 아주 뛰어난 작품이라고 생각합니다. 단 일반적인 소화기 무게가 통상 3KG 이상인 점은 감안한다면 이를 감안한 구동모터 선정과 감속기어 박스 구성이 우선적으로 고려되어 할 것으로 판단이 되는데 이 부분은 작품에 반영이 되지 않은 것 같습니다. 또한 제출된 문서 내용을 감안해 볼 때 최종적인 작품의 완성은 되지는 않은 것으로 판단됩니다.

2. 작품 개요
2.1. 발명 목적

58 ict 자동화소화전 (2)

1) 화재에 대한 안전불감증이 만연한 우리 사회에서 안전에 대한 관심도를 높이고자 한다.
2) 화재 발생 시, 원활하게 화재를 진압하고 신속한 초기대응을 통하여 인적·물적 피해를 최소화하고자 한다.
3) 분말소화기의 적절한 보관방법을 사용하여 소화기의 수명을 늘리는 동시에 폐소화기를 줄여 환경 보호에 기여하고자 한다.
4) 분말소화기의 점유율은 71%로 국내 소화기 중 가장 많은 점유율을 차지하고 있으며, 이를 기반으로 한 창업 아이템은 충분히 수요가 있을 것으로 판단한다.

2.2. 발명아이템의 선정동기 및 배경

58 ict 자동화소화전 (3)

분말소화기의 경우 관리방법 중에 ‘한달에 한번 위아래로 흔들어주어야 함.’이라는 항목이 존재한다. 이는 소화 약제가 굳지 않도록 하기 위함인데, 많은 사람들은 이러한 관리방법에 대해 무지하다. 실제로 분말이 굳어 기능을 상실한 소화기 때문에 화재 진압에 어려움을 겪은 수많은 사례는 우리에게 경각심을 일깨워주었다. 한편, 화재 발생 시 골든타임은 5분이며 이후에는 심각한 인명피해와 재산피해가 발생할 수 있다. 실제로 골든타임을 놓쳐 연마다 4000건 이상의 화재가 일어나고 있고, 2000명 이상의 인명피해가 발생하고 있다. 따라서 제대로 된 소화기의 작동과 신속한 119신고를 통한 화재 초기대응의 필요성을 느끼게 되었고, 앞서 언급한 문제점을 해결하기 위해 ‘한달 주기로 분말형 소화기를 섞어주는 장치’와 ‘화재를 인식하여 자동으로 119신고가 이루어지는 시스템’을 접목한 아이템을 구상하게 되었다.

2.3. 발명아이템의 독창성
소방산업의 발전이 정체되어있는 탓에 시장에 유사제품이 존재하지 않다. 잘 인식하지 못하는 부분에서 불편함을 해소해주는 소방 신기술을 갖춘 제품이며, 디자인 측면에서도 우수하다.

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

58 ict 자동화소화전 (1)

· 소화기의 수명연장을 위해 1달 주기로 한번씩 자동으로 소화기를 회전 시킨다
· 화재경보기가 감지할 만큼의 큰 불이 나면 소화기 터너와 화재경보기가 상호 블루투스 통신으로 화재를 인지하고 소화기의 위치를 식별시켜줌과 동시에 Telematics기술을 활용하여 가까운 소방기관에 자동으로 신고한다.
· 화재 시 소화기 거치대의 부저, 네오픽셀이 켜져 소화기의 위치를 쉽게 파악할 수 있어서 더 큰 화재로 번지는 것을 막아줄 수 있다.
· 벽걸이형 거치대로 제작하여 장소에 영향을 받지 않고 어디든지 설치가 가능하다.
· 화재경보기와 소화기 거치대가 서로 블루투스 기술을 활용 상호 통신하여 소화기의 위치를 빠르게 식별할 수 있어 빠른 진압이 가능하다.
· 자동회전 기능으로 소화기 분말을 섞어줘 소화기의 수명을 크게 연장시킬 수 있다.
· 화재가 발생하면 자동신고, 수동신고 기능으로 가까운 소방기관에 빠른 신고가 가능해 빠른 진압이 가능하다.

3.2. 전체 시스템 구성
알고리즘

58 ict 자동화소화전 (4)

3.3. 개발 환경
· 개발언어 : C++(아두이노), C#(어플 개발)
· 회로도 소스 개발 Tool : 아두이노
· 어플 개발 Tool : Unity

4. 단계별 제작 과정
4.1. 아이템 기획 및 기획서 작성

4.2. 개발자 소스코딩, 기구제작자 모델링

58 ict 자동화소화전 (2)

4.3. 개발자 회로제작, 기구제작자 모델 조립

58 ict 자동화소화전 (3)

4.4. 디자이너 모델 디자인

58 ict 자동화소화전 (4)

4.5. 소화기 거치대 회로도

58 ict 자동화소화전 (5)

4.6. 소화기 거치대 소스코드

#include <Stepper.h> //스텝모터 라이브러리
#include <SoftwareSerial.h> //블루투스 라이브러리
#include <Adafruit_NeoPixel.h> //네오픽셀 라이브러리 시작
#ifdef __AVR__ //네오픽셀 라이브러리 시작
#include <avr/power.h>
#endif //네오픽셀 라이브러리 끝

#define PIN 6 //네오픽셀 핀번호
#define NUMPIXELS 60 //사용할 네오픽셀 수
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//네오픽셀을 위한 객체 선언

const int stepsPerRevolution = 8; //스텝모터 스텝수
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); //스텝모터 객체선언

SoftwareSerial phoneSerial(4, 5); //핸드폰 Master 블루투스의 Tx. Rx핀을 4번 5번핀으로 설정
SoftwareSerial alarmSerial(2, 3); //화재경보기 Slave 블루투스의 Tx, Rx핀을 2번 3번핀으로 설정

int sirenPin = 13; //부저 핀번호
int buttonPin = 7; //버튼 핀번호
int buttonData; //버튼 데이터
bool motorTrigger = false; //화재, 진압 trigger
char serialData; //통신데이터
int oneTimeFlag = 0;
int oddEvenFlag = 0;

void setup()
{

pinMode(buttonPin, INPUT);
pinMode(sirenPin, OUTPUT);

// 네오픽셀 라이브러리 사용 시작
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
strip.begin();
strip.show();

myStepper.setSpeed(60);

Serial.begin(9600); // 시리얼 통신의 속도를 9600으로 설정
alarmSerial.begin(9600); //거치대 블루투스만 연결
phoneSerial.begin(9600);

}
void loop () {

motorEvenOdd(); //모터회전함수
buttonValue(); //수동신고 함수

//화재, 진압 통신
alarmSerial.listen();
if (alarmSerial.available()) {
serialData = alarmSerial.read();
Serial.write(serialData);
fireAlarmBT(); //블루투스 통신 함수
}

}
void alarmData() { //블루투스 데이터 값 받기
serialData = alarmSerial.read();
Serial.write(serialData);
fireAlarmBT();
}

void fireAlarmBT() { //화재,진압 통신
if (serialData == ‘F’) { //화재시
fireWork();
}
if (serialData == ‘E’) { //진압시
exWrok();
}
oneTimeFlag = 1;
}

void fireWork() { //화재시 행동
motorTrigger = true;
fire();
buzzerOn();
oneTimeFlag = 1;
}
void exWrok() { //진압시 행동
motorTrigger = true;
extinguish();
motorTrigger = false;
oneTimeFlag = 0;
}

void buttonValue() { //수동신고 함수
buttonData = digitalRead(buttonPin);
if (buttonData == HIGH) { //수동신고
delay(500);
motorTrigger = true;
selfFire();
buzzerOn();
}
}
void buzzerOn() { //부저, 네오픽셀 On
theaterChase(strip.Color(0, 255, 0), 0); //네오픽셀, 부저
}
void buzzerOff() { //부저, 네오픽셀 Off
noTone(sirenPin);
}

void theaterChase(uint32_t c, uint8_t wait) { //부저,네오픽셀 On 함수
for (int j = 0; j < 30; j++) {
tone(sirenPin, 262);
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int q = 0; q < 3; q++) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int i = 0; i < strip.numPixels(); i = i + 3) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
strip.setPixelColor(i + q, c); //turn every third pixel on

strip.show();
}
}
}
}

void theaterChase_(uint32_t c, uint8_t wait) { //부저,네오픽셀 Off 함수
for (int q = 0; q < 3; q++) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
for (int i = 0; i < strip.numPixels(); i = i + 3) {
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
noTone(sirenPin);
break;
}
strip.setPixelColor(i + q, 0);
}
strip.show();
}
}

void fire() { //화재함수
phoneSerial.listen();
char data = “화재가 발생하였습니다.”;
phoneSerial.write(data);
}

void selfFire() { //수동 신고 화재
alarmSerial.listen();
char data = ‘f’;
alarmSerial.write(data);
phoneSerial.listen();
char data_ = “화재가 발생하였습니다.”;
phoneSerial.write(data_);
}

void extinguish() { //진압함수
phoneSerial.listen();
char data = “화재가 진압되었습니다.”;
phoneSerial.write(data);
theaterChase_(strip.Color(0, 0, 0), 0); //네오픽셀 끔
buzzerOff();
oneTimeFlag = 0;
}

void motorEvenOdd() { //모터회전
for (int i = 0; i <= 10; i++) {
if(oddEvenFlag == 1)break;
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
oddEvenFlag = 1;
break;
}
myStepper.step(stepsPerRevolution);
}
for (int i = 0; i <= 10; i++) {
if(oddEvenFlag == 1)break;
alarmSerial.listen();
if (alarmSerial.available()) {
alarmData();
oddEvenFlag = 1;
break;
}
myStepper.step(-stepsPerRevolution);
}
oddEvenFlag = 0;
Serial.println(“bluetooth Ready”);
}

4.7. 화재경보기 회로도

58 ict 자동화소화전 (6)

4.8. 화재경보기 소스코드

#include <SoftwareSerial.h> //블루투스 라이브러리

SoftwareSerial alarmSerial(2, 3); //블루투스의 Tx, Rx핀을 2번 3번핀으로 설정
char serialData; //블루투스 통신 변수
int temSensor = A0; //온도센서 핀번호
int sirenPin = 4; //부저 핀번호

void setup() {
// 시리얼 통신의 속도를 9600으로 설정
Serial.begin(9600);
alarmSerial.begin(9600);
pinMode(temSensor, INPUT);
}

void loop() {

double temValue = 0; //센서 데이터 값 초기화

while (1) //온도가 올라갈 때까지 기다림
{
int readVal = analogRead(temSensor);
double temValue = Thermistor(readVal);
delay(500);

if (temValue >= 50.0) { //큰 화재 발생
break;
}
alarmSerial.listen();
if (alarmSerial.available()) {
Serial.write(alarmSerial.read());
byte serialData = alarmSerial.read();
if (serialData == 255) //수동신고
{
selfFire();
}
}
}
fire();

while (1)
{
int readVal = analogRead(temSensor);
double temValue = Thermistor(readVal);
delay(500);

if (temValue <= 20) { //진압신호 올때까지 기다림
break;
}
}
extinguish();

}

void selfFire() { //수동신고
buzzerOn();
delay(8000);
extinguish();
}

void fire() { //화재 함수
for(int i=0; i < 50; i++){
char data = ‘F’;
alarmSerial.write(data);
}
buzzerOn();
}

void extinguish() { //진압 함수
for(int i =0; i < 50; i++){
char data = ‘E’;
alarmSerial.write(data);
}
buzzerOff();
}

void buzzerOn() { //부저 On
tone(sirenPin, 262);
}

void buzzerOff() { //부저 Off
noTone(sirenPin);
}

double Thermistor(int RawADC) //온도센서 섭씨 변환
{
double temValue;
temValue = log(10000.0 * ((1024.0 / RawADC – 1)));
temValue = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * temValue * temValue )) * temValue );
temValue = temValue – 273.15; // convert from Kelvin to Celsius
return temValue;
}

 

 

 

 

 

[58호]낙상사고자를 살리는 마지막 사이렌, Life Bell

58 ict 라이프벨 (6)

58 ict 라이프벨 (1)

 

2019 ICT 융합 프로젝트 공모전 참가상

낙상사고자를 살리는 마지막 사이렌, Life Bell

글 | 한동대학교 반병우

1. 심사평
칩센 이미 상용화를 준비하고 있는 제품에 대하여 평가를 하는 것이 맞는것인지 모르겠습니다. 개발자께서 이미 사전 조사를 하여 알고 계시겠으나, 금번 개발 작품과 같이 낙상 사고 대비를 위한 제품을 포함하여 Silver care 관련한 수많은 제품들이 준비되고 기획되고 있습니다. 요양병원등과 같은 B2B의 형태도 중요하지만, 지역 기관등을 통하여 선제적인 보급과 스마트폰 뿐이 아닌 여타 기관에서 관리중인 시스템과 연계하는 부분도 검토가 필요하지 않을까 합니다.
뉴티씨 실제로 삶에서 노인들이 낙상하는 경우나 도움이 필요한데 즉시 도움을 주지 않을 경우 사고가 커져 심지어는 사망에 이르게 되는데, 이런 경우에 자동으로 낙상사고를 알려서 즉시 도움을 받을 수 있도록 하는 장치입니다. 매우 실질적인 제품이기에, 상품화하여 모든 노인분들이 착용하면 좋겠습니다.
위드로봇 낙상의 패턴을 분석하는 것이 가장 어려운 부분인데, 이 부분의 추가 연구가 필요합니다.
펌테크 실생활에 사용이 될 수 있는 실용성, 아이디어, 창의성이 돋보이는 작품으로 생각됩니다. 전체 하드웨어 시스템 구성은 비교적 심플한 구성인 반면에 낙상사고를 실질적으로 대비하기에 손색이 없을 정도로 잘 기획된 작품이라고 생각됩니다 다만 작품의 동작 영상을 볼 수 없어 출품작의 최종 완성도를 정확히 판단할 수가 없었습니다.

2. 작품 개요
내가 중학교 때 할머니가 낙상 사고로 돌아가셨다. 더 안타까운 점은 바로 옆방에 내가 있었음에도 대처를 하지 못했다는 점이다. 그리고 이런 슬픈 일이 나의 일만이 아니라는 것을 알게 되었다. 낙상 사고는 우리나라 사고사망원인 2위로 실제로 많은 사람들의 목숨을 위협하고 있다. 하지만 현재 그 어떤 회사도 이를 막을 만한 제품을 만들어 내지 못하고 있다. 이러한 사회적 문제점을 해결하고자 이번 ‘Life Bell’을만 들게 되었다. 낙상 사고를 막기 위해 우리 사회엔 지팡이 등 넘어지지 않기 위한 도구가 이미 존재한다. 하지만 이러한 도구들도 낙상 사고를 막지 못하고 있다. 그래서 우리는 이미 넘어진 후 생존을 위한 도구를 생각하게 되었고, 이를 만들어 보급함으로써 실제로 정말 많은 사람의 생명을 구하고 싶다.

58 ict 라이프벨 (2)

2.1. 아이디어 필요성
고령자의 안전사고는 매년 점점 더 증가하고 있다. 여기서 우리가 눈여겨 볼 점은 그 중 절반 정도(47.4%)가 낙상사고였다는 것이다. 이러한 낙상사고에는 4분이라는 골든 타임이 존재하지만 사고를 당한 노인분들이 이 상황에서 스스로 대처하시거나 주변사람들에게 도움을 청하는 것은 쉽지 않은 현실이다. 그 결과 노인들의 낙상 사고 사망률은 타 연령대의 10배에 달한다. 더 나아가 이미 우리 사회엔 지팡이와 같이 넘어지지 않기 위한 도구가 존재하지만, 이런 도구들도 낙상 사고를 막지 못하고 있다. 그래서 우린 이미 사고가 발생 한 후 생존을 위한 도구를 생각하게 되었다.

2.2. 아이디어 목표
· 정확한 낙상 감지
· 낙상 감지후 신속한 대처 절차

3. 주요 동작 및 특징
3.1. ‘Life Bell’의 기본 동작 및 역할

58 ict 라이프벨 (3)

착용자의 몸의 기울기를 측정하는 기울기 센서, 착용자의 속도 변화량을 감지하는 가속도 센서를 통해 낙상이 감지 되었을 시 어느정도 시간이 지날 때 까지(현재 15초로 지정) 대처가 되지 않았을 경우 기기 자체에서 1차적으로 사이렌을 울린다. 그리고 시간이 더 지날 때까지도 대처가 되지 않을 시엔 보호자에게 현재 위치와 함께 낙상 감지 문자가 보내진다, 그리고 사고 발생 후 30초가 지날 때 까지도 대처 되지 않았을 시 119에 자동 문자 신고가 접수된다.

3.2. 기존 유사 사례 및 차별화 포인트
가. 유사사례

58 ict 라이프벨 (5)

· 기존에 우리와 유사한 제품으론 바이탈밴드와 낙상 폰이 있다. 하지만 두 기기 모두 팔의 궤적으로 낙상을 감지한다. ▶ 어깨가 굳어 팔의 움직임이 자유롭지 못한 노인분들의 낙상은 감지하지 못한다.
· 낙상폰은 40만원 이상, 바이탈밴드는 50만원 이상의 고가로 책정되어 있고 사용법이 너무 어렵다. ▶ 실직적으로 사용하기가 번거롭고 어렵다. 그리고 가격으로 인해 구매하기가 부담스럽다
· 기기 형태가 제한 ▶ 기기 형태가 제한된 웨어러블 디바이스의 가장 큰 특징은 점점 더 사용빈도가 낮아진다는 점이다.

나. 차별점

58 ict 라이프벨 (4)

· 우리가 만든 기기, Life Bell은 몸의 중심축의 기울기 변화를 통해 낙상을 감지한다. ▶ 정말 낙상 여부 감지가 필요한 노인분들의 낙상을 감지할 수 있다.
· 낙상 감지 기능에 집중하여 가격을 크게 낮추었다.
· 기술력을 바탕으로 노인분들이 일상생활에서 사용하는 지팡이, 휠체어, 보행 도구, 자전거, 모자 신발 등에 적용하여 사용할 수 있어서 사용빈도가 줄지 않는다. 그 외 안전사고가 일어날 수 있는 수많은 곳들에 적용할 수 있다.

3.3. 정확한 낙상 감지 방법

58 ict 라이프벨 (6)

그림에서 볼 수 있듯이 앉았을 때와 누웠을 때와는 다르게 넘어졌을 때 기울기의 변화 값이 3배이상 크게 감지되었다. 이 구별 방법을 통해서 낙상을 정확하게 감지 할 수 있었다.

4. 전체 시스템

‘Life Bell’은 크게 감지부, 관제부, 전력 공급부로 이루어져 있다.

58 ict 라이프벨 (7)

4.1. 구성품

58 ict 라이프벨 (8)

58 ict 라이프벨 (9)

4.2. 구성요소
· 감지부 : mpu6050 기울기센서와 가속도 센서를 통해 이상 움직임을 감지한다. 기울기 센서는 착용자의 몸의 중심축의 기울기 변화를 측정하고, 가속도 센서는 착용자의 몸의 속도 변화를 감지한다. 이 2가지 변수로 낙상을 정확하게 감지한다.
· 관제부 : 사이렌과 통신부로 이루어져 있고, 이곳에서는 위급한 상황이 유지될 시 사이렌을 울리고, 블루투스 통신을 어플리케이션을 통해 문자 기능과 GPS기능을 활성화시켜 보호자과 119에 현재 상황과 위치를 알린다.
· 전력 공급부 : 감지부와 관제부가 역할을 잘 할 수 있도록 전력을 공급하여 준다.

4.3. 개발환경

58 ict 라이프벨 (10)

‘Life Bell’의 기기는 아두이노 나노를 기반으로 PCB를 제작하였으며, 모든 명령어 및 코드는 C언어로 코딩되어 있다. 또한 ‘Life Bell’ 어플리케이션은 자바 이클립스로 코딩을 하여 제작을 하였다.

5. 로드맵

58 ict 라이프벨 (11)

우리는 기술의 유효성, 실효성, 시장성을 인정받아 특허를 등록하였고, 이 기술을 바탕으로 프로토타입을 개발하였다. 그리고 현재는 한동대학교 IDEA 랩실에 지원을 받아 제품의 소형화 단계에 있다. 그리고 제품의 소형화 후 병원, 요양원 등 시설과 B2B마케팅을 통해 시장에진입할 것이고, 그 후엔 보험사, 일인 이용 수단 회사들과 콜라보레이션 마케팅을 통해 시장을 더더욱 확대해 나갈 것이다.

6. 기타

58 ict 라이프벨 (12)

6.1. 기기 소스코드

라이브러리 선언 및 함수 정의
// 라이브러리 선언
#include <Wire.h> // I2C통신 설정 – 가속도 측정하기 위함
#include “MPU6050.h” // 가속도 라이브러리 선언(가속도 측정 관련 라이브러리)
#include <SoftwareSerial.h> // 소프트 시리얼 라이브러리 선언(블루투스 통신하기 위함)

// 핀 번호 설정
#define BUZZER 7 // 부저 핀 번호
#define RESET 4 // 가속도센서(mpu6050) RESET 핀 번호
int TxPin = 5; // 블루투스 통신 TX단자
int RxPin = 6; // 블루투스 통신 RX단자
SoftwareSerial BTSerial(TxPin, RxPin);

// (중요)(중요)
int NOMAL_ANGLE = 20; // 정상기울기 범위, 기울기가 ‘NOMAL_ANGLE’ 안에 들어 올 경우 정상처리
long CRASH_VALUE = 700; // 충돌 값(충돌 판단하는 값, 가속도 변화량 값)

// 구동 변수
long ac_x, ac_y, ac_z, gy_x, gy_y, gy_z ; //acc, gyro data (acc, gyro 계산 수식)
double angle1 = 0, deg ; // angle, deg data (각도계산)
double angle2 = 0;
double dgy_x ;
long mapping_value = 1000;
long normal_x,normal_y,normal_z, deltha_x[3],deltha_y[3],deltha_z[3], deltha, angle_1[3], angle_2[3] ;
long event_value = 1000;

// 처리 변수
const int delay_main = 1; // 전체 시스템 구동하는 데, 걸리는 시간 (즉 구동 시간)이다. (ex) 1000 = 1000ms = 1s = 1초
const int sum_count = 4;
long delay_config = 6000; // 이벤트 발생 후 딜레이
boolean ACCESS_ACCEL = false;
long TIEMR_BLESEND = 0;
bool WARN_STATE = false;
long TIMER_WARN_STATE = 0;
bool buzzer_state2 = true;

// 함수 선언
int ACTION_config();
void value_init();

통신 설정
void setup() {

// 시리얼통신 & 소프트시리얼 통신 설정
Serial.begin(115200); BTSerial.begin(9600);

// 핀모드 및 초기 설정
pinMode(BUZZER, OUTPUT);pinMode(RESET, OUTPUT); // 출력으로 사용
tone(BUZZER, 1000, 100); delay(200); tone(BUZZER, 1000, 100); // 부저 울리기
digitalWrite(RESET, LOW); // RESET 초기화

// 가속도 센서 설정
delay(100);
mpu6050_init(); // 가속도 센서 초기 설정
ACCESS_ACCEL = ACCEL_ACCESS(); // 가속도 센서 값 맞게 나오는지 확인하기
}

블루투스 통신
void loop() {

// 1. 정해진 시간마다 블루투스 통신으로 ‘a’값 보내기 (부팅 되었는지 확인하기 위해)
if(TIEMR_BLESEND < millis()){
BTSerial.print(“a”); // 블루투스 데이터 보내기
TIEMR_BLESEND = millis() + 10000; // 10초 간격으로 데이터 보내기
}

// 2. 블루투스 데이터 감지하기
if (BTSerial.available()){ // 블루투스 데이터를 감지했을 경우 안에 while문이 동작함
int timeout = 50;
String response = “”; long int time = millis();
while( (time+timeout) > millis()) { // 50ms동안 문자열 세는 방식
while(BTSerial.available()) { // 블루투스 통신이 끝날 때 까지
char c = BTSerial.read(); // c에 읽어 response에 저장
response+=c; }}

String DATA = response; // 컨트롤 데이터에 읽은 데이터 넣기
Serial.println( “DATA : “ + DATA); // 컨트롤 데이터 출력

if(DATA.substring(0,2) == “HI”){ // 블루투스 데이터가 “HI”인가? 그럼 ‘a’데이터 보내기
BTSerial.print(“a”);
}
}

[비상모드] 비상모드에서 정상상태로 돌아가는지 확인하기
if(WARN_STATE){

// 0.5초마다 확인 하기
if(TIMER_WARN_STATE < millis()) { TIMER_WARN_STATE = millis() + 100;

// 0.5초 마다 부저 키고 끄기 (띠띠띠 소리 내기)
if(buzzer_state2) { tone(BUZZER, 1000); buzzer_state2 = false; } else { noTone(BUZZER); buzzer_state2 = true;}

// 각도 측정하기
value_init(); // 변수 초기화
accel_calculate(); // 가속도 측정 -> 각도계산
angle1 = abs(angle1); // 각도 변수에 저장
angle2 = abs(angle2); // 각도 변수에 저장

// Serial.print( “ ANGLE1 : “ + String(angle1)); Serial.println( “ ANGLE2 : “ + String(angle2));

if ( (angle1 < NOMAL_ANGLE ) && (angle2 < NOMAL_ANGLE ) ){ // 정상 상태에 돌아왔을 경우 (각도가 안정상태일 경우)

noTone(BUZZER); // 부저 끄기
WARN_STATE = false; // 비상모드 끄기
BTSerial.print(“x”); // 블루투스 데이터 ‘x’보내기

가속도 변화량(충격량) 감지하기
value_init();
//첫번째 센싱
for (int i=0; i < sum_count; i++){ accel_calculate();
deltha_x[1] = deltha_x[1]+(normal_x); deltha_y[1] = deltha_y[1]+(normal_y); deltha_z[1] = deltha_z[1]+(normal_z); delay(5);}
deltha_x[1] = int(deltha_x[1]/sum_count); deltha_y[1] = int(deltha_y[1]/sum_count); deltha_z[1] = int(deltha_z[1]/sum_count);

//두번째 센싱
for (int i=0; i < sum_count; i++){ accel_calculate();
deltha_x[2] = deltha_x[2]+(normal_x); deltha_y[2] = deltha_y[2]+(normal_y); deltha_z[2] = deltha_z[2]+(normal_z); delay(5);}
deltha_x[2] = int(deltha_x[2]/sum_count); deltha_y[2] = int(deltha_y[2]/sum_count); deltha_z[2] = int(deltha_z[2]/sum_count); //3축 변화량 비교가속도 변화량 측정하기
deltha_x[0] = abs(deltha_x[1]-deltha_x[2]); deltha_y[0] = abs(deltha_y[1]-deltha_y[2]); deltha_z[0] = abs(deltha_z[1]-deltha_z[2]);
deltha = deltha_x[0] + deltha_y[0] + deltha_z[0];

가속도 변화량 비교를 통한 낙상 감지
if(deltha > CRASH_VALUE){ // 충격이 감지 되었을 경우 내부 함수 동작하기
ACTION_config(); // 기울기를 통해 비상모드인지 판단함
}

< 비상모드 시 사이렌 알람과 블루투스를 통해 이뤄지는 통신 부분>
// 비상모드인지 판단하는 함수
int ACTION_config(){

tone(BUZZER, 1000,1000); // 부저 키기
delay(3000); // 3초간 대기
long TIMER1 = (long) millis() + 12000; // 12초간 대기하는 구간
long TIMER_buzzer = 0; bool buzzer_state = true;
int WARN = 0;
// 시작 Flow chart
// 충격감지(가속도변화감지) -> 3초간 대기 -> 12초간 기울기 감지

// 비상모드 인가? 정상모드 인가? 판단하기
while( (TIMER1 > millis())&&(WARN == 0)){

// 부저 울리기 : 띠띠띠
// if(TIMER_buzzer < millis()) { TIMER_buzzer = millis() + 500;
// if(buzzer_state) { tone(BUZZER, 1000); buzzer_state = false; } else { noTone(BUZZER); buzzer_state = true;}
// }

// 각도 측정하기
value_init(); accel_calculate();
angle1 = abs(angle1);
angle2 = abs(angle2);

// 정해진 각도 내에 들어가는지 확인하기 (12초 내의 정해진 각도에 들어 갈 경우 정상임)
if ( (angle1 < NOMAL_ANGLE ) && (angle2 < NOMAL_ANGLE ) ){
// tone(BUZZER, 1000, 100); delay(200); tone(BUZZER, 1000, 100);
noTone(BUZZER); WARN = 1; // WARN = 1이면 while에 나갈 수 있음
}

Serial.print( “ ANGLE1 : “ + String(angle1)); Serial.println( “ ANGLE2 : “ + String(angle2));
delay(100);
}
//—————————————//

// 정상 일 경우 return 시키기
if(WARN == 1) { return 0; }

// 비상모드 일 경우 부저 6초간 울리고 블루투스 데이터 보내기
TIMER1 = (long) millis() + 6000;
while( TIMER1 > millis() ){
tone(BUZZER, 1000); delay(100); noTone(BUZZER); delay(100);
}
noTone(BUZZER);
BTSerial.print(“w”); // ‘w’ 블루투스데이터 보내기

가속도 연산 및 각도 계산 함수
void accel_calculate() {

ac_x = 0; ac_y = 0; ac_z = 0;

Wire.beginTransmission(mpu_add) ; // 번지수 찾기
Wire.write(0x3B) ; // 가속도 데이터 보내달라고 컨트롤 신호 보내기
Wire.endTransmission(false) ; // 기달리고,
Wire.requestFrom(mpu_add, 6, true) ; // 데이터를 받아 처리

// Data SHIFT
ac_x = Wire.read() << 8 | Wire.read() ;
ac_y = Wire.read() << 8 | Wire.read() ;
ac_z = Wire.read() << 8 | Wire.read() ;

// Serial.println( “ X : “ + String(ac_x) + “ Y : “ + String(ac_y) + “ Z : “ + String(ac_z) );
if(ACCESS_ACCEL) { } else { return; }

//맵핑화 시킨 것 – 즉 10000으로 맵핑시킴
normal_x = map(int(ac_x), -16384, 16384, 0, mapping_value);
normal_y = map(int(ac_y), -16384, 16384, 0, mapping_value);
normal_z = map(int(ac_z), -16384, 16384, 0, mapping_value);

float accel_xz, accel_yz;
const float RADIANS_TO_DEGREES = 180/3.14159;

// 각도1 계산하기
accel_yz = sqrt(pow(ac_x, 2) + pow(ac_y, 2));
angle1 = atan(-ac_z / accel_yz)*RADIANS_TO_DEGREES;

// 각도2 계산하기
accel_xz = sqrt(pow(ac_z, 2) + pow(ac_y, 2));

에러를 줄이기 위한 변수 초기화
void value_init(){
normal_x = 0; normal_x = 0; normal_x = 0;
for (int i=0; i < 3; i++){ deltha_x[i]=0; deltha_y[i]=0; deltha_z[i] = 0; angle1 = 0;angle2 = 0; }

 

 

[58호]Battleship 2인용 게임기

58 ict 배틀쉽 (5)

58 ict 배틀쉽 (15)

2019 ICT 융합 프로젝트 공모전 참가상

Battleship 2인용 게임기

글 | 국민대학교 오재홍, 이강민

1. 심사평
칩센 보드게임을 디지털화하였다는 것에서 재미있는 발상이라 생각합니다. 하드웨어 구성에 있어서 게임기 조작부는 기성 조이스틱 등을 사용하여 조금 더 심플한 방법을 추구하고, Display 부분에 dot/character 보다 더 유려한 형태의 구성으로 했다면 재미있어 보이지 않았을까 합니다. 모듈 문제로 적용하지 못한 블루투스 기능 또한 아쉬움으로 남습니다.
뉴티씨 한때 유행하던 8비트 임베디드 게임기를 상상하게 만든 작품이었습니다. 실제로 블루투스를 넣어서 서로 통신하여 게임할 수 있도록 된 점도 잘된 점이라고 생각합니다. 다만, 스마트폰을 LCD 표현용으로 사용하고 스마트폰과 연결하여 게임기로 쓸 수 있도록 하였다면, 보조장치로 더 좋지 않을까 생각합니다.
위드로봇 보드 게임을 임베디드 시스템으로 구현한 부분이 재미있는 작품입니다.
펌테크 과거 오락실 게임을 연상시키는 흥미로운 작품이라고 생각합니다. 단순해 보이지만 프로그래밍 과정을 통해 게임 구성에 관한 Algorithm 구현, GLCD를 통한 상태 표시 등은 기술적 구현이 쉽지는 않았을 것으로 예상됩니다. 비록 2대의 게임기기 상호 간 무선통신을 통한 구현을 최종 완성시키지 못했지만 유선상의 구현만으로도 충분히 가치가 있는 작품이라고 생각합니다.

2. 작품 개요
· 2대의 ATmega128을 이용한 유선 통신 기능 구현
· 기존의 종이나 장난감으로 하는 보드게임을 디지털화하여 시중에서 판매되는 게임기와 비슷한 외형의 디지털 게임기 제작

3. 작품 설명

58 ict 배틀쉽 (1)

이 작품은 battleship 보드게임 원리에 착안해 만들었다. 기존의 battleship 보드게임은 10×10의 보드에서 이루어지고, 우선 각자 자신의 보드에 각각 크기가 5,4,3,3,2인 다섯 개의 배(종류는 4종류, 각각 Aircraft(크기 5), Battleship(크기 4), Cruiser(크기 3), Destroyer(크기 2))를 가로 혹은 세로로 겹치지 않게 배열한다. 그리고 서로 돌아가며 상대의 배의 위치를 추측한다. 한 번씩 돌아가며 상대의 배가 있을 걸로 예상되는 위치(게임 보드 위의 한 점)를 지목한 뒤, 그 결과를 듣고 다시 그 결과를 바탕으로 추측하여 먼저 상대의 배가 있는 위치를 모두 맞춘 쪽이 승리하는 게임이다. 이 작품은 기존 battleship 보드게임과 달리 상대방의 5칸 크기의 배를 파괴하거나 5칸 크기의 배가 아닌 배를 3척 파괴하는 것이 승리조건이다.

58 ict 배틀쉽 (2)
차이점은 이 작품에서는 크기가 5,4,3,2인 배가 있고 한 칸 크기의 함정이 있다는 것이다. 이 함정은 배와 겹치지 않게 배열하고 상대방이 함정을 공격했을 때 배를 공격했다고 착각하게 만드는 역할을 하여 배의 모양을 쉽게 예측하지 못하게 만들었다는 것이다. 마지막으로 스캔 기능이 추가되었다. 자신이 공격에 성공한 배가 어떤 배인지 알기 위한 기회가 3번이 주어진다. 자신의 공격 턴에 지정한 좌표에 스캔 버튼을 누르면 배의 종류를 알려준다.
이러한 게임 규칙의 변화, 아이템 사용 효과 추가, 아날로그 게임의 디지털화를 통해서 기존 battleship 보드게임에서 보다 더 재미의 요소를 추가하였다.

3.1. 주요 동작 및 특징
가. 스위치 동작

58 ict 배틀쉽 (1)
(1) 리셋 스위치
(2) 상하좌우 스위치
(3) 포격/확인 스위치
(4) 회전/스캔 스위치

나. 게임 진행 순서

58 ict 배틀쉽 (3)

① 게임기 상단에 부착된 스위치를 이용해 각자의 배 배치를 완료한다.

58 ict 배틀쉽 (4)

② 배 배치가 완료된 후 한 사람씩 공격을 하게 되는데 상대방의 배 위치를 맞췄을 때는 X표시가 되며 한 번 더 차례를 진행하고 공격에 실패했을 때는 *표시가 되며 상대방의 턴으로 넘어간다. 특정 알파벳 배의 모양을 완전히 파괴하게 되면 화면 하단에 있는 알파벳 현황판 숫자가 달라진다.

58 ict 배틀쉽 (2)

③ 게임기 스위치 좌측 상단에 LED는 자신의 턴일 때는 초록색, 상대방의 턴일 때는 빨간색에 불이 들어온다.

58 ict 배틀쉽 (3)

④ 공격 시 파란색 버튼을 이용하여 스캔 기능을 사용함으로써 상대방 특정 위치의 배 종류를 알 수 있다. 스캔 기능은 각 플레이어에게 3번의 사용 기회가 주어진다.

58 ict 배틀쉽 (5)

 

 

58 ict 배틀쉽 (6)

 

⑤ 게임 진행 중 승리조건이 달성되면 승리 문구가 표시되고 흰색 버튼을 눌러 새로운 게임을 시작할 수 있다.

3.2. 전체 시스템 구성
가. 스위치 구성

58 ict 배틀쉽 (7) 58 ict 배틀쉽 (8)

한 대의 게임기 안에 있는 7개 스위치는 모두 풀업 저항 회로로 구성되어 있고 스위치를 누를 때 연결된 포트의 HIGH 신호를 LOW 신호로 바꾸어 입력 신호를 변경한다. 스위치는 모두 폴링(Polling)방식으로 동작되며 RESET 단자에 연결된 스위치를 제외한 나머지는 모두 PORTD에 연결하였다.

나. 사운드

58 ict 배틀쉽 (9)

게임의 효과음은 전기 신호를 소리로 변환시켜 주는 부저(Buzzer)를 통해서 제작하였다.
부저에는 내부에 전자석과 진동을 일으키는 판으로 이루어져 있으며, 전자석이 진동판을 아주 빠르게 흔들어 소리를 발생 시키는 원리를 가지고 있어 타이머/카운터를 이용하여 주파수를 정해주어 소리를 발생시켰다.
하나의 효과음은 여러 가지 주파수의 배열로 만들었고 타이머/카운터 레지스터를 조절하는 함수의 인자로 사용하였다.

다. 통신 방법

58 ict 배틀쉽 (10)

게임기의 통신은 USART(Universal Synchronous and Asynchronous Receive and Transmitter) 통신 방식을 사용한다. USART 통신을 하기 위해서 2대의 ATmega128 Tx/Rx 포트를 서로 교차하여 선을 연결하고 양쪽 ATmega128 모두 송수신 속도, 전송 문자의 데이터 비트수 등 데이터를 송수신 하는데 필요한 레지스터들을 동일하게 설정한다.
정보를 보낼 때 UDR0에 데이터를 넣어 인터럽트를 발생시키고 그 데이터를 받을 때는 미리 선언한 flag 값만 변경시켜 인터럽트를 통해 실시간으로 정보를 주고받는다.

라. 배터리

58 ict 배틀쉽 (4)

게임기의 GLCD 백라이트와 부저에 전원을 공급하기 위해서 약 5V의 전압이 필요하다. 따라서 게임기의 하단부에 AA배터리 소켓을 4개 부착하였고 1.5V AA건전지 4개를 직렬 연결하여 총 6V의 전압을 공급할 수 있도록 설계하였다.

마. 게임 알고리즘

58 ict 배틀쉽 (11)

3.3. 개발 환경(개발 언어, Tool, 사용 시스템 등)

58 ict 배틀쉽 (12)

4. 단계별 제작 과정
4.1. 코드 제작

58 ict 배틀쉽 (13)

① Visual Studio와 Code Vision AVR 모두 C언어를 기반으로 한 플랫폼이기 때문에 먼저 Visual Studio로 게임 알고리즘을 제작한 후 Code Vision AVR에 부합하는 코드로 변환하여 GLCD에 영상을 띄웠다.

58 ict 배틀쉽 (5)

② ATmega128간의 USART 유선통신의 데이터 송수신을 간단한 스위치 동작으로 확인하였다.

4.2. 하드웨어 제작

58 ict 배틀쉽 (6)

① 스위치와 리드선을 글루건으로 고정시키고 스티로폼에 스위치만 보이게 하여 실제 게임기 스위치 같은 외형을 제작하였다.

58 ict 배틀쉽 (14)

② 아크릴판으로 틀을 제작하고 게임기의 윗면에 GLCD와 스위치를 아랫면에는 ATmega128, 부저, 브레드보드를 위치시켰다.

58 ict 배틀쉽 (7)

③ 2대의 게임기를 붙여 게임기 하단에 배터리를 넣으면 게임이 작동하도록 제작하였다.

5. 기타
5.1. 소스코드
가. 배 배치 알고리즘

void print_ship(int x, int y, int ship_length, char ship_name)
{
if(turn==0)
for (i = 0; i < ship_length; i++)
board_char[y][x+i] = ship_name;

else
{
for (i = 0; i < ship_length; i++)
board_char[y+i][x] = ship_name;
}
}

print_ship 함수는 x,y 좌표, 배의 길이, 배 이름을 인수로 받아 전역변수 turn이 0이면
배의 이름을 board_char 배열에 가로로 넣고 turn이 1이면 board_char 배열에 세로로 넣는다.

void MapDraw(void)
{
for(i = 0; i < 10; i++)
{
for(j = 0; j <10; j++)
{
GLCD_TextGoTo(i,j);
GLCD_WriteChar(board_char[j][i]);
}
}
}

MapDraw 함수는 board_char 배열에 저장된 데이터를 GLCD에 찍어주는 역할을 한다.

switch(PIND)
{
case 0xfd: // 아래로 움직이는 키를 눌렀을 때 (PORTD1)
if (turn == 0 && player_y != 9)
{
player_x+=0; player_y+=1;
_delay_ms(3000);
}
if (turn == 1)
{
if(board_char[player_y + ship_length][9] == ‘.’){
player_x+=0; player_y+=1;
_delay_ms(3000);
}
}

배를 이동하기 코드의 일부를 발췌한 부분이다.
turn이 0이면 배가 가로로 되어있는 상태이고 1이면 세로로 되어있는 상태이기 때문에 turn이 0이고 y좌표가 (x,9) 가 아닌 경우에 한 칸 내려갈 수 있고,
turn이 1이고 y좌표와 배의 길이를 더한 좌표에 있는 문자가. 맵의 기본 모양이라면 한 칸 내려갈 수 있기 때문에 y좌표에 1을 더해주었다. GLCD의 좌표는 첫 번째 줄의 y좌표는 0이고 아래로 내려갈수록 +1씩 된다.

void enter_ship(int x, int y, int ship_length, char ship_name)
{
if (turn == 0)
for (i = 0; i<ship_length; i++)
{
grid[y][x + i] = ship_name;
}
else
for (i = 0; i<ship_length; i++)
{
grid[y + i][x] = ship_name;
}
placement_cnt++;
enter_cnt++;
}

enter_ship 함수는 turn의 값을 통해 배의 방향을 판단하고 반복문을 이용해 grid 배열에 배치할 배의 이름을 넣어주는 함수이다.

void erase_ship(int x, int y, int ship_length)
{
if (turn == 0)
for (i = 0; i < ship_length; i++)
board_char[y][x + i] = grid[y][x + i];

else
for (i = 0; i < ship_length; i++)
board_char[y + i][x] = grid[y + i][x];
}

erase_ship 함수는 x,y 좌표, 배의 길이를 인수로 받아 board_char 배열에 grid 배열을 넣어준다. 이 함수는 좌표값을 이동시켰을 때 이전에 print_ship 함수로 board_char 배열에 넣어주어 Mapdraw 함수로 GLCD에 배열을 표현했을 때 잔상이 남는 것을 지워주는 역할을 한다. board_char 배열에 넣어주는 grid 함수는 배를 배치했을 때 배열 안에 값이 저장된다.

while(1)
{
print_ship
-> MapDraw
-> swich case 문을 이용하여 버튼 눌렀을 때 좌표 이동 및 배 배치
-> erase_ship
}

나. 부저 사운드 함수

float start3[]= {329.6, 329.6, 329.6, 293.7, 329.6, 0, 329.6, 329.6 ,329.6, 293.7, 392.0, 349.2, 329.6,-1}; // start 사운드
float end_win[] = {261.6, 329.6, 392.0, 523.3, -1}; // 승리 사운드
float end_lose[] = {277.2, 261.6, 246.9, 223.1,-1}; // 패배 사운드
float fire[]= {261.6, -1}; // 포격 성공 사운드
float wrecked[] = {130.8, 123.5, -1}; // 침몰사운드
float miss[] = {392.0 ,-1}; // miss 사운드
float scan2[] = {440.0, -1}; // scan 사운드
void Buzzer(float arr[])
{
int i = 0;
DDRB |=(1<<DDB4); //5번 핀으로 소리 출력
TCCR0 = 0x1D;
TCCR1A = 0×00;
TCCR1B = 0×04;
TCNT0 = 0;
TCNT1 = 65536 – 55000;

while(arr[i] != -1)
{
OCR0 = (int)(8000000/(arr[i]*256));
while((TIFR & 0×04) == 0);
TIFR |= 0×04;
TCNT1 = 61250;
//=====================
OCR0 = 0;
while((TIFR & 0×04) == 0);
TIFR |= 0×04;
TCNT1 = 55000;
i++;
}
TCCR0 = 0;
}

타이머/카운터 레지스터를 설정하고 while문의 인자에는 arr[i] 배열의 인자(주파수)를 하나씩 실행 시키는데 -1이 나오면 효과음이 끝나도록 설정 하였고 하나의 효과음이 모두 나온 후에 다음 동작(화면이 바뀌거나 스위치를 작동하는 행위)이 실행된다.
빠른 게임 진행을 위해서 게임 시작, 게임 종료를 나타내는 효과음 이외의 배열(arr[i])의 길이를 짧게 설정하였다.

다. 통신 방법

void Init_interrupt_usart(void) // 인터럽트 레지스터 설정
{
UCSR0A = 0×00;
UCSR0C = 0×06;
UCSR0B = 0xd8; // 1101 1000

UBRR0H = 0×00;
UBRR0L = 0×07; // 115200bps
SREG|=0×80;
}
ISR(USART0_TX_vect) // led 제어, 끝나는거 제어
{
tx_done=0;
}

ISR(USART0_RX_vect)
{
data = UDR0;

if(data==1) ////////////////////////
led_turn=1;
if(data==0) ////////////////////////
led_turn=0;

if(data==Game_set)
{
end_flag=1;
loss_cnt++;
}
if(data == re_game)
re_game_flag2=1;

if(data == C_zero)
C_zero_flag=1;

if(data == B_zero)
B_zero_flag=1;

if(data == S_zero)
S_zero_flag=1;

if(data == M_zero)
M_zero_flag=1;

if(data == D_zero)
D_zero_flag=1;
}

인터럽트 ISR(USART0_TX_vect)은 메인문에서 UDR0 값을 넣어줬을 때 tx_done=0 으로 만들면서 ISR을 빠져나가게 되면서 while(tx_done);을 다음 코드로 진행할 수 있게 구성하였다.
인터럽트 ISR(USART0_TX_vect)에서 정보는 최소화 하였고 보내는데 필요한 정보들은 flag 변수를 이용하여 주로 처리하였다.
인터럽트 ISR(USART0_RX_vect)은 UDR0 값을 받아 변수 data에 저장 후 필요한 flag를 1로 set 하는 용도로 쓰였다.

5.2. 아쉬운 점
블루투스 페어링(pairing) 오류

58 ict 배틀쉽 (8)

기존 작품 설계 방향은 무선통신을 이용한 2인용 게임기를 만드는 것 이 목표였기 때문에 아두이노를 이용하여 블루투스를 페어링 하려 했지만 블루투스 모듈 문제로 페어링이 되지 않아 유선통신을 하게 되었다. 그림은 블루투스 모듈인 hc-05와 hc-06을 페어링 하고 있는 모습이다.

휴대하기에는 큰 부피
기존에 보유하고 있던 큰 크기의 브레드보드를 기준으로 회로를 설계하고 게임기 외형을 제작하였기 때문에 휴대하기에는 큰 부피로 작품이 제작되었다.

시간제한 기능 미사용
타이머 인터럽트를 사용해서 사용자가 공격하는데 30초의 시간제한을 두려 하였지만 여러 개의 인터럽트를 동시에 사용하여 충돌이 생겨 타이머가 제대로 작동하지 않았다.
아래 내용은 타이머 인터럽트만을 사용하여 GLCD에 30초 타이머 기능을 구현한 코드와 코드의 설명이다.

ISR(TIMER0_COMP_vect) // 타이머 ISR (30초 카운트)
{
total_count++;
if ( total_count == 1000 ) // total_cound는 1ms
{
if(++sec_first>9){ s=0; // 1초 단위
if(++sec_second>2){ s1=0; //10초 단위
}
}
//sec_first와 sec_second는 전역변수
GLCD_TextGoTo(2,1); GLCD_WriteChar(sec_first+’0’); // GLCD에 1초 단위 표기
GLCD_TextGoTo(1,1); GLCD_WriteChar(sec_second+’0’); // GLCD에 10초단위 표기
_delay_ms(1);

total_count = 0;
}
}

void Init_Timer(void) // 타이머/카운터0 레지스터 설정을 통한 타이머 Init
{
TCCR0 |= (1<<CS02); // 프리스케일러로 64를 선택
TCCR0 |= (1<<WGM01); // CTC 모드
TCNT0 = 0; // 카운터 초기화
OCR0 = 249; // TOP 정의
TIMSK |= (1<<OCIE0); // 타이머/카운터0 Compare Match 인터럽트 활성화
sei(); // 전역 인터럽트 활성화
total_count = 0; // total_count 초기화
}

void Quit_Timer(void) // Timer 레지스터 설정을 통한 Timer Quit
{
TIMSK = 0×00; // 타이머/카운터의 interrupt를 비활성화
sec_first = 0; // sec_first를 초기화
sec_second = 0; // sec_second를 초기화
total_count = 0; // total_count를 초기화
}

타이머 기능: Init_Timer에서 타이머/카운터0의 레지스터 설정을 통해 1ms마다 total_count가 1씩 증가하는 타이머를 만들었다. 각 레지스터의 설정은 다음과 같다. Init_Timer함수의 주석을 통해서 설명되어 있다.
Init_Timer를 통해서 타이머/카운터0이 활성화 되면 TCNT가 OCR과 같아지는 순간 타이머0 ISR(TIMER0_COMP_vect)로 진입하여total_count가 1ms마다 증가하며, total_count가 1000이 되는 순간 sec_first를 1씩 증가시킨다. sec_fisrt가 10이 되는순간 sec_first는 0으로 초기화되고, sec_second가 1씩 증가한다. sec_second가 3이되는 순간 sec_second는 0으로 초기화 된다.
코드를 통해, 위 내용을 확인할 수 있으며, sec_first와 sec_second는 각각 1초 단위 10초 단위를 의미한다.
종합 의견 : 완성된 작품에서 무선통신과 타이머 기능을 추가하고 작은 크기의 브레드보드를 사용하여 외형을 제작한다면 보다 편리하고 직관적인 게임기의 기능을 갖추게 될 것이다.

5.3. 참고문헌
· 뉴티씨 (newtc) : http://www.newtc.co.kr/dpshop/bbs/board.php?bo_table=m41&wr_id=745&page=5
· 인터럽트 레지스터 설정 : https://webnautes.tistory.com/984
· USART 통신 : https://blog.naver.com/xisaturn/220750649418
· 그림 1,2 battleship 보드게임 예시 : https://en.wikipedia.org/wiki/Battleship_(game)
· 그림 3. ATmega128 data sheet : http://www.siphec.com/item/AVR-ATmega128-ATmega1281-ATmega2561.html
· 그림 6. 주파수와 피에조 부저의 음계 : https://kocoafab.cc/tutorial/view/626
· 그림 7. ATmega USART Tx/Rx 연결 회로도 : https://blog.naver.com/iintuition_/220587315291