답변 : 사진과 구동 영상으로 다시 질문하겠습니다!
페이지 정보
작성자 master 작성일19-12-27 22:00 조회6,745회 댓글2건본문
밑줄 친 부분은 제가 LCD 안정화 코드를 따온 것입니다. 신경 안쓰셔도 됩니다. 적
어둔 코드는 화재 감지기를 한 번 구현해본 것인데 가변 저항을 돌려 4.0V 이상 일 때 화재로 판단하여 LED 점등(PA7 단자) 및 스피커 알람, LCD에 fire 점등이며 평상시에는 전압만 출력합니다. 구동이 잘됩니다.
#include
#include
#define LINE2 0xC0 // 2nd Line Move
#define HOME 0x02 // Cursor Home
#define RSHIFT 0x1C // Display Right Shift
#define LSHIFT 0x18 // Display Left Shift
#define DISPON 0x0c // Display On
#define DISPOFF 0x08 // Display Off
void LCD_init(void);
void LCD_String(char flash *str);
void Busy(void);
void Command(unsigned char);
void Data(unsigned char);
void adc_display(void);
int adc_value = 0;
float Vref = 5.0, Vwarn = 4.0, Vdetect = 0;
int cnt_bell = 0;
void main(void)
{
ADMUX = 0x00;
ADCSRA = 0x87;
ETIMSK = 0x04;
TCCR3A = 0x00;
TCCR3B = 0x04;
TCNT3H = 0x85;
TCNT3L = 0xED;
DDRB = 0x30;
DDRA = 0x80;
PORTA = 0xff;
SREG = 0x80;
LCD_init();
adc_display();
while(1){
ADCSRA = 0xc7;
while((ADCSRA & 0x10) == 0);
adc_value0 = (int)ADCL + ((int)ADCH << 8);
Vdetect = (float)adc_value * Vref / 1024;
}
}
interrupt [TIM3_OVF] void timer_tin0 (void)
{
TCNT3H = 0x85;
TCNT3L = 0xED;
if(Vdetect >= Vwarn){
TCCR1A = 0x40;
TCCR1B = 0x0a;
if(cnt_bell == 0){
PORTA = 0x00;
OCR1A = 2082;
Command(CLEAR);
LCD_String("fire!!!");
cnt_bell = 1;
}
else{
PORTA = 0xff;
OCR1A = 2777;
Command(CLEAR);
cnt_bell = 0;
}
}
else{
TCCR1A = 0x00;
TCCR1B = 0x0a;
PORTA = 0xff;
adc_display();
}
}
void adc_display(void)
{
int temp0 = 0, temp1 = 0, temp = 0;
Command(CLEAR);
LCD_String("Value:");
temp = (int)(Vdetect * 10 + 0.5);
temp1 = temp / 10;
temp0 = temp % 10;
Data(0x30 + temp1);
LCD_String(".");
Data(0x30 + temp0);
LCD_String("V");
}
// LCD 초기화 함수
void LCD_init(void)
{
DDRC = 0xFF; // 포트 C 출력 설정
PORTC &= 0xFB; //E = 0;
// 충분한 지연시간을 통한 안정화 과정
delay_ms(15);
Command(0x20); // D5=1
delay_ms(5);
Command(0x20); // D5=1
delay_us(100);
Command(0x20); // D5=1
// 초기화 과정
Command(0x28); // function set
Command(0x06); // entry mode set
Command(0x01); // all clear
Command(0x0c); // display on
}
// 인스트럭션 쓰기 함수
void Command(unsigned char byte)
{
Busy();
// 인스트럭션 상위 바이트
PORTC = (byte & 0xF0); // 데이터
PORTC &= 0xFE; // RS = 0;
PORTC &= 0xFD; // RW = 0;
delay_us(1);
PORTC |= 0x04; // E = 1;
delay_us(1);
PORTC &= 0xFB; // E = 0;
// 인스트럭션 하위 바이트
PORTC = ((byte<<4) & 0xF0); // 데이터
PORTC &= 0xFE; // RS = 0;
PORTC &= 0xFD; // RW = 0;
delay_us(1);
PORTC |= 0x04; // E = 1;
delay_us(1);
PORTC &= 0xFB; // E = 0;
}
// 문자열 출력 함수
void LCD_String(char flash *str)
{
char flash *pStr=0;
pStr = str;
while(*pStr) Data(*pStr++);
}
// char flash : pointer declaration for program memory
// char eeprom : pointer declaration for EEPROM
//데이터 쓰기 함수
void Data(unsigned char byte)
{
Busy();
// 데이터 상위 바이트
PORTC = (byte & 0xF0); // 데이터
PORTC |= 0x01; //RS = 1;
PORTC &= 0xFD; //W = 0;
delay_us(1);
PORTC |= 0x04; //E = 1;
delay_us(1);
PORTC &= 0xFB; //E = 0;
// 데이터 하위 바이트
PORTC = ((byte<<4) & 0xF0); // 데이터
PORTC |= 0x01; //RS = 1;
PORTC &= 0xFD; //RW = 0;
delay_us(1);
PORTC |= 0x04; //E = 1;
delay_us(1);
PORTC &= 0xFB; //E = 0;
}
// Busy Flag Check -> 일반적인 BF를 체크하는 것이 아니라
// 일정한 시간 지연을 이용한다.
void Busy(void)
{
delay_ms(2);
}
위 코드와
#include
#include
#define LINE2 0xC0 // 2nd Line Move
#define HOME 0x02 // Cursor Home
#define RSHIFT 0x1C // Display Right Shift
#define LSHIFT 0x18 // Display Left Shift
#define DISPON 0x0c // Display On
#define DISPOFF 0x08 // Display Off
void LCD_init(void);
void LCD_String(char flash *str);
void Busy(void);
void Command(unsigned char);
void Data(unsigned char);
void degree_display(void);
void v_value(void);
int rot_base=375, rot_min=275, rot_max=475;
int rot_delta1=1, rot_delta2=4, rot_delta=0;
int rot_value=0, rot_dir=2;
int adc_value=0;
float Vref=5.0, f_val=0;
int temp10=0;
void main(void)
{
DDRB=0xff;
DDRF=0xff;
ADMUX=0x00;
ADCSRA=0b10000111;
ETIMSK=0b00000100;
TCCR3A=0x00;
TCCR3B=0b00000100;
TCNT3H=0xE7;
TCNT3L=0x96;
TCCR1A=0b10000010;
TCCR1B=0b00011011;
ICR1H=0x09;
ICR1L=0xc3;
SREG=0b10000000;
rot_value=rot_base;
OCR1A=rot_value;
LCD_init();
degree_display();
while(1)
{
v_value();
if(temp10>0&&temp10<=15)
{
rot_dir=1;
rot_delta=rot_delta2;
}
else if(temp10>15&&temp10<=20)
{
rot_dir=1;
rot_delta=rot_delta1;
}
else if(temp10>30&&temp10<=35)
{
rot_dir=0;
rot_delta=rot_delta1;
}
else if(temp10>35&&temp10<=50)
{
rot_dir=0;
rot_delta=rot_delta2;
}
else
{
rot_dir=2;
OCR1A=rot_value;
}
}
}
interrupt [TIM3_OVF] void timer_int3(void)
{
TCNT3H=0xE7;
TCNT3L=0x96;
if(rot_dir==0)
{
if(rot_value<=rot_max)
{
rot_value+=rot_delta;
}
else
{
rot_value=rot_max;
}
OCR1A=rot_value;
}
else if(rot_dir==1)
{
if(rot_value>=rot_min)
{
rot_value-=rot_delta;
}
else
{
rot_value=rot_min;
}
OCR1A=rot_value;
}
degree_display();
}
void v_value(void)
{
ADCSRA=0b11000111;
while((ADCSRA&0x10)==0);
adc_value=(int)ADCL+((int)ADCH<<8);
f_val=(float)adc_value*Vref/1024;
temp10=(int)(f_val*10+0.5);
}
void degree_display(void)
{
float degree_value=0;
int temp0=0, temp1=0, temp2=0, temp=0;
int v1=0, v2=0;
Command(HOME);
LCD_String("Degree : ");
if(rot_value>=rot_base)
{
degree_value=(float)(rot_value-rot_base)*80/200;
LCD_String("+");
}
else
{
degree_value=(float)(rot_base-rot_value)*80/200;
LCD_String("-");
}
temp=(int)(degree_value*10);
temp2=temp/100;
temp=temp%100;
temp1=temp/10;
temp0=temp%10;
Data(0x30+temp2);
Data(0x30+temp1);
LCD_String(".");
Data(0x30+temp0);
Command(LINE2);
LCD_String("Value : ");
v1=temp10/10;
v2=temp10%10;
Data(0x30+v1);
LCD_String(".");
Data(0x30+v2);
LCD_String("V");
}
// LCD 초기화 함수
void LCD_init(void)
{
DDRC = 0xFF; // 포트 C 출력 설정
PORTC &= 0xFB; //E = 0;
// 충분한 지연시간을 통한 안정화 과정
delay_ms(15);
Command(0x20); // D5=1
delay_ms(5);
Command(0x20); // D5=1
delay_us(100);
Command(0x20); // D5=1
// 초기화 과정
Command(0x28); // function set
Command(0x06); // entry mode set
Command(0x01); // all clear
Command(0x0c); // display on
}
// 인스트럭션 쓰기 함수
void Command(unsigned char byte)
{
Busy();
// 인스트럭션 상위 바이트
PORTC = (byte & 0xF0); // 데이터
PORTC &= 0xFE; // RS = 0;
PORTC &= 0xFD; // RW = 0;
delay_us(1);
PORTC |= 0x04; // E = 1;
delay_us(1);
PORTC &= 0xFB; // E = 0;
// 인스트럭션 하위 바이트
PORTC = ((byte<<4) & 0xF0); // 데이터
PORTC &= 0xFE; // RS = 0;
PORTC &= 0xFD; // RW = 0;
delay_us(1);
PORTC |= 0x04; // E = 1;
delay_us(1);
PORTC &= 0xFB; // E = 0;
}
// 문자열 출력 함수
void LCD_String(char flash *str)
{
char flash *pStr=0;
pStr = str;
while(*pStr) Data(*pStr++);
}
// char flash : pointer declaration for program memory
// char eeprom : pointer declaration for EEPROM
//데이터 쓰기 함수
void Data(unsigned char byte)
{
Busy();
// 데이터 상위 바이트
PORTC = (byte & 0xF0); // 데이터
PORTC |= 0x01; //RS = 1;
PORTC &= 0xFD; //W = 0;
delay_us(1);
PORTC |= 0x04; //E = 1;
delay_us(1);
PORTC &= 0xFB; //E = 0;
// 데이터 하위 바이트
PORTC = ((byte<<4) & 0xF0); // 데이터
PORTC |= 0x01; //RS = 1;
PORTC &= 0xFD; //RW = 0;
delay_us(1);
PORTC |= 0x04; //E = 1;
delay_us(1);
PORTC &= 0xFB; //E = 0;
}
// Busy Flag Check -> 일반적인 BF를 체크하는 것이 아니라
// 일정한 시간 지연을 이용한다.
void Busy(void)
{
delay_ms(2);
}
위 코드는
RC 서보 모터를 시작할 때 0도로 설정하고
가변저항의 값을
3V - 3.5V 구간으로 조정하면, CW 방향으로 100msec 단위로 0.4도씩 증가
3.5V - 5V 구간으로 조정하면, CW 방향으로 100msec 단위로 1.6도씩 증가
2V -1.5V 구간으로 조정하면, CCW 방향으로 100msec 단위로 0.4도씩 증가
1.5V - 0V 구간으로 조정하면, CCW 방향으로 100msec 단위로 1.6도씩 증가
2-3V 구간으로 조정하면, 모터 현재 각도를 유지하고 현재 각도를 LCD에 출력하게 끔 코딩했습니다. 잘 돌아갑니다.
제가 하고 싶은것은 위 코드 2개를 이용하여 0 - 1.5V까지는 서보모터가 약하게 돌며
1.5V - 3V까지는 중간으로 돌며
3V - 4V가 되면 빠르게 돌면서
4V에 도달 시 화재로 판단하여 LED 점등(PA7 단자) 및 스피커 알람, LCD에 fire 점등을 하고 싶습니다.
제가 궁금한 것은 이것입니다.
1. 가변저항 하나는 전압을 변화시키는 것이고 하나는 민감도를 조절하기 위해 만들었는데 잘 되질 않습니다.
2. 제가 구현하고 싶은 것은 단지 화재 경보기가 아니라 화재 발생 강도에 따라 바람(모터)의 세기도 바뀌게 만들고 싶어서 일단 따로 따로 구현은 해놨는데 저걸 이제
0 - 1.5V까지는 서보모터가 약하게 돌며
1.5V - 3V까지는 중간으로 돌며
3V - 4V가 되면 빠르게 돌면서
4V에 도달 시 화재로 판단하여 LED 점등(PA7 단자) 및 스피커 알람, LCD에 fire 점등을 코딩하는 것에서 어려움을 겪고 있습니다. 취합을 하려면 어떻게 해야할 지 도움을 얻고 싶습니다.
//
<답변내용>------------------------------------------------------
DDRF=0xff;
//
LCD 코드는 문제없다고 하니 생략했습니다.
LCD 코드를 위로 올리고
인터럽트 함수를 아래에
메인을 제일 아래에 작성하면
함수 프로토타입을 생략가능한 것이 늘어납니다.
소스코드가 간단해지죠
LCD 출력을 sprintf를 사용해서 작성 했습니다.
댓글 : 2
조회수 : 6,745
Busan님의 댓글
Busan 작성일
master님 답변 정말 감사드립니다. 그런데 제가 main 문을 2개를 써본 적이 없어서 잘 모르겠는데 저 코드를 그대로 쓰면
0 - 1.5V까지는 서보모터가 약하게 돌며
1.5V - 3V까지는 중간으로 돌며
3V - 4V가 되면 빠르게 돌면서
4V에 도달 시 화재로 판단하여 LED 점등(PA7 단자) 및 스피커 알람, LCD에 fire 점등이 되는 것인가요??
main문과 선언이 중복되요 오류가 발생하진 않나요??
두 코드를 취합해서 쓰고 싶은데 main문이 중복이되서요 ㅠㅠ
두 코드를 하나처럼 쓰고 싶은데 어떻게 구성해야할 지 몰라서 댓글 남깁니다.
master님의 댓글
master
소스코드를 합치지 않은 상태입니다.
심각한 오류를 체크 해드렸으니
각각 동작시켜서 제대로 동작하는지 확인하고
합쳐서 만들어보세요