October 17, 2018

디바이스마트 미디어:

[40호]AVR을 이용한 AVR(Auto Vehichle Controller) : CARS

2016 ictmain

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

AVR을 이용한 AVR(Auto Vehichle Controller) : CARS

 

글 | 국민대학교 오승재, 유동규, 이경택, 김해니, 김경연

심사평
뉴티씨 구현한 내용은 매우 재미있게 취미생활에 활용할 수 있을 것 같고, 나아가 사용된 기술들을 잘 활용하면 좋은 제품들이 많이 만들어질 수 있을 것으로 보인다. 따라서, 실 생활에서의 실용성은 크지 않으나 작품의 기대효과는 높게 보았으며, 완성도 등은 높은 수준으로 보았다. 좀 더 나은 아이템을 선택했었다면 보다 좋은 작품을 낼 수 있는 팀으로 생각된다.

칩센 조금은 식상한 주제지만, 학생들이 가볍게 따라 할 만큼 상세한 설명이 눈에 띈다.

위드로봇 운전의 느낌을 살려서 RC카를 조작하는 아이디어에서 페달이 물리적인 장치가 아닌 에어 페달 형식으로 만들면서 얻는 장점도 있지만 잃어버리는 단점도 있는 것 같습니다. 스마트 기기로 물리 장치를 조작하는 상품들이 많이 나와있기에 좀 더 창의성이 돋보이는 아이디어가 필요할 것 같습니다.

1. 작품제목
AVR을 이용한 AVR(Auto Vehichle Controller) : CARS

2. 작품개요
21세기에 들어와서 가장 많이 발전한 산업을 꼽자면 ‘스티븐 잡스’가 시작한 스마트기기 산업의 발전일 것이다. 이 스마트기기 산업의 발달로 무선조종 기기에서 쓰이는 제어 기기, 센서, 위성항법장치(GPS)의 가격이 하락했다.

그로 인해 과거에는 비싸면서 성능이 좋지 않아 비싸기만 하고 조종하기도 불편한 장난감 대우를 받던, 혹은 군사용으로만 사용되던 RC카와 드론은 대중들에게서 다시 사랑을 받기 시작했다. 주위를 둘러보면 공원 등지에서 RC카, 드론 등을 취미생활로 즐기는 어른들인 키덜트(KIDULT) 족들을 심심치 않게 볼 수 있고 부모님과 함께 나들이를 나온 아이들을 볼 수 있다.

CARS는 기존의 RC카처럼 버튼과 스틱으로만 조종하는 일반 RC카와는 다르다. 오락실에서 흔히 볼 수 있는 레이싱 게임 조종기처럼 핸들과 페달 방식으로 조종하도록 구현하였다. 최근에는 누구나 갖고 있는 스마트 기기의 내장 센서인 Lotation 센서를 이용하여 핸들을 구현하였다. 또, 페달은 실제 페달을 밟는 것처럼 느껴지기 위해 적외선 거리 측정 센서를 이용하여 만들었으며, 이 두 센서에서 받은 데이터를 RC카 내부에 Atmega128과 블루투스를 통해 통신함으로써 실제 운전하는 감각으로 RC카를 조종한다.

이렇게 실제로 운전하는 감각으로 조종하게 되면 조종기의 스틱이나 버튼만으로 조종하는 것보다는 훨씬 생동감과 현장감을 줄 수 있게 되어 아이들의 교통 안전 교육용 자료로 사용할 수 있다. 실제 자동차의 핸들을 만져서 조종할 수 없는 아이들에게 있어서, 평소에 가지고 있던 스마트 기기를 이용한 핸들과 페달식 조종 방식은 운전에 대한 이해도를 올려줄 수 있다.

현재 서울시에 일부 자치구에서는 어린이 및 시민을 대상으로 안전하고 올바른 자전거 이용에 필요한 교육을 실시하고 이를 통한 자전거이용 활성화 도모를 위해 소규모의 트랙을 설치하여 자전거 교통안전 체험장을 마련하였다. 시스템만 구축된다면 이런 자전거 교통안전 체험장을 현재의 상태에서 최대한 도로와 비슷하게 보완하여 ‘도로 교통안전 모의 체험장’으로 만들고, 그곳에서 아이들이 CARS를 통해 올바른 교통 안전수칙을 배울 수도 있다. 아이들에게는 딱딱하게 교실 속에서 말로만, 동영상으로만 교육해서는 쉽게 집중력을 잃고 흥미도 잃어버린다. 하지만 CARS를 통해 간접적으로라도 도로 운전을 체험해 본다면 교통 수칙을 따분하지 않고 흥미롭게 배울 수 있을 것이라 생각된다.

