회원가입 ID/PW 찾기
AA

서보모터 2개를 이용해서 팬틸트를 만드려고 합니다.
일단은 시리얼 통신으로 팬틸트를 제어해보고자 해서 예제를 참고해서 짠 소스입니다.

원래 타이머 하나로 서보모터 2개를 동시에 제어하는거 까지는 성공했으나..
2개를 각각 따로 제어하는게 잘 안되서 여기저기 찾아도 보고 생각해봐서 짠 소스입니다만,

TIMSK  = 0x03;
으로 했을 시엔 TIMER0만 동작하고
TIMSK = 0x04;
로 설정했을시엔 TIMER1만 동작합니다.

아직 소스 이해가 부족해서 TIMSK 부분 값을 어떻게 설정해야 될지 몰라서 질문글 올립니다..


//ICC-AVR application builder : 2007-04-20 오후 2:39:41
// Target : M128
// Crystal: 16.000Mhz

#include <iom128v.h>
#include <macros.h>
#include <stdio.h>

#define SERVOMIN 0
#define SERVOMAX 200
//#define SERVOMAX 100
#define SERVOPORT PORTF
#define SERVODDR DDRF

#define MOVMAX 23
#define MOVMIN 20

#define VALUEMIN 6
#define VALUEMAX 24

#define ARRAYMAX 16

volatile unsigned int servoTime1 = 0;
volatile unsigned int servoTime2 = 0;
volatile int defValue1;
volatile int defValue2;
int i;


// printf 함수 사용시 추가할 것.
int putchar(char c)
{
    while (((UCSR0A>>UDRE0)&0x01) == 0) ;  // UDRE, data register empty
       
    UDR0 = c;
    return c;
}

// scanf 함수 사용시 추가할 것.
int getchar(void)
{
    while ((UCSR0A & 0x80) == 0);
    return UDR0;
}


void port_init(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0x00;
 DDRB  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRC  = 0x00;
 PORTD = 0x00;
 DDRD  = 0x00;
 PORTE = 0x00;
 DDRE  = 0x00;
 PORTF = 0x00;
 DDRF  = 0xFF;
 PORTG = 0x00;
 DDRG  = 0x00;
}

//TIMER0 initialize - prescale:64
// WGM: Normal
// desired value: 20uSec
// actual value: 20.000uSec (0.0%)
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT0 = 0xFB; //set count
 OCR0  = 0x05;
 TCCR0 = 0x04; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
 unsigned char n = 0;
 
 TCNT0 = 0xFB; //reload counter low value

 if(servoTime2 >= SERVOMAX){
 servoTime2 = SERVOMIN;
 }
 servoTime2++;

 if(defValue2 > servoTime2)
 SERVOPORT = 0x01;
 else
  SERVOPORT = 0x00;
}


//TIMER1 initialize - prescale:64
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 20uSec
// actual value: 20.000uSec (0.0%)
void timer1_init(void)
{
 TCCR1B = 0x00; //stop
 TCNT1H = 0xFF; //setup
 TCNT1L = 0xFB;
 OCR1AH = 0x00;
 OCR1AL = 0x05;
 OCR1BH = 0x00;
 OCR1BL = 0x05;
 OCR1CH = 0x00;
 OCR1CL = 0x05;
 ICR1H  = 0x00;
 ICR1L  = 0x05;
 TCCR1A = 0x00;
 TCCR1B = 0x03; //start Timer
}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
 unsigned char n = 0;
 
 TCNT1H = 0xFF; //reload counter high value
 TCNT1L = 0xFB; //reload counter low value

 if(servoTime1 >= SERVOMAX){
 servoTime1 = SERVOMIN;
 }
 servoTime1++;
 
 if(defValue1 > servoTime1)
 SERVOPORT = 0x03;
 else
  SERVOPORT = 0x01;
}

//UART0 initialize
// desired baud rate: 115200
// actual: baud rate:111111 (3.7%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x06;
 UBRR0L = 0x08; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0x18;
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 XDIV  = 0x00; //xtal divider
 XMCRA = 0x00; //external memory
 port_init();
 uart0_init();
 timer0_init();
 timer1_init();
 SERVODDR = 0xFF;

 MCUCR = 0x00;
 EICRA = 0x00; //extended ext ints
 EICRB = 0x00; //extended ext ints
 EIMSK = 0x00;
 TIMSK = 0x04; //timer interrupt sources
 ETIMSK = 0x00; //extended timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}

void delay(int cnt){
 int i, j;
 
 for(i=0; i < cnt; i++){
  for(j=0; j < 1000; j++){
   ;
  }
 }
}


