sensor 실습 (not updated)

Download Report

Transcript sensor 실습 (not updated)

마이크로프로세서응용설계 - 10
sensor – temperature, cds sensor
시스템및센서네트워크연구실
1
ATmega128
시스템및센서네트워크연구실
2
LED sink / switch pullup 회로
470
5V
PC0
+5V
PC1
…..
10K
PC7
PD2
104 (0.1uF)
시스템및센서네트워크연구실
3
LCD 회로
#1
+5V
VDD
#2
LCD 밝기 조절
V0
RS
R/W
E
PC0
PC1
PC2
DB4
DB5
DB6
DB7
PC4
PC5
PC6
PC7
VSS
#3
시스템및센서네트워크연구실
+5
V
LEDA
LEDK
4
Speaker 회로 / RC servo motor / DC motor
DC motor
RC servo motor
-
motor-
PWM Vcc GND
+
black
red
black
red
yellow
OC1A(PB5)
motor+
+5V
시스템및센서네트워크연구실
5
Temperature sensor / cds sensor
R1
+5V
R0
GND
-
ADC
+
Vs
ADC
+5V
GND
시스템및센서네트워크연구실
6
시스템및센서네트워크연구실
7
LCD 함수
// LCD 초기화 함수
#include <delay.h>
void LCD_init(void)
#define CLEAR
#define LINE2
#define HOME
#define RSHIFT
#define LSHIFT
#define DISPON
#define DISPOFF
0x01
0xC0
0x02
0x1C
0x18
0x0c
0x08
// Clear Display
// 2nd Line Move
// Cursor Home
// Display Right Shift
// Display Left Shift
// Display On
// Display Off
{
DDRC = 0xFF;
// 포트 C 출력 설정
PORTC &= 0xFB;
//E = 0;
// 충분한 지연시간을 통한 안정화 과정
delay_ms(15);
Command(0x20);
// D5=1
delay_ms(5);
void LCD_init(void);
void LCD_String(char flash str[]);
void Busy(void);
void Command(unsigned char);
void Data(unsigned char);
Command(0x20);
// D5=1
delay_us(100);
Command(0x20);
// D5=1
// 초기화 과정
Command(0x28);
// function set
Command(0x06);
// entry mode set
Command(0x01);
// all clear
Command(0x0c);
// display on
}
시스템및센서네트워크연구실
8
//데이터 쓰기 함수
void Data(unsigned char byte)
{
Busy();
// 인스트럭션 쓰기 함수
void Command(unsigned char byte)
{
Busy();
// 인스트럭션 상위 바이트
PORTC = (byte & 0xF0);
PORTC &= 0xFE;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 인스트럭션 하위 바이트
PORTC = ((byte<<4) & 0xF0);
PORTC &= 0xFE;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터 상위 바이트
PORTC = (byte & 0xF0);
PORTC |= 0x01;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터
// RS = 0;
// RW = 0;
// E = 1;
// E = 0;
// 데이터 하위 바이트
PORTC = ((byte<<4) & 0xF0);
PORTC |= 0x01;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터
// RS = 0;
// RW = 0;
// E = 1;
// E = 0;
// 데이터
//RS = 1;
//RW = 0;
//E = 1;
//E = 0;
// 데이터
//RS = 1;
//RW = 0;
//E = 1;
//E = 0;
}
}
// 문자열 출력 함수
void LCD_String(char flash str[])
{
char flash *pStr=0;
// Busy Flag Check -> 일반적인 BF를 체크하는 것이 아니라
// 일정한 시간 지연을 이용한다.
void Busy(void)
{
delay_ms(2);
}
pStr = str;
while(*pStr) Data(*pStr++);
}
시스템및센서네트워크연구실
9
ADC 관련 레지스터
 ADMUX (ADC Multiplexer Selection Register)
 bit 4-0 – MUX4-0 (analog channel and gain selection bits)