3. 작품설명
3.1. 주요 동작 및 특징
이 작품은 에어페달과 스마트기기를 이용한 조종기, 그리고 Atmega128을 이용한 RC카이다. 스마트기기 안에 있는 Rotation vector Sensor를 이용해서 방향이 센서 값 중 z축 값만을 추출하였기 때문에 방향 조정을 x축과 y축으로만 이루어져 있어 자동차 핸들과 유사한 방법으로 사용이 가능하다. 또한, 스마트기기에 어플만 설치하면 돼 굳이 따로 핸들 모형이 필요하지 않으며 간편하게 사용할 수 있다.
페달은 에어페달을 이용하였기 때문에 무게가 적게나가 휴대성이 좋으며 센서를 이용하여 작동하기 때문에 더 부드럽게 조작이 가능하다. 페달은 DMS Sensor를 사용하였으며 페달 위에 발을 올려놓음으로써 DMS Sensor의 기울기 값이 작아지면 다시 밟는데까지 걸리는 시간이 짧아지므로 속도는 더욱 빨라진다. 스마트기기에서 Rotation vector Sensor로 받은 방향과 페달에 있는 DMS Sensor로 받은 속도를 RC카에 장착된 Atmega128와 Bluetooth를 통한 무선통신을 이용하였기 때문에 다른 연결선이 필요하지 않다. 이렇게 DMS Sensor와 Rotation vector Sensor로 받은 Sensor값들을 Atmega128에서 PWM 제어를 통하여 Rotation vector Sensor로 받은 Direction Sensor 값은 RC카에 있는 서브모터를 제어하며 DMS Sensor로 받은 속도 값은 모터 DC모터를 제어하는데 사용된다.

3.1.1. 하드웨어 동작 및 특징
1. 에어패달 모듈의 측정 센서값을 RC카의 DC모터 제어 Atmega128모듈로 전송하여 PWM 제어

40 ict 참가상 avr (1)

40 ict 참가상 avr (2)

2. 안드로이드 폰의 Rotation 센서를 이용한 어플을 제작하여 센서의 Z축 값만을 RC카의 조향을 조정하는 Servo모터로 전송하여 PWM 제어

40 ict 참가상 avr (3)

3.1.2. 소프트웨어 동작 및 특징
적외선 센서인 DMS센서를 이용하여 발바닥과 센서 모듈과의 거리를 측정하여 측정값을 Atmega128의 ADC를 이용하여 설정된 문자를 Bluetooth 모듈를 이용하여 DC모터 제어 Atmega128과 USART통신하여 전송한다. Bluetooth 모듈을 이용해서 DC모터 제어 Atmega128로 들어온 해당 문자를 해석하여 설정한 OCR값을 조정하게 되고 PWM값을 모터드라이브를 거쳐 DC모터의 전송하여 PWM제어하게 된다.
스마트 기기의 RotationSensor를 이용한 어플을 제작하여 RotationSensor의 Z축 값에 따라 설정된 문자를 스마트 기기내의 Bluetooth를 이용하여 Servo모터 제어 Atmega128과 USART통신을 이용하여 전송한다. Bluetooth 모듈을 이용해서 Servo모터 제어Atmega128로 들어온 해당 문자를 해석하여 설정한 OCR값을 조정하여 Servo모터를 PWM제어 하게 된다.

40 ict 참가상 avr (1)

3.2. 전체 시스템 구성

40 ict 참가상 avr (2)

3.3. 개발환경
3.3.1. Soft Ware
· AVR studio Version 4.19
· Android Studio
· JAVA

3.3.2. Hard Ware

Cap 2017-04-06 13-14-33-243

 

4. 참고문헌
· AVR ATmega128 프로그래밍과 인터페이싱 :( ITC출판, 이응혁, 장문석, 장영건 지음)
· NT-DC20A Datasheet
· JMDO-BT-1 사용자 메뉴얼
· MTS-A410SE 사용자 매뉴얼
· LK-DMS Datasheet
· Android Studio :( 한빛소프트 출판, 마츠오카 겐지 지음)

5. 단계별 제작 과정
5.1. Hard Ware

5.1.1. 패달 모듈 제작

40 ict 참가상 avr (4)

 

40 ict 참가상 avr (5)

 

40 ict 참가상 avr (6)

5.1.2. servo모터 제어를 위한 Atmega128 모듈제작

40 ict 참가상 avr (7)

40 ict 참가상 avr (8) 40 ict 참가상 avr (9) 40 ict 참가상 avr (10) 40 ict 참가상 avr (11)

5.1.3. DC 모터를 제어를 위한 Atmega128 모듈제작

40 ict 참가상 avr (12) 40 ict 참가상 avr (13) 40 ict 참가상 avr (14)

5.2. Soft Ware
5.2.1. DMS센서 ADC 추출

#include<avr/io.h>
#define F_CPU 16000000
void ADC_init(void); // ADC초기 설정
unsigned int ADConversion(int ch); // ADC 실행

