모터 > 8비트 타이머 인터럽트를 사용한 8개의 RC 서보모터 구동

TODAY698 TOTAL2,230,380
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | 모터 | 서보모터 | 8비트 타이머 인터럽트를 사용한 8개의 RC 서보모터 구동

페이지 정보

작성자 키트 작성일2017-09-05 17:16 조회1,499회 댓글0건

본문

 

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
//--------------------------------------------------------
// CVAVR
//--------------------------------------------------------
#include <mega128.h>
#include <delay.h>
//
unsigned char pwm[181],angle[8]={0,};
unsigned int  cnt=0;
//
interrupt [TIM0_COMP] void timer0_comp_isr(void){
    if     (cnt<=179){ PORTA=pwm[cnt]; TCCR0=0x0A; OCR0= 19; cnt++; } // ~179 : 10us
    else if(cnt==180){ PORTA=0x00;     TCCR0=0x0F; OCR0=136; cnt++; } // 180 : 8768us
    else if(cnt==181){ PORTA=0x00;     TCCR0=0x0F; OCR0=137; cnt++; } // 180 : 8832us
    else if(cnt==182){ PORTA=0xFF;     TCCR0=0x0D; OCR0= 74; cnt=0; } // 181 : 600us
}
//
void save_angle(char ch,char angle){
    char pos[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    char neg[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
    unsigned char i;
    for(i=0;i<=angle;i++){ pwm[i]|=pos[ch]; } // 1을 채우고
    for(   ;i<=180  ;i++){ pwm[i]&=neg[ch]; } // 0을 채움
}
//
void main(void){
    unsigned char i;
    unsigned int  tp;
    DDRA=0xFF;   // 서보모터
    TCCR0=0x0A; OCR0=19; TIMSK=2// 16000000/8/(1+ 19),10us
    ADCSRA=0xE7;
    SREG|=0x80;
    while(1){
        for(i=0;i<8;i++){ // 8개의 가변저항을 읽어서
            ADMUX=0x40|i; delay_ms(2); tp=ADCW;
            angle[i]=(unsigned char)( (float)tp*179.0/1023.); // 0~180도로 변환
        }
        for(i=0;i<8;i++)save_angle(i,angle[i]); // pwm 변환
    }
}
cs


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
//--------------------------------------------------------
// AVRStudio
//--------------------------------------------------------
#define F_CPU 16000000UL // 16 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//
volatile unsigned char pwm[180],angle[8]={0,};
volatile unsigned int  cnt=0;
//
ISR(TIMER0_COMP_vect) {
    if     (cnt<=179){ PORTA=pwm[cnt]; TCCR0=0x0A; OCR0= 19; cnt++; } // ~179 : 10us
    else if(cnt==180){ PORTA=0x00;     TCCR0=0x0F; OCR0=136; cnt++; } // 180 : 8768us
    else if(cnt==181){ PORTA=0x00;     TCCR0=0x0F; OCR0=137; cnt++; } // 180 : 8832us
    else if(cnt==182){ PORTA=0xFF;     TCCR0=0x0D; OCR0= 74; cnt=0; } // 181 : 600us
}
//
void save_angle(char ch,char angle){
    char pos[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    char neg[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
    unsigned char i;
    for(i=0;i<=angle;i++){ pwm[i]|=pos[ch]; } // 1을 채우고
    for(   ;i<=180  ;i++){ pwm[i]&=neg[ch]; } // 0을 채움
}
//
int main(void){
    unsigned char i;
    unsigned int  tp;
    DDRA=0xFF;   // 서보모터
    TCCR0=0x0A; OCR0=19; TIMSK=2// 16000000/8/(1+ 19),10us
    ADCSRA=0xE7;
    SREG|=0x80;
    while(1){
        for(i=0;i<8;i++){ // 8개의 가변저항을 읽어서
            ADMUX=0x40|i; _delay_ms(2); tp=ADCW;
            angle[i]=(unsigned char)( (float)tp*179.0/1023.); // 0~180도로 변환
        }
        for(i=0;i<8;i++)save_angle(i,angle[i]); // pwm 변환
    }
}
cs

앞 글의 예제와 같은 기능인데 8비트 타이머 1개로 만들었습니다.

RC서보모터는 1도당 10us 이고, 전체 주기는 20ms입니다. 
600us(on)---1800us(pwm구간)----17600us(off)
시간으로 표현하면 위처럼 됩니다.

1800us(pwm구간)----17600us(off)---600us(on)
반복되는 신호이므로 순서를 바꾼다고 해서 문제 될 것은 없겠죠

17600us(off) 이 시간은 두개로 나누어서 출력하고 있습니다.
    else if(cnt==180){ PORTA=0x00;     TCCR0=0x0F; OCR0=136; cnt++; } // 180 : 8768us
    else if(cnt==181){ PORTA=0x00;     TCCR0=0x0F; OCR0=137; cnt++; } // 180 : 8832us
8832+8768=17600

돌려보지 않은 예제니 문제가 있으면 덧글로 적어주세요^^

댓글 0

조회수 1,499

등록된 댓글이 없습니다.

모터HOME > 모터 > 서보모터 목록

게시물 검색

2022년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2021년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2020년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2020
모바일버전으로보기