• AD 변환기에 연결되는 아날로그 입력채널과 차동입력채널에 대한
이득 선택
• 입력 채널 선택 (p233, 표 9-2)
 00000 - 00111 - 단극성 입력 (ADC0 – ADC7)
 01001 - 차동 입력 (ADC1(+) – ADC0(-), 이득 x10)
 01011 - 차동 입력 (ADC1(+) – ADC0(-), 이득 x200)
 10000 - 차동 입력 (ADC0(+) – ADC1(-), 이득 x1)
시스템및센서네트워크연구실
10
 ADCSRA (ADC control and status register A)
 bit 7 – ADEN (ADC enable)
• 1 – ADC 모듈 인에이블
 bit 6 – ADSC (ADC start conversion)
• 0 – stop
• 1 – start conversion
 bit 5 – ADFR (ADC Free Running select)
• 0 – single conversion mode
• 1 – free running mode
시스템및센서네트워크연구실
11
 bit 4 – ADIF (ADC interrupt flag)
• ADC 인터럽트 발생시 1로 셋
 bit 3 – ADIE (ADC interrupt enable)
• 1 – ADC interrupt enable
 bit 2-0 – ADPS2-0 (ADC prescaler select bit)
• 분주비
000 – 2
001 – 2
010 – 4
011 – 8
100 – 16
101 – 32
110 – 64
111 – 128
시스템및센서네트워크연구실
12
 ADCH, ADCL (ADC data register)
 ADC 모듈의 변환 결과를 저장하는 10비트 레지스터
 ADCL, ADCH 값 순서로 읽음 (ADLAR = 0일때)
시스템및센서네트워크연구실
13
온도 센서
 반도체 온도 센서 LM35DZ의 특징
 0 – 100°C 측정 가능
 1°C마다 10mV씩 증가, 0mV – 1000mV(1V)까지 변화
 물리적 온도(아날로그) -> 전압(아날로그) -> 이진값(디지털)
-> 물리적 온도값(디지털)으로 변환 단계
 ADC를 사용할 경우
• 단극성 입력을 사용하면
 ADC의 경우 5V가 1023구간이므로, 온도 센서의 0-1V구간은 대략 203구간으로
나눌 수 있음. 따라서, ADC의 한 구간은 0.49°C(100°C/203구간)의 분해능을 가짐
• 온도센서 출력을 Op-amp를 이용하여 5배로 증폭하면
 출력이 5V로 증대되기 때문에, ADC의 1023구간을 모두 이용할 수 있으므로,
ADC의 한 구간은 0.098°C(100°C/1023구간)의 분해능을 가짐
시스템및센서네트워크연구실
14
온도 센서 회로
 온도 센서 회로
 Op-amp의 증폭률 : R1/R0
• R0 = 2k 옴, R1 = 10k옴 => R1/R0 = 5
• 0 – 100°C => 0 – 1V => 0 – 5V로 증폭
=> ADC : 0 – 1023
 측정 전압 = (ADC value * 5V / 1023)
 측정 온도 = 측정전압 * 100°C / 5V