void ADC_init(void)
{
DDRF=0×00; // 기준전압 설정
ADMUX |= (1 << REFS1) | (1 << REFS0); // ADC 허용
ADCSRA |= (1 << ADEN); // 프리스케일러 값 64
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
}
unsigned int ADConversion(int ch)
{ // 핀 선택
ADMUX |= (ch << MUX4) | (ch << MUX3) | (ch << MUX2) | (ch << MUX1) | (ch << MUX1); // AD 변환 시작
ADCSRA |= (1 << ADSC); // AD 변환 완료 여부 확인, AD 변환 완료될 때까지 대기, 완료 확인되면 다음 진행
while(!(ADCSRA & (1 << ADIF))); // AD 변환 완료된 데이터 반환
return ADC;
}

5.2.2. 추출된 ADC값에 따라서 특정 문자 지정

void main(void)
{
char result;
ADC_init();
unsigned int ch_ADC;
SREG=0X08;
while(1)
{
ch_ADC = ADConversion(0);
if((500<ch_ADC)&&(ch_ADC <700))//6~4cm
{
result=’a’;
}
else if((400<ch_ADC)&&(ch_ADC <500))//9~7cm
{
result=’b’;
}
else if((300<ch_ADC)&&(ch_ADC <400))//11~9cm
{
result=’c’;
}
else if((200<ch_ADC)&&(ch_ADC <300))//발과의 거리 12~13cm
{
result=’d’;
}
}
}

5.2.3. DC모터 PWM제어

void Init_Timer1(void)//pwm 사용을 위한 타이머1 초기화
{
TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<< WGM10) | (1<<CS10) ; //고속pwm 10비트
TCCR1B |= (1<<WGM12) | (1<<CS12) ; //분주비 8
TIMSK = 1<<TOIE1;
OCR1AH = 0×00;
OCR1AL = 0×00;
}
void dc_con(char D)
{
if(D==’a’)//차량 속도 3단
{
OCR1AH = 0×00;
OCR1AL = 0xff;
}
else if(D==’b’)//차량 속도 2단
{
OCR1AH = 0×00;
OCR1AL = 0xc0;
}
else if(D==’c’)//차량 속도 1단
{
OCR1AH = 0×00;
OCR1AL = 0xa0;
}
else if(D==’d’)//차량 정지
{
OCR1AH = 0×00;
OCR1AL = 0×00;
}
}

5.2.4. 패달 모듈과 DC모터 제어 Atmega128 모듈 간 블루투스 연결

void Data(unsigned char data) //송신 USART0사용
{
while((UCSR0A & 0X20)==0×00);
UDR0 =data;
}

char recive(void) //수신 USART0사용
{
unsigned char data;
while((UCSR0A & 0×80) == 0×00);
data=UDR0;
return data;
}

5.2.5. 패달 모듈로 DC모터 제어 Atmega128 모듈 제어

