'백설기물만두'님 보세요. ATmega128을 이용한 예제 소스입니다.

공업센터본관 작성일 14.03.12 00:05:19
댓글 5조회 10,756추천 4

139455015010298.jpg


댓글만 남기고 방금 집에 와서 예전 놀았던 소스들 뒤졌네요ㅋㅋㅋ


인터넷에 글 잘 안남기지만 짱공유에서 도움받은 적이 있어서ㅋㅋㅋ


서로 돕고 살아야죠 ㅋ


질문 남기시면 자료 수정하며 올리겠습니다.


오래전에 만들었던 장난감들이라 소스에 대한 자세한 설명은 일일히 기억이 안나네요 ㅠㅠ


주석 처리 되고 마지막 수정이 어찌 된지 기억이 안나고 필요 없는 부분들(친구들 학번 등) 빼고 올리는거라 완벽한 코드는 아닙니다ㅋㅋㅋ


학부 2학년 아무것도 모를 때 짰던 것도 있어서 지금보면 수정해야 할 것도 많을꺼 같네요.


적당히 알아서 보세요 ㅋㅋㅋ


avr studio와 winavr을 이용하였습니다.


//----------------------------- '백설기물만두' 님께서 하시려는 프로젝트(RC카 이용) ----------------------------//
#include <avr/io.h>#include <avr/interrupt.h>#define F_CPU 16000000UL#include <util\delay.h>
#define left 106 //106#define right 76 //76#define center 92 //92 대충 95#define CW 0x50#define CCW 0x90#define STOP 0x00
volatile long servo = 0;volatile int DC = 0;
void init_sys(){ DDRA = 0x01; DDRB = 0xf0; // 4:eneble, 5:DC Motor PWM, 6:Direction A, 7:Direction B DDRE = 0x0a; // 0:UART0 recive, 1:UART0 trans, 3:Servo PWM
TCCR1A = 0x83; TCCR1B = 0x0d;
TCCR3A = 0x83; TCCR3B = 0x0c;
UCSR0B = 0xd8; //UCSR0B = 0x90; UCSR0C = 0x06; UBRR0H = 0; UBRR0L = 25; //38.4k spb
SREG = 0x80;}
int main(){ init_sys();
int i = 0; //servo = center; servo = 95;// servo = 80;
while(1){ PORTA = 0x00;
/* for(i = right; i < left; i ++){ OCR3AH = i>>8; OCR3AL = i; _delay_ms(7); }
for(i = left; i > right; i --){ OCR3AH = i>>8; OCR3AL = i; _delay_ms(7); }*/
// PORTB = (PORTB & 0x0f) | CW; //PORTB = (PORTB & 0x0f) | CCW;
// OCR1AH = DC>>8;// OCR1AL = DC;
// OCR3AH = servo>>8;// OCR3AL = servo;
}// DC = 20;// servo = 100;
// OCR3AH = servo>>8;// OCR3AL = servo;

/* PORTB = (PORTB & 0x0f) | CW; OCR1AH = DC>>8; OCR1AL = DC;
OCR3AH = servo>>8; OCR3AL = servo;
_delay_ms(3000);
DC = 10; servo = 25;
PORTB = (PORTB & 0x0f) | CCW; OCR1AH = DC>>8; OCR1AL = DC;
OCR3AH = servo>>8; OCR3AL = servo;
_delay_ms(1000);
DC = 10; servo = 16;
PORTB = (PORTB & 0x0f) | CW; OCR1AH = DC>>8; OCR1AL = DC;
OCR3AH = servo>>8; OCR3AL = servo;
_delay_ms(5000);
return 0;*/}
ISR(SIG_UART0_RECV){ if(UDR0 == 'a'){ PORTA = 0x01; _delay_us(500); servo -= 1; if(servo < left) servo = left; } if(UDR0 == 'd'){ PORTA = 0x01; _delay_us(500); servo += 1; if(servo > right) servo = right; } if(UDR0 == 'w'){ PORTA = 0x01; _delay_us(500);
DC += 5;
if(DC > 100) DC = 100; } if(UDR0 == 's'){ PORTA = 0x01; _delay_us(500);
DC -= 5;
if(DC < 0) DC = 0; }
if(UDR0 == 'q'){ PORTA = 0x01; _delay_us(500);
PORTB = (PORTB & 0x0f) | STOP; DC = 0; }}


