프로그래밍/Atmega128

[ATmega128] 16Bit 타이머를 이용한 스텝모터 사용 방법 (28BYJ-48 + L298N)

효또잠 2024. 1. 31. 09:00
반응형

1. Step Motor

스텝모터는 28BYJ-48을 사용하며, 해당 모델은 5개의 핀으로 구성되어 있고 상세 스펙은 아래와 같다.

 

각 상에 스테핑 방법에 맞게 PWM을 출력하면 모터의 구동이 가능하다.

* 위 그림의 Step을 8 -> 1로 (반대 방향) 진행 시키면 역방향으로 제어도 가능하다.

[참고]

https://github.com/gavinlyonsrepo/RpiMotorLib/blob/master/Documentation/28BYJ.md

위 글에서 나온 설명을 참고하면 Half-Step은 1ms 간격으로 Full-Step과 Wave-Drive는 10ms 간격으로 틱을 제어하는 게 좋다고 말하고 있다.

설명대로 동작시키려면 틱의 시간을 단순히 delay로 조절하는 방법이 있고 타이머 인터럽트를 설정해서 사용할 수 있다.

2. 16bit 타이머 인터럽트 제어

16 bit 타이머 인터럽트를 사용하는 이유는 8 bit 보다 정교하게 시간을 제어하기 위함이다.

우선 타이머 인터럽트 사용을 위해서는 0번 모드인 Normal을 선택한다.

 

 

마찬가지로 Normal 설정을 위해 모두 0으로 설정한다.

 

마지막으로 오버플로로 동작하도록 TOIE (Timer/Counter1 Overflow Interrupt Enable) 설정을 해준다.

 

3. 회로 구성

모터드라이버에 STEP 단자에 모터의 핀을 그대로 연결하고 INA~D 핀을 PA0~3으로 연결해준다.

4. 예제 코드

모터의 각 모드별 Phase 값을 저장한 배열을 미리 등록해준 뒤 사용하면 편하다.

 

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/common.h>

unsigned char halfStep[8] = {0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09};
unsigned char fullStep[8] = {0x0c, 0x06, 0x03, 0x09, 0x0c, 0x06, 0x03, 0x09};
unsigned char waveDrive[8] = {0x08, 0x04, 0x02, 0x01, 0x08, 0x04, 0x02, 0x01};

/* 16MHz(≈0.0625㎲) */
/* 0.0625㎲ * 64 * 250 */

volatile unsigned char count = 0;
ISR(TIMER1_OVF_vect)
{
	PORTA = halfStep[count];
	count++;
	if(count == 8)
	{
		count = 0;
	}
	TCNT1 = 65285; // 65535 - 250 => 1ms
}

int main(void)
{
	DDRA = 0x0f; // PA0 ~ 3 output
	TCCR1A = 0x00;
	TCCR1B = 0x03;
	TIMSK = 0x04;
	SREG = 0x80; // Global Interrupt Enable
	TCNT1 = 65285;
	
	while (1)
	{
		_delay_ms(10);	
	}
	return 0;
}
반응형