void main(){
 int i=24;
 unsigned char ch;
 init_devices();
 printf("Testing Servo\r\n");
 
 defValue1 = 74;
 defValue2 = 74;
 while(1){
   scanf("%c", &ch);
   printf("Value:%d",defValue1);
    printf("Value:%d",defValue2);
   if((ch == 'a') || (ch == 'A')){
   defValue1++;
   }
  
   if((ch == 'q') || (ch == 'Q')){
   defValue1--;
   }
  
   if((ch == 's') || (ch == 'S')){
   defValue2++;
   }
  
   if((ch == 'w') || (ch == 'W')){
   defValue2--;
   }    
  
  if(defValue1 <=32) defValue1 = 32;
   if(defValue1 >=114) defValue1 = 114;
  if(defValue2 <=32) defValue2 = 32;
   if(defValue2 >=114) defValue2 = 114;
  }



서보 모터 두개를 각각 따로 제어해야 하는데 똑같이 움직일 수는 있어도
따로 움직이는게 어렵네요 타이머 하나로 쓰려니까 계속 떨리는 현상이 생겨서 이렇게 짜봤는데..
타이머 두개가 동시에 구동이 안되서 어떻게 해야 될지 모르겠습니다.
포트 2개를 쓰지 않아도 타이머를 여러개 쓰면 각각 따로 제어가 가능할 것 같은데..
시작한지 얼마 안되서 잘 모르겠네요..


요점은
서보모터 2개를 각각 따로 제어하기 위해서
위 소스에서 고쳐야 할 부분.. 알려주시면 감사하겠습니다..

댓글 9
  • No Profile
    ATMEGA128 은 Timer 0과 Timer 1은 동시에 구동이 안되는 걸로 알고 있습니다. Timer 0과 Timer 2를 쓰시고 인터럽트서비스 루틴에서 처리를 하시면 될 듯 싶네요 ^^
  • No Profile
    글쓴이 haze 10.01.26 18:09 댓글 좋아요 0 싫어요 0
    답변 감사드립니다.
    그런데 0과 2를 썼을때에도 동시에 구동이 안되더군요..
    아마 인터럽트 부분이 잘못된거 같은데.. 데이터 시트 뒤져봐도 잘 모르겠고.. 아니면 포트에 출력핀 지정하는 부분이 잘못된건지..
    답답하네요 ㅠㅠ
  • No Profile
    인터럽트가 제대로 작동 되는지 확인을 하기위해 우선 타이머 셋팅 값이 제대로 되었나를 확인 하시고 제대로 설정 되었다면, 인터럽트 서비스 루틴에서 카운트 변수 하나 설정해 놓으시고...카운트 변수가 셋 되었을때 포트에서 안쓰는 핀을 반전 시켜서 PWM 파형이 나오는지 우선 오실로 스코프로 찍어 보시고, 만약에 그 핀의 파형이 안나온다 하면(예를 들어 타이머 0 인터럽트 서비스루틴은 나오고 2가 안나온다 싶으면..) 동시에 구동이 안되는 것입니다. 한번 체크해보세요^^ 
  • No Profile
    그리고 타이머 설정 레지 스터에서 TIMSK  = 0x03; 이런 식으로 설정하면 문제가 생깁니다^^:
    타이머 0을 쓰기 위해 TIMSK  = 0x03;를 썻다가 다시 타이머 1을 쓰기 위해 TIMSK  = 0x04; 이런식으로 쓴다면 당연히 한쪽만 구동 됩니다. TIMSK |= 0x03; TIMSK  |= 0x04; 이런 식으로 비트 연산 부호인 ' | ' 를 붙여야
    TIMSK  = 0x07;로 셋팅 되어 타이머 0과 1을 쓴다는 설정값이기 때문입니다.

    모든 레지스터를 셋팅 하실때 그전에 있던 값이 지워짐을 방지 하기 위해서 일반적으로 ' = ' 이거 하나 보단
    비트 연산 부호인 ' | '를 추가해서 ' |= ' 를 많이 사용 합니다. ' = '이것 하나만 쓴다면은 이전에 있던 값이 지워 집니다. 예를 들어 TIMSK 레지스터에 전에 있던 값이 0x10; 이라고 가정하면 TIMSK = 0x10; 일 것입니다.
    거기에 TIMSK  |= 0x03 ; 이렇게 하는 것과 TIMSK  = 0x03 ;은 큰차이가 있습니다.
    TIMSK  |= 0x03 ;이렇게 하는 것은 0x10 + 0x03하는 것이 됨으로 TIMSK =  0x13; 이 됩니다.
    TIMSK 레지스터는 8bit로 구성되어 있습니다. 이진수로 표현하면 1111 1111 이 되는 것이죠 0x10은 이진수로 0001 0000 이고 0x03은 이진수로 0000 0011 입니다. 그것을 ' |= ' 이것으로 전에 있던 0x10즉 0001 0000이란 레지스터 셋팅 값을 건들이지 않고 0x03을 (0000 0011) 을 더한 0x13 (0001 0011)이것이 됩니다. 참고 하세요 ^^
  • No Profile
    글쓴이 haze 10.01.28 16:54 댓글 좋아요 0 싫어요 0
    타이머 1과 3은 동시에 사용이 가능한가요?
    인터럽트 셋팅값은 iccavr에서 자동으로 되니까 맞는거 같은데
    이상하게 타이머 0,2나 1,3을 쓰면 아예 시리얼 통신자체가 안되고
    0,1을 쓰면 시리얼 통신은 되긴 되는데 타이머 둘 중 하나만 되네요
    답답합니다..
  • No Profile
    글쓴이 haze 10.01.29 14:10 댓글 좋아요 1 싫어요 0
    타이머 하나로 하고 소스 수정해서 해결했습니다-
    배열 쓰면 간단한것을 괜히 타이머로 해보려다가;;
    배열쓰니 각각 따로 제어 가능하긴 한데
    모터 하나 제어할때 다른 모터가 약간씩 미세하게 움직이네요
  • No Profile
    모터하나를 제어 할때 다른 쪽의 모터가 움직인다면... 우선 2가지의 경우를 생각 할 수 있습니다. 한가지는 하드웨어 적으로 미세 전류가 다른쪽 모터쪽으로 흘러들어간다는 것이며, 다른것은 소프트웨어적 문제 일수도 있습니다. 해결방 법은 간단하게 하드웨어적으로는 만약 PORTF의 상위 비트위 하위비트에 모터를 연결 하셧다면.. 포트 F에 연결한 모터를 하나를 떼어서 쓰지않는 포트 에 물려서 제어를 한번 해보세요. 소프트웨어 적인것이라면 우선 자신이 코딩한대로 PWM파형이 나가는지 CPU쪽의 출력핀부터 하나 하나 오실로 스코프로 찍어가며 확인하여야 합니다.^^
  • No Profile
    글쓴이 haze 10.02.05 17:37 댓글 좋아요 0 싫어요 0
    까까님 감사합니다 덕분에 많은 도움이 되었습니다 ^^
  • No Profile
    웃는 얼굴을 보니 완성에 가까워 지신것 같으신데 화이팅 입니다^^ . 자신이 짠대로 동작하는 넘을 보면... 그야말로 뿌듯 그자체네요.. 그감을 얻기 위해 노력하신다면...프로가 되실 준비가 되신것입니다^^

하드웨어 설계 및 개발에 대하여 개발자들이 자유롭게 토론하는 공간입니다.
- Q&A, 자유주재 토론, 관련 정보 공유
- 분야 : 마이크로프로세서 응용, 전기/전자(아날로그/디지털) 회로 설계, C/C++ 프로그래밍, 펌웨어,
         PCB Artwork, 트러블슈팅 등 하드웨어 설계에 관한 전반인 내용
※ 게시글에 맞는 분류를 선택하여 글을 작성해 주시면 쾌적한 사이트 운영에 많은 도움이 됩니다.
※ 하드웨어 인사이트는 회원들간의 거래정보를 게재할 뿐이지, 그 어떤 책임과 의무도 가지지 않습니다.

search
번호 분류 제목 글쓴이 조회 수 날짜
3 머신러닝, AI & 알고리즘 HOT오목 게임 알고리즘3 새로운하늘 3459 2010.03.29
2 머신러닝, AI & 알고리즘 HOT지하철 최단거리 알고리즘은?2 지워나 2861 2008.06.20
1 머신러닝, AI & 알고리즘 HOT순차 프로그램에 대한 간단한 알고리즘과 재귀 알고리즘의 속도 테스트 - by 아크마7 아크마 3063 2007.08.08
  • 인생의 비극은 목표를 달성하지 못하는데 있는 것이 아니라, 달성할 목표가 없는 데에 있다.
    - 메이스
  • * 납포인트 정보 *
  • 글 작성 : 3
  • 댓글 작성 : 1
  • 내 글이 추천받음 : 1
저작권법에 위배되는 콘텐츠는 등록 불가하며, 저작물에 대한 권리는 저작자에게 있습니다.
Copyright 2006-2021 © hardwareis.com, All rights reserved.