이번에 프로젝트때문에 초음파센서가 필요해서 하나 주문해서 구현해봤습니다.^^
기존의 많이 사용하시는 SRF-04 (핀4개) 와는 다르게 핀이 3개밖에 없어서 처음에 이게 뭔가 했는데요..
원리는 간단했습니다.
[제품의 동작방법]
먼저 MCU 의 출력핀으로 NT-TS601 의 SIG 핀에 Input trigger pulse(t1)를 보내줍니다.
NT-TS601 의 SIG 핀에 Input trigger pulse 를 받은 NT-TS601 의 초음파센서 TX pin 에서
40kHz 로 Burst pulse 를 발생합니다.
Output echo pulse 가 나타날 때까지 Echo postpone(t2)을 기다립니다.
Burst pulse 가 물체에 반사되어 올 때까지 Output echo pulse 를 체크합니다.
MCU 가 입력받은 Output echo pulse 의 폭을 측정하여 거리로 나타낼 수 있습니다.
다시 측정하기 위해서는 최소 200 μs 이상 기다린 후에 Input trigger pulse 를 보냅니다.
즉, 간단하게 말해서 MCU에게 High신호를 센서핀에게 줘라 -> 센서는 초음파를 쏘고 -> 기다렸다가 동일한 핀으로 초음파에서 출력했던 펄스가 물체를 감지후 돌아온 에코펄스를 읽어라. 그러나 여기서 중요한것은 에코펄스를 읽을때 인터럽트가 걸리는 시간을 이용해서 물체의 거리를 측정한다는 것입니다.
음파 속도 V = 331.5 + 0.60714 T [m/s]
그러나 센서의 동작 범위의 0 ℃에서 70 ℃까지로 오차는 약 11 ~ 12 % 정도입니다. 따라서 주위 온도에 의해서 음속이 변함으로 정밀도가 높은 거리를 측정할 경우에는 온도 보상을 필요로 합니다. 아무래도..온도센서를 사용해서 함께 구현해야지 않을까 생각이 되네요.그리고 초음파의 특성상 측정되는 오브젝트의 형태(곡면일경우 또 반사되겠죠?)와 재질(천인지 금속인지에따라)에 또 측정값이 변할테니..신뢰성있는 값을 얻어내려면 평균값필터나 무빙에버레지도 필요할듯 합니다.
아래는 업체(엔티렉스)에서 제공하는 공개소스입니다.
/********************************************************************************
Title : TS601 module TEST Code
MCU : Atmega32
외부 xtal : 16MHz
File Name : ultra00.c
Data : 2008/06/27 (Ver1.1)
Notice : 아래 코드는 TS601 module TEST 프로그램이며
이 프로그램을 이용하여 발생하는 모든 문제에 대해서는
(주)엔티렉스에서는 어떠한 법적 책임도 지지 않습니다.
참고
1. TS601 module의 SIG pin과 Atmega32 PD3 pin 사이에
1kΩ을 넣도록 권장합니다.
2.RS-232C 통신을 통한 하이퍼터미널로 확인할 수 있습니다.
( 9600 bps / 8-n-1 )
*******************************************************************************/
#include "io.h"
#include "interrupt.h"
#include "delay.h"
#include "avrlibdefs.h"
#include "avrlibtypes.h"
#define PD3pin_clear cbi(PORTD, 3)
#define PD3pin_set sbi(PORTD, 3)
#define PD3pin_IN cbi(DDRD, 3)
#define PD3pin_OUT sbi(DDRD, 3)
#define TEMPERATURE 25
// global variable
volatile u16 tick = 0;
volatile u16 pulse_check = 0;
volatile u16 pulse_end = 0;
void PORT_init(void)
{
PORTA = 0x00;
DDRA = 0xFF;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00;
DDRC = 0xFF;
PORTD = 0x08;
DDRD = 0xFA;
}
void EXTINT_init(void)
{
MCUCR = 0x6F;
GICR = (1<<INT1);
GIFR = 0x00;
}
void TIMER0_COMPA_init(void)
{
TCCR0 = (1<<WGM01)|(1<<CS01);
TCNT0 = 0;
OCR0 = 19; // 1cycle --> 20us = 1/(16M/(2*8*(19+1))
TIMSK = (1<<OCIE0);
TIFR = 0x00;
}
void USART_Init( void )
{
/* Set baud rate 16MHz, 9600 bps */
UBRRH = 0x00;
UBRRL = 103;
/* Enable transmitter */
UCSRB = (1<<TXEN);
/* Set frame format: 8data, 1stop bit */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
void USART_Transmit( unsigned char ultrasonic )
{
/* Wait for empty transmit buffer */
while ( !(UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = ultrasonic;
}
ISR(TIMER0_COMP_vect) //핵심소스는 이부분이 되겠네요..ㅎ
{
tick++;
}
ISR(INT1_vect)
{
u16 pulse_tick;
pulse_tick = tick;
if( MCUCR & 0x0C ) {
MCUCR &= 0xF3;
tick = 0;
}
else {
MCUCR |= 0x0C;
pulse_end = pulse_tick;
}
}
int main(void)
{
unsigned char thousand, hundred, ten, one;
float distance;
PORT_init();
EXTINT_init();
TIMER0_COMPA_init();
USART_Init();
_delay_ms(50);
while(1)
{
cli();
PD3pin_clear;
PD3pin_OUT; // PD3 pin is output
_delay_us(500);
PD3pin_set; // output set during 5us
_delay_us(5);
PD3pin_clear;
_delay_us(100);
PD3pin_IN; // PD3 pin is input
_delay_us(100);
sei();
/* distance = velocity * time */
distance = (331.5+(0.6*TEMPERATURE))*(pulse_end*0.00001/2)*1000;
/* distance digit display */
thousand = distance/1000;
USART_Transmit(thousand + 48);
distance = distance - (thousand * 1000);
hundred = distance /100;
USART_Transmit(hundred + 48);
distance = distance - (hundred * 100);
ten = distance/10;
USART_Transmit(ten + 48);
distance = distance - (ten * 10);
one = distance;
USART_Transmit( one + 48);
USART_Transmit(109);
USART_Transmit(109);
USART_Transmit('\n');
USART_Transmit('\r');
_delay_ms(100);
}
return 0;
}
'Nobody tells you about.. > Ultrasonic' 카테고리의 다른 글
[HRLV-MaxSonar-WRC] MB7367 초음파센서 (0) | 2012.10.23 |
---|