- 센서에 입력되는 신호가 임계값을 넘으면 Low/High를 출력하는 센서 모듈
- Low/High를 출력하는 센서 모듈 예
- PIR(인체 감지) 센서모듈(HC-SR501)
- Sound 센서모듈(SZH-EK033)
- 홀 센서(Hall Sensor) WSH131
- Low/High를 출력하는 센서 모듈을 제어하는 구성도
- Low/High를 출력하는 센서 모듈을 제어하는 프로그램 예
- Analog 전압을 출력하는 센서 모듈
- ADC(Analog to Digital Conversion) object(class ADC)
- Analog 전압을 출력하는 센서 모듈 예
- 물 수위 센서(Water Level Sensor)
- 포토 센서(GL5516)
- 온도 센서(LM35DZ)
- Analog voltage를 출력하는 센서 모듈을 사용하는 구성도
- Analog voltage를 출력하는 센서 모듈을 사용하는 프로그램 예
- 펄스폭(Pulse width) 출력 모듈
- Single-Wire 통신을 사용하는 센서
- I2C 통신을 사용하는 모듈
- AVR(Atmega128) 센서(Sensors)와 센서 모듈(Sensor Modules) 관련 페이지 보기
- Low/High를 출력하는 센서 모듈 예
- Low/High를 출력하는 센서 모듈을 사용하는 구성도
- Low/High를 출력하는 센서 모듈을 제어하는 프로그램 예
- Input port의 값을 이용하는 예
- PIR 센서모듈(HC-SR501)의 상태를 LED에 표시하는 프로그램 예(Atmel Studio 7): sensor_handler.zip
아래 사진은 자주 자용하는 Low/High를 출력하는 센서 모듈의 예 이다. 아래 예의 센서는 입력 신호가 미리 정해진 임계치를 넘으면 Low 상태에서 High 상태(or High 상태에서 Low 상태)로 천이(Rising edge or Falling edge)하기 때문에 External Interrupt 처리 방식으로 제어 할 수 있다.
윗 예의 센서 모듈은 입력 신호가 임계치를 넘기면 Low 상태에서 High 상태(or High 상태에서 Low 상태)로 천이하기 때문에 Input port의 값(또는 변동)을 이용하여 센서의 상태를 입력 받을 수 있다.
PIR 센서모듈(HC-SR501)은 제어 기능(인체가 감지되면 일정시간 동안 High 상태를 유지하는 기능, High 상태에서 Low 상태로 천이하면 일정시간 신호를 감지하지 않는 기능 등)을 내장하고 있기 때문에 마이크로 콘트롤러를 사용하지 않아도 대부분의 용도에 사용할 수 있다. 아래 프로그램은 PIR 센서모듈의 출력을 LED에 보여 주는 간단한 프로그램 예 이다.
// Target : Atmega128
// Crystal: 16Mhz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
void port_init(void)
{
// Sensor의 출력신호를 PE4에 연결 하고 다른 한 단자는 GND에 연결한다.
DDRE &= (~0x10); // PORTE의 PE4를 Input Port로 설정
PORTF = 0x00; // PORTF의 초기값 설정(PORTF의 LED가 꺼진 상태)
DDRF = 0xff; // PORTF를 Output Port로 설정
}
// Initialize all peripherals
void init_devices(void)
{
cli(); // Disable all interrupts
port_init(); // I/O Port init
sei(); // Re-enable interrupts
}
int main (void)
{
init_devices();
// Infinite loop
while(1){
// PE4 가 Low인 경우
if((PINE & 0x10) == 0){
PORTF &= ~0x01; // LED(PF0): Turn off
}
// PE4 가 High인 경우
else {
PORTF |= 0x01; // LED(PF0): Turn on
}
}
return 0;
}
- Atmega128 개발보드와 센서 모듈 연결
- Atmega128 개발보드 PE4 <-> 센서의 Output pin
- Atmega128 개발보드 VDD(5V) <-> 센서의 Power pin.
- Atmega128 개발보드 GND <-> 센서 GND
- Output port(PF0)에 LED 연결
- PF0에 저항(330Ω)과 LED를 직열로 연결한다.
- sensor_handler.zip 파일을 Download하여 압축을 해제한다.
- sensor_handler.hex를 개발 보드에 Upload 한다.
- 실험:
- 개발 보드의 프로그램(sensor_handler)을 실행한다.
- Atmega128 개발보드의 프로그램을 실행하고 PIR(인체 감지) 센서모듈(HC-SR501) 앞에 손(인체)을 가까이 접근 시킨다.
- 센서모듈(HC-SR501)이 인체를 감지하면 일정 시간(센서 모듈에서 설정된 시간) 동안 LED가 Turn on 상태를 유지한다.
- Sound 센서와 홀 센서 응용을 위한 프로그램 예(Atmel Studio 7): sensor_event_one_short.zip
Sound 센서와 홀 센서는 입력 신호의 크기가 일정한 값을 초과하면 출력이 High 상태에서 Low 상태로 천이한다. 아래 예는 입력 신호의 크기가 일정한 값을 초과하면 일정 시간 동안(4초) LED가 Turn on 되는 프로그램 예이다.
// Sound 센서 모듈(SZH-EK-33), 홀센서(WSH131)
// 입력 신호가 일정 기준을 초과한 경우(센서 High -> Low) LED를 4초동안 Turn on 한다.
// PE4(외부 Interrupt 4번)를 이용 하여 High/Low를 출력하는 센서(Sensor) 신호를 받는다.
// 4초 Delay을 구현하가 위하여 Timer1의 Compare Match A Interrupt를 이용한다.
// Target : Atmega128
// Crystal: 16Mhz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
void port_init(void)
{
// PE4(INT4)를 이용 하여 Sensor의 출력신호(High/Low)를 입력 받는다.
// Sensor의 출력신호를 PE4(External Interrupt)에 연결 하고 다른 한 단자는 GND에 연결 하여야 한다.
DDRE &= (~0x10); // PORTE의 PE4를 Input Port로 설정
PORTF = 0x00; // PORTF의 초기값 설정(PORTF의 LED가 꺼진 상태)
DDRF = 0xff; // PORTF를 Output Port로 설정
// External Interrupt 4, Falling edge interrupt.
EICRB = 0x02;
// External Interrupt 4, Rising edge interrupt.
//EICRB = 0x03;
// External Interrupt 4 enable
EIMSK |= (1 << INT4);
}
// Timer1의 Output Compare Interrupt A를 이용하여 4Sec Time delay를 구현한다.
#define DELAY_SEC (62500) // 64uSec * 62500 = 4000000uSec = 4Sec
void timer_init(void)
{
// (0 << WGM13) | (0 << WGM12)(0 << WGM11) | (0 << WGM10) : Normal port operation.
// (1 << CS12) | (0 << CS11) | (1 << CS10) : 101 prescale clk/1024, Clock 주기 : 64uSec
TCCR1B = ((1 << CS12) | (0 << CS11) | (1 << CS10));
// 이 예에서는 Output Compare Interrupt A를 사용하기 때문에 4Sec 시간 지연을 얻기 위하여는
// OCR1A의 값을 TCNT1 + DELAY_SEC로 설정하여야 한다.
// OCR1A = TCNT1 + DELAY_SEC;
TIMSK &= ~(1 << OCIE1A); // Output Compare A Match Interrupt Disable
}
// Initialize all peripherals
void init_devices(void)
{
cli(); // Disable all interrupts
port_init(); // I/O Port initialized
timer_init(); // Timer1 initialized
sei(); // Re-enable interrupts
}
// External Interrupt 4가 발생 하였을 때 실행되는 함수
SIGNAL (INT4_vect)
{
EIMSK &= ~(1 << INT4); // External Interrupt 4 Disable
PORTF |= 0x01; // LED(PF0): Turn on
OCR1A = TCNT1 + DELAY_SEC; //4 Sec Delay(Timer1 output compare A match)
TIMSK |= (1 << OCIE1A); // Output Compare A Match Interrupt Enable
}
// Timer1 Output Compare A Match Interrupt가 발생 하였을 때 실행되는 함수
SIGNAL (TIMER1_COMPA_vect)
{
TIMSK &= ~(1 << OCIE1A); // Output Compare A Match Interrupt Disable
PORTF &= ~0x01; // LED(PF0): Turn off
EIFR |= (1 << INTF4); // Clear External Interrupt Flag
EIMSK |= (1 << INT4); // External Interrupt 4 enable
}
int main (void)
{
init_devices();
// Infinite loop
while(1){
}
return 0;
}
- Atmega128 개발보드와 센서 모듈 연결
- Atmega128 개발보드 PE4 <-> 센서의 Output pin
- Atmega128 개발보드 VDD(5V) <-> 센서의 Power pin.
- Atmega128 개발보드 GND <-> 센서 GND
- 홀 센서인 경우에는 전원과 센서의 Output pin 사이에 약 4.7K 부하 저항을 연결한다.
- Output port(PF0)에 LED 연결
- PF0에 저항(330Ω)과 LED를 직열로 연결한다.
- sensor_event_one_short.zip 파일을 Download하여 압축을 해제한다.
- sensor_event_one_short.hex를 개발 보드에 Upload 한다.
- 실험:
- Atmega128 개발보드의 프로그램을 실행한다.
- 프로그램이 실행되면 센서에 임계치 이상의 신호를 인가 한다.
- 센서에 임계치 이상의 신호를 인가되면 LED가 지정된 시간(4Sec) 동안 Turn on 된다.
- 센서에 임계치 이상의 신호를 인가하는 방법 예
- Sound 센서모듈(SZH-EK033): 센서에 큰 소음이나 진동(입으로 후하고 마이크에 진동)을 가한다.
- 홀 센서(Hall Sensor) WSH131: 먼저 홀 센서 회로를 구성하고 홀 센서 앞에 자성체(자석)를 접근 시킨다.
참고자료: 홀 센서 회로 예
- Analog 전압을 출력하는 센서 모듈 예
- Analog voltage를 출력하는 센서 모듈을 사용하는 구성도
- Analog voltage를 출력하는 센서 모듈을 사용하는 프로그램 예
- Atmega128 개발보드를 사용하여 Analog voltage를 주기적으로 측정하여 출력하는 프로그램 예(Atmel Studio 7): sensor_analog_interrupt_uart.zip
아래 사진은 자주 자용하는 Analog 전압을 출력하는 센서 모듈의 예 이다. 아래 예 센서는 입력 신호의 크기에 따라 출력 전압이 변동하기 때문에 센서 모듈의 출력 전압을 디지털 값으로 변환하는 A/D 변환기를 사용하여야 한다.
윗 예의 센서 모듈은 모두 Analog voltage 신호를 출력하기 때문에 ADC를 사용하여야 한다.
아래 프로그램 예는 sensor_analog_interrupt_uart 프로그램 중 Timer를 이용하여 측정 주기를 발생하고 ADC로 Analog voltage를 측정하는 프로그램 예이다. 전체 프로그램은 sensor_analog_interrupt_uart.zip에 포함되어 있다.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "gnu_sciutil.h"
#include "adc.h"
unsigned short int adcResult;
void init_port(void)
{
DDRF &= ~(1 << PF0); // PF0 : Input Port
}
#define ADC_PERIOD 1562 // 1562 * 64uSec = 0.1Sec
void timer3_init(void)
{
// Timer3를 Normal Mode로 설정 한다.
// ADC 변환 주기: OC3A Rg의 Compare match Interrupt를 이용 하여 0.1 Sec 주기의
// Interrupt를 발생 시키고, 이 주기를 ADC 변환 주기로 이용 한다.
// (0 << WGM33) | (0 << WGM32) | (0 << WGM31) | (0 << WGM30) : Normal mode
// (0 << COM3A1) | (0 << COM3A0) : Normal port operation, OCnA disconnected.
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (0 << WGM31) | (0 << WGM30);
// (1 << CS32) | (0 << CS31) | (1 << CS30) : 101 prescale clk/1024, Clock 주기 : 64uSec
TCCR3B = (0 << WGM33) | (0 << WGM32) | (1 << CS32) | (0 << CS31) | (1 << CS30);
TCNT3 = 0x0000; // Timer3 Counter Register 초기화
// OCR3A 값 설정 : 1562 * 64uSec = 0.1Sec
OCR3A = TCNT3 + ADC_PERIOD;
// Timer/Counter3, Output Compare A Match(ADC 변환 Start) Interrupt Enable
ETIMSK |= (1 << OCIE3A);
}
void adc_init(void){
// (0 << REFS1) | (0 << REFS0) ; AREF, Internal Vref turned off
// (0 << ADLAR) ; ADLAR: ADC Right Adjust Result
// MUX4:0 <= 00000 ; ADC0, Single Ended Input
ADMUX = 0x00; // Ch 0 사용
// (1 << ADEN) ; ADC Enable
// (0 << ADSC) ; ADC Start Conversion, 0 : Stop Convertion , 1 Start Convertion
// (0 << ADFR) ; Single Convertion mode
// (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) ; Prescaler Select Bits, Division Factor ; 128
// ADC의 Clock frequency: 16M /128 = 125KHz
// (0 << ADIE) ; ADC Interrupt Disable
ADCSRA = (1 << ADEN) | (0 << ADSC) | (0 << ADFR) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (0 << ADIE);
}
void init_adc(void){
init_port();
timer3_init();
adc_init();
}
SIGNAL(TIMER3_COMPA_vect)
{
ETIMSK &= ~(1 << OCIE3A); // Timer3, Output Compare A Match Interrupt Disable
OCR3A = TCNT3 + ADC_PERIOD; // Output Compare A Match Interrupt 주기 설정
// A/D 변환
ADCSRA |= (1 << ADSC) ; // ADC Start Conversion
ADCSRA |= (1 << ADIE); // ADC Interrupt Ensable
ETIMSK |= (1 << OCIE3A); // Timer3, Output Compare A Match Interrupt Enable
}
SIGNAL(ADC_vect)
{
ADCSRA &= ~(1 << ADIE); // ADC Interrupt Disable
// ADC의 출력을 부호없는 10진수로 출력한다.
// 센서의 종류에 따라 출력 값을 조정하는 코드가 필요하다.
adcResult = ADC;
// A/D 변환 결과를 모니터에 출력 한다.
SCI_OutChar(CR);
SCI_OutString(" ");
SCI_OutChar(CR);
// ADC의 출력을 부호 없는 10진수로 출력한다.
// 센서의 종류에 따라 출력 값을 조정하는 프로그램이 필요하다.
SCI_OutUDec(adcResult);
}
- PC와 AVR 사이에 UART 통신선을 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 GND와 Atmega128의 GND를 연결한다.
- Atmega128 개발보드와 센서 모듈 연결
- Atmega128 개발보드 ADC0를 입력 단자(PF0) <-> 센서의 Analog output pin
- Atmega128 개발보드 VDD(5V} <-> 센서 Vdd pin(센서의 종류에 따라 공급 전압을 확인 할 것)
- Atmega128 개발보드 GND <-> 센서 GND
주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.
참고자료: USB - Serial 변환 모듈
- sensor_analog_interrupt_uart.zip 파일을 Download하여 압축을 해제한다.
- sensor_analog_interrupt_uart.hex를 개발 보드에 Upload 한다.
- 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
- 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate(19200) 등을 설정)을 한다.
- 실험:
- 개발 보드의 Reset SW를 누르면 모니터에 "ADC Testing." 메세지가 출력된다.
- 0.1 Sec 주기로 ADC0(PF0)의 전압 값이 A/D 변환되어 모니터에 출력된다.
- 센서에 신호(센서의 종류에 따라)를 가하고 Console에 출력되는 측정 값과 비교한다.
- 초음파 거리 센서(HC-SR04)
- 초음파 거리 센서(HC-SR04) 모듈을 제어하는 프로그램 예
- 초음파 거리 센서(HC-SR04) 모듈을 제어하는 프로그램 예(Atmel Studio 7): sensor_pulse_width_HC_SR04.zip
초음파 거리 센서(HC-SR04) 모듈을 사용하는 구성도 예
초음파 거리 센서(HC-SR04) 모듈은 초음파를 반사하는 물체까지의 거리에 비례한 Pulse 폭을 출력한다.
아래 프로그램 예는 sensor_pulse_width_HC_SR04 프로그램 중 Timer를 이용하여 Trigger 신호를 출력하고 펄스폭을 측정하는 프로그램 예이다. 전체 프로그램은 sensor_pulse_width_HC_SR04.zip에 포함되어 있다.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "gnu_sciutil.h"
#include "timer1_input_capture_pulse_width_measure.h"
#define TRIGER_PORT PORTE
#define TRIGER_DDR DDRE
#define TRIGER_BIT 3
#define CAPTURE_PORT PORTE
#define CAPTURE_DDR DDRE
#define CAPTURE_PORT_BIT 7
#define MEASURE_PERIOD 6250 // 0.1Sec <- 16uSec * 6250
#define TRIGER_WIDTH 3 // 12uSSec <- 4uSec * 3
volatile unsigned short int oldICR;
unsigned short int pulseWidth, distance;
unsigned long int long_dist;
void init_port(void)
{
TRIGER_DDR |= (1 << TRIGER_BIT); // Triger 출력 Port를 Output port로 설정한다.
TRIGER_PORT &= ~(1 << TRIGER_BIT); // Triger 출력 Port를 초기화(0)
CAPTURE_DDR &= ~(1 << CAPTURE_PORT_BIT); // ICP1(PD4 : J2 --> 16번)을
CAPTURE_PORT &= ~(1 << CAPTURE_PORT_BIT); // ? Input Capture Register Tregger 신호의 입력 단자로 사용 한다.
}
// Timer1A의 Output Compare Register(OCR1A)는 측정 주기 발생을 위하여 사용 한다.
// 측정주기 0.1Sec <- 16uSec * 6250
// Prescale clk/256, Clock 주기 : 16uSec
void timer1_init(void)
{
// (0 << WGM13) | (0 << WGM12) | (0 << WGM11) | (0 << WGM10) : Normal mode
// (0 << COM1A1) | (0 << COM1A0) : Normal port operation, OCnA disconnected.
// (1 << CS12) | (0 << CS11) | (0 << CS10) : 100 prescale ck/256, Clock 주기 : 16uSec
TCCR1B = (1 << CS12) | (0 << CS11) | (0 << CS10);
TCNT1 = 0x00; //Timer/Counter1 Register 초기화
OCR1A = TCNT1 + MEASURE_PERIOD; // 0.1Sec <- 16uSec * 6250
// OCIE1A : Output Compare A Match Interrupt Enable.
TIMSK = (1 << OCIE1A);
}
// Timer3A의 Output Compare Register(OCR3A)는 HC-SR04의 Trigger pulse를 발생을 위하여 사용 한다.
// Timer3A의 Input Capture Register는 펄스 폭을 측정 하기 위한 Rg로 사용 한다.
// 펄스 폭(High 상태) 측정 : Timer3, ICR3를 사용 한다.
// Prescale clk/64, Clock 주기 : 4uSec
void timer3_init(void)
{
// (0 << WGM33) | (0 << WGM32) | (0 << WGM31) | (0 << WGM30) : Normal mode
// (0 << COM3A1) | (0 << COM3A0) : Normal port operation, OCnA disconnected.
// TCCR3A = (0 << COM3A1) | (0 << COM3A0);
// ICNC3: Input Capture Noise Canceler.
// ICES3: Input Capture Edge Select. One : Rising edge, Zero : Falling edge.
// (1 << CS32) | (0 << CS31) | (0 << CS30) : 100 prescale ck/64, Clock 주기 : 4uSec
TCCR3B = (1 << ICNC3) | (1 << ICES3) | (0 << CS32) | (1 << CS31) | (1 << CS30);
TCNT3 = 0x00; //Timer/Counter1 Register 초기화
// TICIE3 ; Input Capture Interrupt Disable.
// OCIE3A : Output Compare A Match Interrupt Disable.
ETIMSK &= ~(1 << OCIE3A);
ETIMSK &= ~(1 << TICIE3);
}
void init_timer(void){
init_port();
timer1_init();
timer3_init();
}
// 측정 주기를 발생
SIGNAL(TIMER1_COMPA_vect)
{
// OCIE1A : Output Compare A Match Interrupt Disable.
TIMSK &= ~(1 << OCIE1A);
// 측정 주기
OCR1A = TCNT1 + MEASURE_PERIOD; // 0.1Sec <- 16uSec * 6250
// Triger 신호를 출력한다. Triger Port <- High
TRIGER_PORT |= (1 << TRIGER_BIT);
// Triger 신호 폭 설정(12uSec <- 4uSec * 3)
OCR3A = TCNT3 + TRIGER_WIDTH;
// Trigger pulse clear를 위한 Timer3 interrupt enable
ETIMSK |= (1 << OCIE3A);
// 측정 주기 발생 Timer interrupt enable.
TIMSK |= (1 << OCIE1A);
}
// HC-SR04의 Trigger pulse를 Low로 하고 Echo 신호의 펄스폭 측정을 Enable 한다.
SIGNAL(TIMER3_COMPA_vect)
{
// OCIE1B : Output Compare B Match Interrupt Disable.
ETIMSK &= ~(1 << OCIE3A);
// Triger Port <- Low
TRIGER_PORT &= ~(1 << TRIGER_BIT);
// Input Capture Interrupt가 Rising edge에서 발생 하도록 설정 한다.
// ICES3: Input Capture Edge Select. One : Rising edge, Zero : Falling edge.
TCCR3B |= (1 << ICES3);
// TICIE3: Input Capture Interrupt Enable.
ETIMSK |= (1 << TICIE3);
}
// HC-SR04의 Echo 펄스폭을 측정하고 결과를 출력한다.
SIGNAL(TIMER3_CAPT_vect)
{
ETIMSK &= ~(1 << TICIE3); // TICIE3 ; Input Capture Interrupt Disable.
// 만약 현재 Rising edge에서 Input Capture Interrupt가 발생된 경우
if((TCCR3B & (1 << ICES3)) != 0){
// 펄스 폭 측정을 위하여 현재 Capture된 ICR3 값을 저장 한다.
oldICR = ICR3;
// 다음 Interrupt는 Falling edge에서 발생 하도록 설정 한다.
// ICES3: Input Capture Edge Select. One : Rising edge, Zero : Falling edge.
TCCR3B &= ~(1 << ICES3);
// TICIE3 ; Input Capture Interrupt Enable.
ETIMSK |= (1 << TICIE3);
}
// 만약 현재 Falling edge에서 Input Capture Interrupt가 발생된 된 경우
else{
// 펄스 폭을 측정(계산) 한다.
pulseWidth = ICR3 - oldICR;
// pulseWidth를 uSec(*4)로 변환한 다음 거리(cm)로 변환한다.
// 거리 cm <- (pulseWidth * 4(uSec)) / 58 <- ((pulseWidth * 4(uSec)) * 17) / 1000
// 거리 cm <- (pulseWidth * 17) / 250
long_dist = ((unsigned long)pulseWidth * 17) / 250;
distance = long_dist;
// 측정 된 펄스 폭 값을 모니터에 출력 한다.
SCI_OutChar(CR);
SCI_OutString(" ");
SCI_OutChar(CR);
// 거리(cm)를 부호 없는 10진수로 출력한다.
SCI_OutUDec(distance);
}
}
- PC와 AVR 사이에 UART 통신선을 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 GND와 Atmega128의 GND를 연결한다.
- Atmega128 개발보드와 센서 모듈 연결
- Atmega128 개발보드 Trigger output pin(PE3) <-> HC-SR04 센서의 Trig pin
- Atmega128 개발보드 Pulse input pin(PE7) <-> HC-SR04 센서의 Echo pin
- Atmega128 개발보드 VDD(5V} <-> HC-SR04 센서 Vdd pin
- Atmega128 개발보드 GND <-> HC-SR04 센서 GND
주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.
- sensor_pulse_width_HC_SR04.zip 파일을 Download하여 압축을 해제한다.
- sensor_pulse_width_HC_SR04.hex를 개발 보드에 Upload 한다.
- 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
- 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate(19200) 등을 설정)을 한다.
- 실험:
- 개발 보드의 Reset SW를 누르면 모니터에 "Pulse width output sensor testing." 메세지가 출력된다.
- 0.1Sec 주기로 거리가 측정되어 모니터에 출력된다.
- 초음파 거리센서 앞에 반사체의 위치를 변경하며 실험한다.
- 온도/습도 센서(DHT11/DHT22) 모듈
- 온도/습도 센서(DHT11/DHT22) 모듈을 제어하는 프로그램 예
- 온도/습도 센서(DHT11) 모듈을 제어하는 프로그램 예(Atmel Studio 7): single_wire_comm_DHT11.zip
DHT11/DHT22 센서 모듈을 사용하는 구성도 예
DHT11 센서 모듈에 따른의 Pin 배치 예
주: 위 예와 같이 DHT11 센서 모듈의 제작 회사에 따라 Pin 배치와 Pull-up 저항의 내장여부가 다르기 때문에 주의를 요함. 2번 모듈인 경우에는 10K Pull-up 저항이 내장되어 있다.
온도/습도 센서(DHT11/DHT22) 모듈은 측정한 온도/습도 값을 디지털 데이터로 변환하여 Single-Wire 통신 프로토콜로 출력한다.
DHT11 센서의 Data signal timming diadram 예. 더 자세한 자료는 DHT11 Data sheet에서 확인하기 바람.
아래 프로그램 예는 single_wire_comm_DHT11 프로그램 중 측정 결과를 읽는 함수와 결과를 모니터에 출력하는 함수 예이다. 전체 프로그램은 single_wire_comm_DHT11.zip에 포함되어 있다.
#include <avr/io.h>
#include "timer0_clock.h"
#include "gnu_sciutil.h"
// DEFINE SETUP
#define SENSOR_DDR DDRC
#define SENSOR_PORT PORTC
#define SENSOR_PIN PINC
#define SENSOR_PIN_BIT PC5
// GLOBAL VARIABLES
uint8_t DHT11Data[5] = {0};
static uint8_t DHT11Init = 0;
// DHT11 초기화
void DHT11Setup(){
// Power on 후 DHT11 이 안정화(사용 가능한 상태)되는데 약 1초 정도가 필요하다.
delay(2000);
// SENSOR_PORT를 output port로 설정한다.
SENSOR_DDR |= 1 << SENSOR_PIN_BIT;
// Set setup flag
DHT11Init = 1;
}
// 온도를 출력하는 함수
void DHT11DisplayTemperature(){
SCI_OutString("온도: ");
SCI_OutUDec(DHT11Data[2]);
SCI_OutChar('.');
SCI_OutUDec(DHT11Data[3]);
SCI_OutChar('C');
}
// 습도를 출력하는 함수
void DHT11DisplayHumidity(){
SCI_OutString("습도: ");
SCI_OutUDec(DHT11Data[0]);
SCI_OutChar('.');
SCI_OutUDec(DHT11Data[1]);
SCI_OutChar('%');
}
// DHT11의 습도와 온도 값을 읽는 함수
int8_t DHT11ReadData(){
uint8_t sensor_bytes, bits, buffer=0, timeout = 0, checksum;
// 만약 DHT11 초기화가 실행되지 않은 경우 DHT11를 초기화한다.
if(DHT11Init == 0) DHT11Setup();
// START signal을 Sensor에 Send 한다.
// SENSOR_PORT를 output port로 설정한다.
SENSOR_DDR |= (1 << SENSOR_PIN_BIT);
SENSOR_PORT &= ~(1 << SENSOR_PIN_BIT); // Pin에 LOW를 출력한다.
delay(20); // Pin의 LOW 상태를 최소 18 mSec 동안 유지한다.
// SENSOR_DDR을 Input port(high Z)로 설정한다.
// Data line에 신호가 없는 경우 Pull-up 저항에 의하여 Data line은 HIGH 상태가된다.
SENSOR_DDR &= ~(1 << SENSOR_PIN_BIT);
delayMicroseconds(32); // Wait for 20-40 us
// Sensor 응답 신호를 Check 한다. 80us LOW -> 80us HIGH signal
// 만약 신호가 HIGH 이면(Sensor didn't respond) Error code를 Return 한다.
if(SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
return 0; // Error code
}
// Sensor가 LOW signal을 Send 한 경우 HIGH 신호를 기다린다.
delayMicroseconds(82);
// 만약 HIGH인 경우 Sensor는 Data를 Send 할 준비가 된 상태이다.
if(SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
delayMicroseconds(82); // HIGH 신호가 종료되기를 기다린다.
// 만약 HIGH 상태가 계속되면 Error 가 발생한 것이기 때문에 0를 Return 한다.
if(SENSOR_PIN & (1 << SENSOR_PIN_BIT)) return 0;
}else{
return 0; // Error code
}
// Sensor로 부터 Data(5 Byte)를 읽는다.
for(sensor_bytes = 0; sensor_bytes < 5; sensor_bytes++){
// Sensor로 부터 수신한 Bit Data를 Byte Data로 변환하는 값을 저장하는 buffer를 초기화한다.
buffer = 0;
// 8 Bits를 수신하여 Byte로 변환한다.
for(bits = 0; bits < 8; bits++){
// 각 Bits를 수신할 때 마다 Signal이 Low인 상태를 50uSec 동안 기다린다.
while(~SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
// Signal Low 상태를 기다리는 시간을 최대 80uSec로 제한한다.
// Signal이 Low인 상태를 80uSec 이상 지속하면 Error code(Return 0)를 Return한다.
timeout++;
if(timeout > 8) break;
delayMicroseconds(10);
}
timeout = 0;
// Signal이 HIGH 이면 Bit 값을 읽는다.
if(SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
// bit 값이 0인 경우 26-28 us 동안 HIGH 이고, bit 값이 1인 경우 70uSec 동안 High이다.
delayMicroseconds(40);
// 만약 Signal이 HIGH 상태이면 buffer의 bits 위치를 1로 Set 한다.
if(SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
// buffer의 bits 위치를 1로 Set 한다.
// Sensor는 MSB 먼저 송신한다.
buffer |= 1 << (7 - bits);
}
// Signal의 HIGH 상태가 종료되기를 80uSec 동안 기다린다.
while(SENSOR_PIN & (1 << SENSOR_PIN_BIT)){
// Signal High 상태를 기다리는 시간을 최대 80uSec로 제한한다.
timeout++;
if(timeout > 8) break;
delayMicroseconds(10);
}
timeout = 0;
}else{
// Signal LOW 인 상태를 지속하면 0를 Return(Error response) 한다.
return 0;
}
}
// 수신한 Byte data를 DHT11Data[sensor_bytes]에 저장한다.
DHT11Data[sensor_bytes] = buffer;
}
// Data transmision 이 조료되기를 기다린다. Sensor는 50uSec 동안 LOW를 출력하고,
// 다음 START command 이 있을 때까지 Low-power consumption mode가 된다.
// Sensor 가 안정되어 다음 측정이 가능한 상태까지 약 1Sec 정도의 시간이 필요하다.
delayMicroseconds(60);
// Idle 상태일 때 Sensor DATA line은 HIGH 상태를 유지하여야 한다.
// 아래와 같이 AVR에서 High를 출력 할 수도 있지만 더 좋은 방법은
// Idle 상태(high Z)에서는 Pull-up 저항으로 High 상태가 되도록 하는 방법이다.
// Pull-up 저항으로 High 상태가 되도록 하기 위하여는 적당한 값의 Pull-up 저항을 사용하여야 한다.
// AVR에서 High를 출력하는 코드 예
// SENSOR_DDR |= 1 << SENSOR_PIN_BIT;
// SENSOR_PORT |= 1 << SENSOR_PIN_BIT;
// Data transmission errors를 check 한다.
checksum = DHT11Data[0] + DHT11Data[1] + DHT11Data[2] + DHT11Data[3];
if(checksum != DHT11Data[4]){
return -1; // Checksum error code
}
// OK return code
return 1;
}
- PC와 AVR 사이에 UART 통신선을 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Atmega128의 TXD0(PE1)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Atmega128의 RXD0(PE0)를 연결한다.
- 컴퓨터(USB --> UART(RS232) 변환 모듈)의 GND와 Atmega128의 GND를 연결한다.
- Atmega128 개발보드와 센서 모듈 연결
- Atmega128 개발보드 Data pin(PC5) <-> DHT11 센서의 Data pin
- Atmega128 개발보드 VDD(5V} <-> DHT11 센서 Vcc pin
- Atmega128 개발보드 GND <-> DHT11 센서 GND
주: 컴퓨터에 Serial Port가 없는 경우 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. 개발보드에 따라서는 "USB --> UART(RS232) 변환 모듈"을 내장하고 있는 경우가 많기 때문에 본인이 사용하는 개발보드에서 확인 하여야 한다.
- single_wire_comm_DHT11.zip 파일을 Download하여 압축을 해제한다.
- single_wire_comm_DHT11.hex를 개발 보드에 Upload 한다.
- 모니터 프로그램(예: OC-Console, Tera Term)을 설치(이미 설치되어 있는 경우에는 실행만 하면됨)하고 실행 한다.
- 모니터 프로그램에서 필요한 설정(Serial Port와 Baudrate(19200) 등을 설정)을 한다.
- 실험:
- 개발 보드의 Reset SW를 누르면 모니터에 "DHT11 Testing" 메세지가 출력된다.
- 약 2초 주기로 DHT11 센서의 측정 결과(온도와 습도)가 Console에 출력된다.
- 센서의 온도와 습도를 변경하며 결과를 관측한다.
- 디지털 출력 온도 센서(DS1621)
- 디지털 출력 온도 센서(DS1621)를 제어하는 프로그램 예
- AVR(Atmega128) 센서(Sensors)와 센서 모듈(Sensor Modules) 관련 페이지 보기
I2C 통신을 이용한 측정 과 제어 시스템 구성도
주: AVR 보드 또는 센서 모듈에 Pull-Up 저항이 내장되지 않은 경우 I2C Pull-Up 저항(데이터 선의 길이에 따라 1K - 10K 저항을 사용)이 필요하다. 아래 프로그램 예에서 링크되는 TWI 통신 예제 페이지에 회로 예가 있다.
디지털 출력 온도 센서(DS1621)를 사용하는 시스템 구성과 프로그램 예는 "TWI 통신을 사용한 응용 프로그램 예: DS1621을 사용한 온도 측정 프로그램 예"에서 설명하였으니 참고하기 바람.