R1
R0
GND
+
ADC
Vcc
+5V
시스템및센서네트워크연구실
15
실습 1
// Op-amp를 사용하여 온도 센서값 확인 : 0 – 5V 입력
// Op-amp를 사용하지 않고 온도 센서값 확인 : 0 – 1V 입력
void adc_display (void);
int adc_value=0;
float sensor = 0.0;
void main(void)
{
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 단극성 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADFR(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
SREG = 0x80;
LCD_init();
adc_display();
while(1) {
ADCSRA = 0b11000111;
// ADEN=1, ADSC = 1 변환 시작
while((ADCSRA & 0x10) == 0);
// ADIF=1이 될 때까지 대기
adc_value = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
adc_display();
}
}
시스템및센서네트워크연구실
16
void adc_display(void)
{
float f_val=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(HOME);
LCD_String(“Temp:”);
f_val = (float)adc_value * 5.0 / 1023; // 전압값으로 변환
//
sensor = f_val * 20.0;
sensor = f_val * 100;
// 5 : 100 = f_val : sensor => op-amp비에 맞추어서 값 조정하여야 함
// 1 : 100 = f_val : sensor
temp = (int)(sensor * 10 + 0.5);
temp2 = temp / 100;
temp = temp % 100;
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp2);
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“deg.”);
}
시스템및센서네트워크연구실
17
실습 2
// timer를 사용하여 100ms 간격으로 온도 센서 입력 확인, Op-amp 사용
void adc_display (void);
int adc_value=0;
float sensor = 0.0;
int cnt = 0;
void main(void)
{
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 단극성 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADFR(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
// timer0 normal 모드 설정
TIMSK = 0b00000001;
TCCR0 = 0b00000111;
TCNT0 = 0b00000000;
// TOIE0 = 1;
// 일반모드, 프리스케일 = CK/1024
// 타이머/카운터2 레지스터 초기값
SREG = 0x80;
LCD_init();
adc_display();
while(1) ;
}
시스템및센서네트워크연구실
18
// 타이머/카운터0 오버플로우 서비스 루틴
// 1/16us x 1024 x 256 = 16.384ms
// 100msec : 6 * 16.384m = 98.3msec
interrupt [TIM0_OVF] void timer_int0(void)
{
cnt++;
if(cnt == 6) {
cnt = 0;
void adc_display(void)
{
float f_val=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(HOME);
LCD_String(“Temp:”);
f_val = (float)adc_value * 5.0 / 1023;
ADCSRA = 0b11000111;
// ADEN=1, ADSC = 1 변환 시작
while((ADCSRA & 0x10) == 0);
// ADIF=1이 될 때까지 대기
adc_value = (int)ADCL + ((int)ADCH << 8);
// A/D 변환값 읽기
sensor = f_val * 20.0;
temp = (int)(sensor * 10 + 0.5);
temp2 = temp / 100;
temp = temp % 100;
adc_display();
}
}
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp2);
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“deg.”);
}
시스템및센서네트워크연구실
19
cds 센서
 cds 센서 GL5537의 특징
 light resistance measured at 10 lux : 20 – 50K옴
 dark resistance measured after 10 s when 10 lux light is closed : 2.0M옴
 센서 값
