728x90
더보기
SRF02를 사용하여 거리를 측정하는 프로그램을 작성하시오.
SRF02를 사용하여 거리를 측정하는 프로그램을 작성하시오.
위 문제는 초음파센서를 사용해보는 예제였는데 원래 항상 아두이노에 사용되던 간단한 센서를 사용했는데 이 아이는 자체 주소값들도 가지고 있고 TWI통신도 이용해야해서 생각보다 되게 까다로웠다.
#define _USE_SAFTY_TWI_ //에러체크 모드를 사용했기에 필요하다
#include <mega128.h>
#include <stdio.h>
#include "twi.h"
#include "lcd.h"
#define COM_REG 0
#define SRF02_1st_Seq_change 160
#define SRF02_2nd_Seq_change 170
#define SRF02_3rd_Seq_change 165
#define SRF02_Return_inch 80
#define SRF02_Return_Cm 81
#define SRF02_Return_microSecond 82
unsigned char ti_Cnt_1ms;
unsigned char LCD_DelCnt_1ms;
void Timer0_Init() //타이머 기본 설정
{
TCCR0 = (1<<WGM01)|(1<<CS00)|(1<<CS01)|(1<<CS02);
TCNT0 = 0x00;
OCR2 = 14;
TIMSK = (1<<OCIE0);
}
interrupt [TIM0_COMP] void timer0_comp(void) //타이머 인터럽트
{
ti_Cnt_1ms ++;
LCD_DelCnt_1ms ++;
}
unsigned char SRF02_I2C_Write(char address, char reg, char data)
{
unsigned char ret_err = 0;
ret_err = TWI_Start();
ret_err = TWI_Write_SLAW(address);
if(ret_err !=0) return ret_err;
ret_err = TWI_Write_Data(reg);
if(ret_err != 0) return ret_err;
ret_err = TWI_Write_Data(data);
if(ret_err != 0) return ret_err;
TWI_Stop();
return 0;
}
unsigned char SRF02_I2C_Read(char address, char reg, unsigned char* Data)
{
char read_data = 0;
unsigned char ret_err = 0;
ret_err = TWI_Start();
ret_err = TWI_Write_SLAW(address);
if(ret_err !=0) return ret_err;
ret_err = TWI_Write_Data(reg);
if(ret_err !=0) return ret_err;
ret_err = TWI_Restart();
PORTB|= 0x08;
if(ret_err !=0) return ret_err;
ret_err = TWI_Write_SLAR(address);
PORTB |= 0x10;
if(ret_err !=0) return ret_err;
ret_err = TWI_Read_Data_NACK(&read_data);
PORTB |= 0x20;
if(ret_err !=0) return ret_err;
TWI_Stop();
*Data = read_data;
return 0;
}
unsigned char startRanging(char addr)
{
return SRF02_I2C_Write(addr, COM_REG, SRF02_Return_Cm);
}
unsigned int getRange(char addr, unsigned int*pDistance)
{
unsigned char temp;
unsigned char res = 0;
res = SRF02_I2C_Read(addr,2,&temp);
if(res) return res;
*pDistance = temp << 8;
res = SRF02_I2C_Read(addr,3,&temp);
if(res) return res;
*pDistance |= temp;
return res;
}
unsigned char change_Sonar_Addr(unsigned char ori, unsigned char des)
{
unsigned char res = 0;
switch(des)
{ //초음파센서는 FE까지 주소가 가능
case 0xE0:
case 0xE2:
case 0xE4:
case 0xE6:
case 0xE8:
case 0xEA:
case 0xEC:
case 0xEE:
case 0xF0:
case 0xF2:
case 0xF4:
case 0xF6:
case 0xF8:
case 0xFA:
case 0xFC:
case 0xFE:
res = SRF02_I2C_Write(ori, COM_REG, SRF02_1st_Seq_change);
if(res) return res;
res = SRF02_I2C_Write(ori, COM_REG, SRF02_2nd_Seq_change);
if(res) return res;
res = SRF02_I2C_Write(ori, COM_REG, SRF02_3rd_Seq_change);
if(res) return res;
res = SRF02_I2C_Write(ori,COM_REG,des);
if(res) return res;
break;
default:
return -1;
}
return 0;
}
void main(void)
{
char Sonar_Addr = 0xE0;
unsigned int Sonar_range;
char Message[40];
int readCnt = 0;
unsigned char res = 0;
DDRD |= 0x03;
LCD_Init();
Timer0_Init();
Init_TWI();
delay_ms(1000);
SREG|=0x80;
startRanging(Sonar_Addr);
ti_Cnt_1ms = 0;
LCD_DelCnt_1ms = 0;
while (1)
{
if(ti_Cnt_1ms > 66){ //66ms이상일 때 동작 // 충분한 시간이 있어야함
res = getRange(Sonar_Addr, &Sonar_range);
if(res)
{
LCD_Pos(0,0);
LCD_Str("Measured Dist.= ");
LCD_Pos(1,5);
LCD_Str("ERR ");
}
else if(LCD_DelCnt_1ms > 66)
{
LCD_Pos(0,0);
LCD_Str("Measured Dist.)= ");
sprintf(Message, "%01d %03d cm",readCnt,Sonar_range);
LCD_Pos(1,5); //거리는 센티미터 단위로 출력
LCD_Str(Message);
LCD_DelCnt_1ms = 0;
}
startRanging(Sonar_Addr);
ti_Cnt_1ms = 0;
readCnt = (readCnt + 1)%10;
}
}
}
이 모듈 특징은 2개도 사용할 수있다는거고 초음파를 쏘고 받는 부분이 1개로 되어있다는 점이 특징. 하지만 HC-SR04이 초음파 센서가 너무 간결하고 쉬워서 앞으로 잘 쓸지는 모르겠지만 어느정도 원리는 이해했다!!
근데 실제 동작에서 생각보다 잘 구현되지 않았다.. 70cm가 넘으면 잘동작하지 않았는데 현재 진행하고 있는 프로젝트를 하면서 좀 더 연구해봐야겠다.
728x90
'C_Atmega128' 카테고리의 다른 글
03_ MCP23008 (0) | 2021.10.30 |
---|---|
01_TWI (0) | 2021.10.30 |