//----------------------------- 간단한 라인트레이서 예제 (RC카 이용) -----------------------------//


#include <avr/io.h>

#define F_CPU 14740600UL

#include <util\delay.h>

#include <stdio.h>


#define LINE1 0x80 //첫번째 라인 DDRAM address

#define LINE2 0xC0 //두번째 라인 DDRAM address


//PORTC0 = Enable, PORTC1 = R/W, PORTC1 = Register select, PORTA = Date

#define CMD_WRITE 0x01 //E=1, RW=0, RS=0

#define CMD_READ 0x03 //E=1, RW=1, RS=0

#define DATA_WRITE 0x05 //E=1, RW=0, RS=1

#define DATA_READ 0x07 //E=1, RW=1, RS=1

#define LCD_EN 0x01 //enable 신호

#define ADMUX_value 0xC0 //ADCMUX Register 변수

#define center 300 //center 95,right = 80, left = 110


volatile int ADC_high[8]={0,0,0,0,0,0,0,0};

volatile int ADC_low[8]={1024,1024,1024,1024,1024,1024,1024,1024};

void init_port(void)

{

DDRC = 0xFF;

DDRA = 0xFF;

DDRE = 0xFF;

DDRF = 0x00;

DDRG = 0x00;

}


void init_PWM(){

TCCR3A = 0xAB; // encoder input

TCCR3B = 0x0C;

OCR3A = 95; //servo

OCR3B = 1022-100; //cw

OCR3C = 1022; //ccw

}


////////////////////     ADC     ////////////////////


int run_ADC(int channel){

int value[8];


ADMUX =  ADMUX_value + channel;

_delay_us(200);

ADCSRA = 0xAD;

ADCSRA |= 0x40;

while((ADCSRA&0x10)!=0x10)

value[channel] = (int)ADCL + ((int)ADCH<<8);


return value[channel];

}


void init_ADC_value(){

int i,value[8];

for(i=0;i<8;i++){

value[i]= run_ADC(i);

if(ADC_high[i] <= value[i])

ADC_high[i] = value[i];

if(ADC_low[i] >= value[i])

ADC_low[i] = value[i];

}

}


int main()

{

init_port();

init_LCD();

init_PWM();


unsigned int channel,min_channel[3]={3,3,3},aver,total_value,final_value=95;

long ADC_value[8];


while(1){

if(PING&0x02){

init_ADC_value();

}


else{

for(channel=0;channel<8;channel++){

for(aver=0;aver<5;aver++){

ADC_value[channel] = ADC_value[channel] + run_ADC(channel);

}

ADC_value[channel] = ADC_value[channel]/(aver);

ADC_value[channel] = ((ADC_value[channel] - ADC_low[channel]) * 100 )/ (ADC_high[channel]-ADC_low[channel]);

if(ADC_value[channel]<35){

min_channel[0] = channel;

min_channel[1] = min_channel[0];

min_channel[2] = min_channel[1];

}

if(ADC_value[channel]<3)

ADC_value[channel]=0;

if(ADC_value[channel]>97)

ADC_value[channel]=100;

}

}


switch(min_channel[0]){

case 0:{

final_value = center + 15 + (ADC_value[0]-ADC_value[1])/11.42;

break;

}


case 1:{

if(ADC_value[0]>ADC_value[2])

final_value = center + 10 + (ADC_value[2]-ADC_value[1])/40;


if(ADC_value[0]<ADC_value[2])

final_value = center + 10 + (ADC_value[1]-ADC_value[0])/11.42;

break;

}

case 2:{

if(ADC_value[1]>ADC_value[3])

final_value = center + 7.5 + (ADC_value[3]-ADC_value[2])/40;


if(ADC_value[1]<ADC_value[3])

final_value = center + 7.5 + (ADC_value[2]-ADC_value[1])/26.67;

break;

}

case 3:{

if(ADC_value[2]>ADC_value[4])

final_value = center + 3.75 + (ADC_value[4]-ADC_value[3])/13.33;


if(ADC_value[2]<ADC_value[4])

final_value = center + 3.75 + (ADC_value[3]-ADC_value[2])/26.67;

break;

}

case 4:{

if(ADC_value[3]>ADC_value[5])

final_value = center - 3.75 + (ADC_value[5]-ADC_value[4])/13.33;


if(ADC_value[3]<ADC_value[5])

final_value = center - 3.75 + (ADC_value[4]-ADC_value[3])/26.67;

break;

}

case 5:{

if(ADC_value[4]>ADC_value[6])

final_value = center - 7.5 + (ADC_value[6]-ADC_value[5])/40;


if(ADC_value[4]<ADC_value[6])

final_value = center - 7.5 + (ADC_value[5]-ADC_value[4])/26.67;

break;

}

case 6:{

if(ADC_value[5]>ADC_value[7])

final_value = center - 10 + (ADC_value[7]-ADC_value[6])/11.42;


if(ADC_value[5]<ADC_value[7])

final_value = center - 10 + (ADC_value[6]+ADC_value[5])/49;

break;

}

case 7:{

final_value = center - 15 + (ADC_value[7]-ADC_value[6])/11.42;

break;

}

}


total_value = ADC_value[0] + ADC_value[1] + ADC_value[2] + ADC_value[3] + ADC_value[4] + ADC_value[5] + ADC_value[6] + ADC_value[7];

if(final_value<285)

final_value = 285;

if(final_value>315)

final_value = 315;


if(total_value>600){

if((min_channel[0]==0)|(min_channel[1]==0)|(min_channel[2]==0))

final_value = 315;


else if((min_channel[0]==7)|(min_channel[1]==7)|(min_channel[2]==7))

final_value = 285;

}


OCR3A = final_value;

}

}


