HC-SR04(초음파 센서)의 이해 Datasheet : HCSR04.pdf
초음파란? 주파수가 20kHz를 넘는 사람이 듣지 못하는 음파를 초음파라고 한다.
HC-SR04 란? 초음파 센서 모듈로 초음파 송신부(Trig), 초음파 수신부(Echo), 제어회로로
구성되어 있는데, 가격적으로 저렴하고 사용자가 간편하게 초음파를 제어해 거리를 측정 할 수 있도록 만들어졌다.
이 초음파 센서는 전방 2cm ~ 400cm의 15도까지 정확하게 측정이 가능하다. 하지만 측정이 가능
하게 하려면 사용자는 이 제품의 데이터 시트가 원하는 조건을 들어주어야 한다.
그 조건이란 타이밍 다이어그램을 말하는데 이 HC-HSR04말고도 다른 제품을 사용할때,
타이밍 다이어그램이 존재한다면 그것을 이해하는것은 매우 중요하다.
HC-SR04 Timing Diagram
[타이밍 다이어그램 해석] 1. 모듈의 트리거 인풋에 10 us의 하이펄스를 준다. 2. 40KHz의 8개 초음파 버스트 발생. [1번 과정을 거쳐야만 발생] 3. 에코는 초음파 발신 직후 HIGH 레벨이 되고, 반항을 감지하면 LOW 레벨이 된다. -> 에코 펄스는 즉, 초음파가 장애물을 만나 다시 에코로 돌아올때까지의 왕복 시간을 나타낸다, 4. 거리 = 에코 High Pulse 시간(왕복시간) x 소리의 속도(340m/s) / 2 -> 왕복이므로 2로 나누어 주어야한다. |
위는 HC-SR04 데이터 시트의일부 내용이다. 측정 주기를 60ms 이상 주어서 측정을 하라는 말이다. 위에 보면 자세하지 않은 타이밍 다이어그램도 그렇고, 바로 위에 이 측정 주기를 60ms 이상으로 주어라....
뭐 사용하는데 지장은 없겠지만, 저는 완벽하게 이해하기 위해서 이 HC-SR04와 비슷한 제품인
SRF-04를 찾을 수 있었다.
보기전에 SRF-04 제품은 2cm ~ 300cm 측정이 가능하기에 이 부분이 다르다,
즉 걸러낼것은 걸러내고 HC-SR04 제품을 생각하면서 참고를 목적으로 봐야한다.
SRF04 Timing Diagram
HC-SR04 제품보다 이 SRF04제품은 타이밍 다이어그램에 더 자세한 설명들이 적혀있다.
1. 우선 에코펄스. 에코 펄스가 100us ~ 18ms 의 범위라고 나오는데, 위에서 말했듯이 이것은
측정 가능한 범위를 나타낸다. 2cm ~ 300cm를 나타내는데,
직접 에코펄스*소리의 속도/2를 계산해보면 알수있다. HC-SR04 제품은 최대 측정 거리가 400cm 이므로 에코 펄스가 더 클 수 있다는 점을 알아야한다.
또한 객체탐지가 안됬을시, 즉 8개의 초음파 버스트가 모두 장애물 감지를 못했을때. 최대 36ms까지 펄스가 커진다는 점도 알아야한다.
2. 다음은 에코펄스가 끝나고 다음 트리거를 주기전까지 10ms의 딜레이가 필요한데, 그 이유는
8개의 초음파 펄스가 모두 사라질 때까지 대기해야 하기 때문이다. 8개중 1개가 제일 가까운 장애물을 감지하고 들어왔는데, 나머지 7개의 버스트가 들어오지 않았기 때문에 딜레이가 필요하다는 거다.
-> 결과적으로 보면 10us의 트리거 입력 주기(측정주기)를 이 제품은 약 50ms 주기로 측정해야 하고, 왜 HC-SR04 제품이 60ms의 주기로 측정하라는 건지 어느정도 이해갔을것이다.
지금까지의 과정을 이해했다면, 초음파 센서로 거리가 어떻게 측정되는지 감이 왔을것이다.
거리 = 속도 x 시간 이므로, 거리 = 소리의 속도(0.034 cm/us) x 에코 펄스시간이 된다.
위 사진은 역으로 에코펄스의 시간을 구해보았다. 만약 장애물이 10cm라 가정했을때,
에코 펄스는 588.235us가 된다는것을 알 수 있다.
소리의 속도는 340m/s = 0.034 cm/s
즉, 1cm가는데 걸리는 시간은 29us인데, 왕복이므로 58us가 된다.
10cm 이므로 580us.
외부인터럽트와 16bit 타이머를 이용한 초음파 센서 제어
해상도(CM, MM 등)
1cm 왕복시간은 58us이고, 1mm 왕복시간은 5.88us 이다.
거리 = 속도 x 시간 / 2 = 소리의 속도 x ((F-R TCNT) x 분주비/F CPU) / 2
빨간색으로 표시한 부분이 에코펄스 구간이다.
센티미터
이 제품의 최소 거리인 2cm의 에코펄스는 116us가 된다.
3cm는? +58us
4cm는? +58us
밀리미터
동일하게 최소 거리인 20mm의 에코펄스는 116us가 되고,
21mm는? +5.88us
22mm는? +5.88us
결과적으로 분주비와 F CPU 선택이 해상도에 영향을 준다는것을 알 수 있다.
** 참고한 소스코드(https://cafe.naver.com/circuitsmanual/149885) **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #define F_CPU 16000000UL // 16 MHz #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> // volatile unsigned int buf[8],dist[8],start=0,end=0; volatile unsigned char cnt=0,flag[8]={0,}; // ISR(INT0_vect){ if(EICRA==0x03)start=TCNT1; else{ end=TCNT1; buf[0]=end-start; EIMSK=0; flag[0]=1; } EICRA^=0x01; } ISR(INT1_vect){ if(EICRA==0x0C)start=TCNT1; else{ end=TCNT1; buf[1]=end-start; EIMSK=0; flag[1]=1; } EICRA^=0x04; } ISR(INT2_vect){ if(EICRA==0x30)start=TCNT1; else{ end=TCNT1; buf[2]=end-start; EIMSK=0; flag[2]=1; } EICRA^=0x10; } ISR(INT3_vect){ if(EICRA==0xC0)start=TCNT1; else{ end=TCNT1; buf[3]=end-start; EIMSK=0; flag[3]=1; } EICRA^=0x40; } ISR(INT4_vect){ if(EICRB==0x03)start=TCNT1; else{ end=TCNT1; buf[4]=end-start; EIMSK=0; flag[4]=1; } EICRB^=0x01; } ISR(INT5_vect){ if(EICRB==0x0C)start=TCNT1; else{ end=TCNT1; buf[5]=end-start; EIMSK=0; flag[5]=1; } EICRB^=0x04; } ISR(INT6_vect){ if(EICRB==0x30)start=TCNT1; else{ end=TCNT1; buf[6]=end-start; EIMSK=0; flag[6]=1; } EICRB^=0x10; } ISR(INT7_vect){ if(EICRB==0xC0)start=TCNT1; else{ end=TCNT1; buf[7]=end-start; EIMSK=0; flag[7]=1; } EICRB^=0x40; } // ISR(TIMER1_COMPA_vect){ switch(cnt){ case 0: PORTA|=0x01; _delay_us(10); PORTA&=~0x01; EICRA=0x03; EICRB=0x00; EIFR=0xFF; EIMSK=0x01; break; case 1: PORTA|=0x02; _delay_us(10); PORTA&=~0x02; EICRA=0x0C; EICRB=0x00; EIFR=0xFF; EIMSK=0x02; break; case 2: PORTA|=0x04; _delay_us(10); PORTA&=~0x04; EICRA=0x30; EICRB=0x00; EIFR=0xFF; EIMSK=0x04; break; case 3: PORTA|=0x08; _delay_us(10); PORTA&=~0x08; EICRA=0xC0; EICRB=0x00; EIFR=0xFF; EIMSK=0x08; break; case 4: PORTA|=0x19; _delay_us(10); PORTA&=~0x10; EICRA=0x00; EICRB=0x03; EIFR=0xFF; EIMSK=0x10; break; case 5: PORTA|=0x20; _delay_us(10); PORTA&=~0x20; EICRA=0x00; EICRB=0x0C; EIFR=0xFF; EIMSK=0x20; break; case 6: PORTA|=0x40; _delay_us(10); PORTA&=~0x40; EICRA=0x00; EICRB=0x30; EIFR=0xFF; EIMSK=0x40; break; case 7: PORTA|=0x80; _delay_us(10); PORTA&=~0x80; EICRA=0x00; EICRB=0xC0; EIFR=0xFF; EIMSK=0x80; break; } if(++cnt>7)cnt=0; } // int main(void){ DDRA=0xFF; // 트리거 DDRB=0xff; TCCR1B=0x0C; OCR1A=3124; TIMSK=0x10; //16000000/256/(1+ 3124)=20Hz=50ms SREG=0x80; while(1){ if(flag[0]){ flag[0]=0; dist[0]=(int)((float)buf[0]/14.5); } if(flag[1]){ flag[1]=0; dist[1]=(int)((float)buf[1]/14.5); } if(flag[2]){ flag[2]=0; dist[2]=(int)((float)buf[2]/14.5); } if(flag[3]){ flag[3]=0; dist[3]=(int)((float)buf[3]/14.5); } if(flag[4]){ flag[4]=0; dist[4]=(int)((float)buf[4]/14.5); } if(flag[5]){ flag[5]=0; dist[5]=(int)((float)buf[5]/14.5); } if(flag[6]){ flag[6]=0; dist[6]=(int)((float)buf[6]/14.5); } if(flag[7]){ flag[7]=0; dist[7]=(int)((float)buf[7]/14.5); } } } | cs |
공부할때 정말 많은 도움이 된 전자공작 사이트 주소입니다. http://cafe.naver.com/circuitsmanual
'Embedded System > ATmega128' 카테고리의 다른 글
[ATmega128] DHT11(온습도 센서) 제어 (10) | 2019.12.02 |
---|---|
[ATmega128] sg90(서보모터) 제어 (2) | 2019.10.02 |
[ATmega128] Smart Moving Trash Can Project (0) | 2019.09.18 |
[ATmega128] DFPlayer_Mini (15) | 2019.08.16 |
MAX7219를 이용한 도트매트릭스 제어 (2) | 2017.08.11 |