//////////////////////////////수신//////////////////////////////////////////////////
#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU 16000000
char recive(void);
void delay_ms(unsigned int m);
void dc_con(char D);
void Init_Timer1(void);
void Init_Timer1(void)
{
TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<< WGM10) | (1<<CS10) ; //고속pwm 10비트
TCCR1B |= (1<<WGM12) | (1<<CS12) ; //분주비 8
TIMSK = 1<<TOIE1;
OCR1AH = 0×00;
OCR1AL = 0×00;
}
char recive(void)
{
unsigned char data;
while((UCSR0A & 0×80) == 0×00);
data=UDR0;
return data;
}
void delay_ms(unsigned int m)
{
unsigned int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<2117;j++);
}
}
void dc_con(char D)
{
if(D==’a’)
{
OCR1AH = 0×00;
OCR1AL = 0xff;
}
else if(D==’b’)
{
OCR1AH = 0×00;
OCR1AL = 0xc0;
}
else if(D==’c’)
{
OCR1AH = 0×00;
OCR1AL = 0xa0;
}
else if(D==’d’)
{
OCR1AH = 0×00;
OCR1AL = 0×00;
}
}
void main(void)
{
unsigned char data;
unsigned int cnt=0;
DDRA=0xFF;
DDRE=0×08;
DDRD=0×00;
DDRB=0xFF;
UBRR0H=0×00;
UBRR0L=0×67;
UCSR0A=0×00;
UCSR0B=0×10;
UCSR0C=0×06;
SREG=0×08;
Init_Timer1();
while(1)
{
data=recive();
dc_con(data);
}
}
//////////////////////////////송신//////////////////////////////////////////////////
void Data(unsigned char data);
void delay_ms(unsigned int m);
void main(void)
{
ADC_init();
Init_Timer1();
unsigned int ch_ADC;
DDRE=0×02;
UBRR0H=0X00;
UBRR0L=0X67;
UCSR0A = 0X00;
UCSR0B = 0X08;
UCSR0C = 0X06;
SREG=0X08;
char data;
while(1)
{
ch_ADC = ADConversion(0);
if((500<ch_ADC)&&(ch_ADC <700))//->초기
{
Data(‘a’);
delay_ms(100);
}
else if((400<ch_ADC)&&(ch_ADC <500))//
{
Data(‘b’);
delay_ms(100);
}
else if((300<ch_ADC)&&(ch_ADC <400))//1
{

Data(‘c’);
delay_ms(100);
}
else if((200<ch_ADC)&&(ch_ADC <300))//1
{
Data(‘d’);
delay_ms(100);
}
}
}
void Data(unsigned char data)
{
while((UCSR0A & 0X20)==0×00);
UDR0 =data;
}
void delay_ms(unsigned int m)
{
unsigned int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<2117;j++);
}
}
void Init_Timer1(void)
{
TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<< WGM10);
TCCR1B |= (1<<WGM12) | 1<<(CS12) | (0<<CS11) | (0<<CS10);
OCR1AH = 0×03;
OCR1AL = 0xFF;
TIMSK = 1<<TOIE1;
DDRB = 0XFF;
}
void ADC_init(void)
{
// 기준전압 설정
ADMUX |= (1 << REFS1) | (1 << REFS0);
// ADC 허용
ADCSRA |= (1 << ADEN);
// 프리스케일러 값 64
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
}
unsigned int ADConversion(int ch)
{ // 핀 선택
ADMUX |= (ch << MUX4) | (ch << MUX3) | (ch << MUX2) | (ch << MUX1) | (ch << MUX1); // AD 변환 시작
ADCSRA |= (1 << ADSC);
// AD 변환 완료 여부 확인, AD 변환 완료될 때까지 대기, 완료 확인되면 다음 진행
while(!(ADCSRA & (1 << ADIF)));
// AD 변환 완료된 데이터 반환
return ADC;
}

5.2.6. RotationSensor 값 추출 어플 제작

5.2.7. RotationSensor어플과 Servo모터제어 Atmega128 모듈간 블루투스 연결

연결하려는 블루투스 대상을 선택

40 ict 참가상 avr (15)

선택된 블루투스와 연결완료

40 ict 참가상 avr (16)

5.2.8. Servo모터 PWM제어

void servo_con(char S)
{
if((S==’e’))
{
OCR1AH = 0×00;
OCR1AL = 0×30;
}
else if((S==’d’))
{
OCR1AH = 0×00;
OCR1AL = 0×40;
}
else if((S==’c’))
{
OCR1AH = 0×00;
OCR1AL = 0×50;
}
else if((S==’b’))
{
OCR1AH = 0×00;
OCR1AL = 0×60;
}
else if((S==’a’))
{
OCR1AH = 0×00;
OCR1AL = 0×70;
}
}

5.2.9. RotationSensor 어플을 이용 Servo모터 PWM제어

#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU 16000000
char recive_p(void);
void delay_ms(unsigned int m);
void dc_con(char D);
void servo_con(char S);
void Init_Timer1(void);
void Init_Timer1(void)
{
TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<< WGM10) ; //고속 pwm 10비트
TCCR1B |= (1<<WGM12) | (1<<CS12) ; //분주비 64
TIMSK = 1<<TOIE1;
OCR1AH = 0×00;
OCR1AL = 0×50;

}
void main(void)
{
unsigned char data2;
unsigned int cnt=0;
DDRA=0xFF;
DDRE=0×08;
DDRD=0×00;
DDRB=0xFF;
UBRR1H=0×00;
UBRR1L=0×19;
UCSR1A=0×00;
UCSR1B=0×90;
UCSR1C=0×06;
SREG=0×08;
Init_Timer1();
while(1)
{
data2=recive_p();
if(data2==’f’)
{
delay_ms(500);
PORTA=0×02;//차량 전,후진 설정
}
servo_con(data2);
}
}
char recive_p(void)//USART1 사용
{
unsigned char data;
while((UCSR1A & 0×80) == 0×00);

data=UDR1;
return data;
}
void servo_con(char S)
{
if((S==’e’))
{
OCR1AH = 0×00;
OCR1AL = 0×30;
}
else if((S==’d’))
{
OCR1AH = 0×00;
OCR1AL = 0×40;
}
else if((S==’c’))
{
OCR1AH = 0×00;
OCR1AL = 0×50;
}
else if((S==’b’))
{
OCR1AH = 0×00;
OCR1AL = 0×60;
}
else if((S==’a’))
{
OCR1AH = 0×00;
OCR1AL = 0×70;
}
}

6. 완성된 모습

40 ict 참가상 avr (17)

 

Leave A Comment

*