//----------------------------- 간단한 모터 속도 제어 (PID 제어) -----------------------------//
#include "간단한 모터 속도 제어.h"#include "LCD.h"#include "variable.c"
void run_ADC();
int main(){ init_DDR(); init_Timer(); init_ADC(); init_LCD();
while(1){// m_desire_spd = pressure/10; //아직 값 몰라 run_ADC(); OCR2 = 0; OCR0 = pressure/4; } return 0;}
run_ADC(){ ADCSRA |= 0x40; while((ADCSRA&0x10)!=0x10) pressure = (int)ADCL + ((int)ADCH<<8);}

#include <avr/io.h>#define F_CPU 16000000UL#include <util/delay.h> //delay.h 함수는 F_CPU는 (Clock 설정 뒤로 가야함)#include <avr/interrupt.h>

#include "간단한 모터 속도 제어.h"
void init_DDR(){ DDRA = 0xff; // LCD Instruction DDRB = 0x90; // PB4 = CW, PB7 = CCW DDRC = 0xff; // LCD Data
// PD6 = Timer 1 Extern Clock, PF0 = ADC0 input, Timer0 = Calculation Frequency SREG = 0x80; // Global Interrupt Enable}
void init_Timer(){ TCCR0 = 0x7f; // CW = Fast PWM, Campare match Set, 1024 Prescale TCCR1B = 0x06; // Encorder Counter = Extern Clock (Falling Edge) TCCR2 = 0x7d; // CCW = Fast PWM, Campare match Set, 1024 Prescale TIMSK = 0x21; // Timer0 Overflow interrupt Enable, Timer1 Overflow interrupt Enable}
void init_ADC(){// ADCSRA = 0xef; // ADC Enable, Start Bit Set, Free Running Mode, Interrrupt Enable, 128 Prescale ADCSRA = 0xe7;}

#include "간단한 모터 속도 제어.h"#include "variable.c"#include "PID_gain.h"#include "LCD.h"
ISR(TIMER0_OVF_vect){ e_counter = (TCNT1H<<8) + TCNT1L; TCNT1H = 0; TCNT1L = 0;
m_err_now = e_counter - (e_counter/10); //엔코더 변수도 몰라 m_sum_err += m_err_now; // OCR0 = PID_kp*(m_err_now) + PID_ki*(m_sum_err) + PID_kd*(m_err_now - m_err_past); m_err_past = m_err_now;}
ISR(TIMER1_OVF_vect){ e_counter = (1<<16); //long 타입 몇까지 저장하는지 확인 안 해봤어~ㅋㅋㅋ}/*ISR(ADC_vect){ pressure = (ADCH<<8) + ADCL; LCD_wr_str(LINE1, pressure);}*/
아래 define 3개는 'PID_gain.h' 입니다.#define PID_kp 1#define PID_ki 0#define PID_kd 0
#include "간단한 모터 속도 제어.h"
int m_err_past;int m_err_now;int m_sum_err;int m_desire_spd;int pressure;long e_counter;

//----------------------------- 초음파 센서로 거리를 받아 스태핑 모터 구동로 위치 제어 (PID 제어) -----------------------------//
#include <avr/io.h>#define F_CPU 16000000UL#include <util/delay.h>#include <avr/interrupt.h>#include <stdio.h>#include <string.h>
#define LINE1 0x80 //첫번째 라인 DDRAM address#define LINE2 0xC0 //두번째 라인 DDRAM address//PORTB0 = Register select, PORTB1 = R/W, PORTB2 = Enable, PORTC = Date#define CMD_WRITE 0x04 // E=1, RW=0, RS=0#define CMD_READ 0x06 // E=1, RW=1, RS=0#define DATA_WRITE 0x05 // E=1, RW=0, RS=1#define DATA_READ 0x07 // E=1, RW=1, RS=1#define LCD_EN 0x04 // E=1, RW=0, RS=0
int l_dis, r_dis;int l_m[] = {0x80, 0x40, 0x20, 0x10};int r_m[] = {0x01, 0x02, 0x04, 0x08};int l_cnt = 0, r_cnt = 0; int l_result, r_result;int l_error, l_error_i, l_error_d, pre_l_error;int r_error, r_error_i, r_error_d, pre_r_error;
float kp = 1, ki ,kd = 0.035;
char *str;
void init_PORT(){ DDRA = 0xff; // Motor CW, CCW DDRB = 0x07; // LCD Cmd DDRC = 0xff; // LCD Data DDRF = 0x00; // 0:l_dis, 1:r_dis DDRG = 0x03;
SREG = 0x80; // Global Interrupt Enable}
void init_ADC(){ ADCSRA = 0xa5;}
void init_timer(){ TCCR0 = 0x07; TIMSK = 0x01;}
int conv_ADC(int channel){ int value[6]; ADMUX = channel; _delay_us(200); ADCSRA |= 0x40; while((ADCSRA&0x10) == 0) value[channel] = (int)ADCL + (long)(ADCH<<8);
return value[channel];}
void LCD_cmd_write(char cmd){ PORTB = CMD_WRITE; PORTC = cmd; PORTB = PORTB^LCD_EN; _delay_ms(2);}
void LCD_data_write(char data){ PORTB = DATA_WRITE; PORTC = data; PORTB = PORTB^LCD_EN; _delay_ms(2);}
void init_LCD(void){ _delay_ms(15); LCD_cmd_write(0x38); _delay_ms(5); LCD_cmd_write(0x38); _delay_us(100); LCD_cmd_write(0x38); LCD_cmd_write(0x08); LCD_cmd_write(0x01); LCD_cmd_write(0x06); LCD_cmd_write(0x0C);}
void LCD_wr_str(char d_line, char *lcd_str){ LCD_cmd_write(d_line); while(*lcd_str != '\0') { LCD_data_write(*lcd_str); lcd_str++; }}
int main(){
init_PORT(); init_ADC(); init_timer(); init_LCD();
while(1){ l_dis = conv_ADC(0); r_dis = conv_ADC(1); if(l_error<0) PORTG = 0x01; if(r_error<0) PORTG = PORTG | 0x02;
sprintf(&str, "%d %d      ", l_error, r_error); LCD_wr_str(LINE1, &str); sprintf(&str, "%d %d      ", l_result, r_result); LCD_wr_str(LINE2, &str);
PORTG = 0x00; }}
ISR(TIMER0_OVF_vect){ r_error = 250 - r_dis; l_error = 250 - l_dis;
l_error_i += l_error; r_error_i += r_error;
l_error_d = l_error - pre_l_error; r_error_d = r_error - pre_r_error;
l_result = kp * l_error + ki * l_error_i + kd * l_error_d; r_result = kp * r_error + ki * r_error_i + kd * r_error_d;
if(l_error < 50 && l_error > -50) l_result = 0;
else{ if(l_result > 0){ PORTA = l_m[l_cnt];
l_result = 7000 - l_result; if(l_result < 2000) l_result = 2000;
_delay_us(l_result); l_cnt++;
if(l_cnt > 3) l_cnt = 0; } else{ PORTA = l_m[l_cnt];
l_result = 7000 + l_result; if(l_result < 2000) l_result = 2000;
_delay_us(l_result); l_cnt--;
if(l_cnt < 0) l_cnt = 3; } }
if(r_error < 50 && r_error > -50) r_result = 0;
else{ if(r_result > 0){ PORTA = r_m[r_cnt];
r_result = 7000 - r_result; if(r_result < 2000) r_result = 2000;
_delay_us(r_result); r_cnt++;
if(r_cnt > 3) r_cnt = 0; } else{ PORTA = r_m[r_cnt];
r_result = 7000 + r_result; if(r_result < 2000) r_result = 2000;
_delay_us(r_result); r_cnt--;
if(r_cnt < 0) r_cnt = 3; } } pre_l_error = l_error_d; pre_r_error = r_error_d;}

//----------------------------- 캐릭터 LCD (MCU를 사용하시면 변수 확인이 안됩니다. 확인 원할시 사용) -----------------------------//
#include <avr/io.h>#define F_CPU 16000000UL#include <util\delay.h>#include <string.h>
#define LINE1 0x80 //첫번째 라인 DDRAM address#define LINE2 0xC0 //두번째 라인 DDRAM address
//PORTB0 = Register select, PORTB1 = R/W, PORTB2 = Enable, PORTC = Date#define CMD_WRITE 0x04 //E=1, RW=0, RS=0#define CMD_READ 0x06 //E=1, RW=1, RS=0#define DATA_WRITE 0x05 //E=1, RW=0, RS=1#define DATA_READ 0x07 //E=1, RW=1, RS=1#define LCD_EN 0x04 //E=1, RW=0, RS=0
////////////////////     LCD     ////////////////////
void LCD_cmd_write(char cmd){ PORTB = CMD_WRITE; PORTC = cmd; PORTB = PORTB^LCD_EN; _delay_ms(2);}
void LCD_data_write(char data){ PORTB = DATA_WRITE; PORTC = data; PORTB = PORTB^LCD_EN; _delay_ms(2);}
void init_LCD(void){ _delay_ms(15); LCD_cmd_write(0x38); _delay_ms(5); LCD_cmd_write(0x38); _delay_us(100); LCD_cmd_write(0x38); LCD_cmd_write(0x08); LCD_cmd_write(0x01); LCD_cmd_write(0x06); LCD_cmd_write(0x0C);}
void LCD_wr_str(char d_line, char *lcd_str){ LCD_cmd_write(d_line); while(*lcd_str != '\0') { LCD_data_write(*lcd_str); lcd_str++; }}
void init_port(void){ DDRB = 0x07; DDRC = 0xFF;}
int main(){ init_port(); init_LCD();
char *str;
while(1){ sprintf(&str, "%d %d         ", 'a', 1); LCD_wr_str(LINE1, &str); }}

//----------------------------- 장난감 만들 때 사용 했던 간단한 digital filter -----------------------------//
#include "two_wheel_balancing.h"
// 필터링할 항목마다 value[8]에 관한 변수 선언 할것float mov_aver_filter(float pre_aver,int value[8], int input){ int cnt; float aver;
value[0] = input; for(cnt = 1; cnt < 7; cnt ++) value[cnt+1] = value[cnt];
aver = pre_aver + ((input - value[7]) >> 3);
return aver;}
// alpha = 가중치 (항상 1 이하, 클수록 현재값 치중)int low_pass_filter(int pre_aver, int input, float alpha){ int aver;
aver = alpha * pre_aver + (1- alpha) * input;
return aver;}
int high_pass_filter(int pre_aver, int pre_input, int input, float alpha){ int aver;
aver = alpha * pre_aver + alpha * (input - pre_input);
return aver;}

제가 그림 그리는 재주가 없어서 ㅋㅋㅋ 대충 보시면 이해하실꺼에요ㅋㅋㅋ
DC 모터로 구동, 서보 모터로 조향 예 입니다.

컴퓨터 → (UART) → 무선 통신 모듈(지그비or 블루투스)                                                |                                                | (무선 통신)                                                                             무선 통신 모듈(지그비or 블루투스)  (UART)  MCU  (PWM)   조향 모터                                                                                                                                                                                                   (PWM)                                                                                                                                                                                                 구동 모터
이런 느낌이 될꺼에요.
이 정도 자료면 충분히 성공 하실 수 있을꺼에요.
공대 화이팅입니다 ㅋ    
공업센터본관의 최근 게시물

자유·수다 인기 게시글