TS601 과 CLCD를 ATmega8에서 사용 하기위한 회로도.


이번에 프로젝트때문에 초음파센서가 필요해서 하나 주문해서 구현해봤습니다.^^



기존의 많이 사용하시는 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;

}



USART통신으로 PC상에 뿌려주는 코드입니다. 저는 이게 귀찮아서 바로 ATmega8에 연결한 CLCD에 뿌려봤습니다.
처음 ATmega8을 사용하시는 분이 계실까봐 아래에 주석을 남깁니다.^^
(그리고 ATmega8로 CLCD를 사용하시면 데이터핀을 8개 쓸만큼 여유가 없기때문에 설계하실때 4핀으로 제어하셔야 합니다.)

/* -------------------------------------------인터럽트 서비스 루틴----------------------------------------------- */


ISR(TIMER2_COMP_vect) //타이머 인터럽트 서비스 루틴 ->언제 실행되는가? -> 비교일치 
{
tick++;
}

ISR(INT1_vect) //외부 인터럽트 서비스 루틴
{
u16 pulse_tick;
pulse_tick = tick;  //타이머 인터럽트 서비스루틴에서 계수된 인터럽트값을 pulse_tick 에 저장.

if( MCUCR & 0x0C ) // INT1이 The rising edge일때 인터럽트를 감지하는 상태라면
{
MCUCR &= 0xF3;  //로우레벨 감지로 변경시키고(인터럽트를 끄는느낌) 초기화.

tick = 0;  //타이머 인터럽트의 변수를 초기화.
}
else  //그리고 다음 싸이클에서 다시 인터럽트 시작.
{
MCUCR |= 0x0C;  // INT1을 The rising edge 감지상태로 다시 만들어줌.
pulse_end = pulse_tick; //계수된 펄스값을 저장함.
}
}

결국 아트메가32나 8이나 동일하더군요..ㅎㅎ 그냥 ATmega128과 MCUCR때문에 조금 차이가 있을뿐입니다.
128에서 TIFR, TIMSK와 같은 레지스터가 있어서 인터럽트에 대한 설정들을 했었지만 ATmega 8과 32 시리즈는 MCUCR레지스터로 제어 한다것만 달랐습니다. ^^



어쨌든 위와 같이 ATmega8A 로 2개의 TS601을 구현할수가 있었습니다~ 온도센서는 제 블로그에 있는 NTC-10KD-5J를 사용해서 보상했으며 평균값함수를 사용하니 거리의 오차는 1%미만, 최대 측정거리는 3.3M 였습니다 ^^



NT-TS601.pdf


'Nobody tells you about.. > Ultrasonic' 카테고리의 다른 글

[HRLV-MaxSonar-WRC] MB7367 초음파센서  (0) 2012.10.23

+ Recent posts