• light 시 : about 0.8 V
+5V
• dark 시 : about 5.0V
ADC
GND
시스템및센서네트워크연구실
20
실습 3
// 조도 센서 입력 확인, VR의 저항값으로 20k옴 사용
void adc_display (void);
int adc_value=0;
float sensor = 0.0;
void main(void)
{
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 단극성 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADFR(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
SREG = 0x80;
LCD_init();
adc_display();
while(1) {
ADCSRA = 0b11000111;
// ADEN=1, ADSC = 1 변환 시작
while((ADCSRA & 0x10) == 0);
// ADIF=1이 될 때까지 대기
adc_value = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
adc_display();
}
}
시스템및센서네트워크연구실
21
void adc_display(void)
{
float f_val=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(HOME);
LCD_String(“Cds:”);
f_val = (float)adc_value * 5.0 / 1023; // 전압값으로 변환
temp = (int)(f_val * 10 + 0.5);
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“V”);
}
시스템및센서네트워크연구실
22
실습 4
// timer를 사용하여 100ms 간격으로 온도 센서 및 조도 센서 값 확인, Op-amp 사용
void adc_display 1(void);
void adc_display 2(void);
int adc_value0=0, adc_value1=0;
int cnt = 0;
void main(void)
{
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 단극성 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADFR(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
// timer0 normal 모드 설정
TIMSK = 0b00000001;
TCCR0 = 0b00000111;
TCNT0 = 0b00000000;
// TOIE0 = 1;
// 일반모드, 프리스케일 = CK/1024
// 타이머/카운터2 레지스터 초기값
SREG = 0x80;
LCD_init();
adc_display1();
adc_display2();
while(1) ;
}
시스템및센서네트워크연구실
23
// 타이머/카운터0 오버플로우 서비스 루틴
// 1/16us x 1024 x 256 = 16.384ms
// 100msec : 6 * 16.384m = 98.3msec
interrupt [TIM0_OVF] void timer_int0(void)
{
cnt++;
if(cnt == 6) {
cnt = 0;
void adc_display1(void)
{
float f_val=0, sensor=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(HOME);
LCD_String(“Temp:”);
f_val = (float)adc_value0 * 5.0 / 1023
ADMUX = 0b00000000;
// MUX(4-0):00000(ADC0 단극성 입력)
ADCSRA = 0b11000111;
// ADEN=1, ADSC = 1 변환 시작
;
sensor = f_val * 20.0;
while((ADCSRA & 0x10) == 0); // ADIF=1이 될 때까지 대기
temp = (int)(sensor * 10 + 0.5);
adc_value0 = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
temp2 = temp / 100;
temp = temp % 100;
adc_display1();
ADMUX = 0b00000001;
// MUX(4-0):00001(ADC1 단극성 입력)
ADCSRA = 0b11000111;
// ADEN=1, ADSC = 1 변환 시작
temp1 = temp / 10;
temp0 = temp % 10;
while((ADCSRA & 0x10) == 0); // ADIF=1이 될 때까지 대기
Data(0x30 + temp2);
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“deg.”);
adc_value1 = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
adc_display2();
}
}
}
시스템및센서네트워크연구실
24
void adc_display2(void)
{
float f_val=0, sensor=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(LINE2);
LCD_String(“Cds:”);
f_val = (float)adc_value1 * 5.0 / 1023;
// 전압값으로 변환
temp = (int)(f_val * 10 + 0.5);
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“V”);
}
시스템및센서네트워크연구실
25
실습 5
// 온도센서 값에 따라 온도가 높으면 DC 모터 속도를 증가시키고, 낮으면 DC 모터 속도를 감소시킴
// 온도센서 값을 LCD에 출력
void adc_display(void);
float sensor = 0.0;
void main(void)
{
int adc_val=0;
float f_val=0.0;
unsigned int N1, N10;
// timer 1 PWM mode setting
DDRB = 0b00100000; // PB5(OC1A) 출력 설정
// PB5 – 좌측 motor1_A상 연결, PB1 – GND 연결
TCCR1A = 0b10000010;
// mode 14(ICRn top fast PWM) : 1110, 1,0(WGM11,10)-10, 7,6(COM1A1,COM1A0)-10
TCCR1B = 0b00011011;
// 4,3(WGM13,12)-11, 2-0(CS)-011 (64분주)
ICR1H = 0x09;
// ICR1 = 2499 (0x09C3) -> 주기 : 10msec
ICR1L = 0xC3;
TCNT1 = 0x0000;
// 타이머1 초기화
OCR1A = 0x0000;
// ADC setting
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADATE(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
시스템및센서네트워크연구실
26
SREG = 0b10000000;
// 전역 인터럽트 인에이블 비트 셋
LCD_init();
adc_display();
while(1) {
ADCSRA = 0b11000111;
while((ADCSRA & 0x10) == 0);
adc_val = (int)ADCL + ((int)ADCH << 8);
f_val = (float)adc_val * 5.0 / 1023;
sensor = f_val * 20.0;
void adc_display(void)
{
float f_val=0;
int temp0=0, temp1=0, temp2=0, temp=0;
Command(HOME);
LCD_String(“Temp:”);
// ADEN=1, ADSC = 1 변환 시작
// ADIF=1이 될 때까지 대기
// A/D 변환값 읽기
// 전압값으로 변환
// 온도값으로 변환
temp = (int)(sensor * 10 + 0.5);
temp2 = temp / 100;
temp = temp % 100;
if(sensor < 35) {
// 35도 이하일 때 모터 정지
OCR1A = 0;
}
else {
OCR1A = (2499-1250)/(50-35)*(sensor-35) + 1250;
// 35도일 때 1250에서 (최저속도를 추정해서 값을 변경해 볼 것)
// 50도일 때 2499까지 선형적으로 증가하도록 설계
}
adc_display();
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp2);
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“deg.”);
}
}
}
시스템및센서네트워크연구실
27
실습 6
// 화재 감지기 -> 프로그램은 강의노트 9번 5번 문제와 동일함
// ADC0에 조도 센서값을 입력받은 후
// 특정 전압(3.5V) 이상일 때 화재로 판단하여 LED(PA7) 점등, 스피커 알람, LCD에 fire 점등 (평상시에는 전압값만 출력)
void adc_display (void);
int adc_value=0;
float Vref = 5.0, Vwarn = 3.5, Vdetect = 0;
int cnt = 0, cnt_bell = 0, cnt_fire = 0;
void main(void)
{
ADMUX = 0b00000000; // MUX(4-0):00000(ADC0 입력)
ADCSRA = 0b10000111; // ADEN(7)-1,ADSC(6)-0,ADATE(5)-0(single conversion mode),ADIF(4)-0,ADIE(3)-0
// ADPS(2-0)-111(128분주:16MHz/128->125kHz) : 13cycle당 1회 샘플링 - 약 9.6kHz
// timer3 normal 모드 설정 : 1/16us * 256분주 * 31250= 500ms
ETIMSK = 0b00000100; // TOIE3 = 1;
TCCR3A = 0b00000000; // 일반모드 (WGM11, WGM10)
TCCR3B = 0b00000100; // 일반모드 (WGM13, WGM12), 프리스케일 = 256
TCNT3H = 0x85;
TCNT3L = 0xED;
// 65535-31250 = 34285 (0x85ED)
// OC1A 출력 설정
DDRB = 0x30;
// PB5 = 1
시스템및센서네트워크연구실
28
// PA7 출력 설정
ETIMSK = 0b00000100;
// TOIE3 = 1;
DDRA = 0x80;
PORTA = 0xFF;
SREG = 0b10000000; // 전역 인터럽트 인에이블 비트 셋
LCD_init();
adc_display();
while(1) {
ADCSRA = 0b11000111;
// ADEN=1, ADSC=1 변환 시작
while((ADCSRA & 0x10) == 0);
// ADIF=1이 될 떄까지
adc_value = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
Vdetect = (float)adc_value * Vref / 1023;
}
}
시스템및센서네트워크연구실
29
// 타이머/카운터3 오버플로우 서비스 루틴
interrupt [TIM3_OVF] void timer_int0(void)
{
if(Vdetect >= Vwarn) {
TCCR1A = 0b01000000; // COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
TCCR1B = 0b00001010; // mode 4(WGM13,12 - 01), 프리스케일 = 8
if(cnt_bell == 0) {
PORTA = 0x00;
OCR1A = 2082;
// 1M / (1+2082) = 480
Command(CLEAR);
LCD_String(“Fire!!!”);
cnt_bell = 1;
}
else {
PORTA = 0xFF;
OCR1A = 2777;
void adc_display(void)
{
int temp0=0, temp1=0, temp=0;
Command(CLEAR);
LCD_String(“Value:”);
// 1M / (1+2777) = 360
temp = (int)(Vdetect * 10 + 0.5);
Command(CLEAR);
temp1 = temp / 10;
temp0 = temp % 10;
cnt_bell = 0;
}
}
else {
TCCR1A = 0b00000000;
TCCR1B = 0b00001010;
PORTA = 0xFF;
adc_display();
}
Data(0x30 + temp1);
LCD_String(“.”);
Data(0x30 + temp0);
LCD_String(“V”);
// COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
// mode 4(WGM13,12 - 01), 프리스케일 = 8
}
}
시스템및센서네트워크연구실
30