Fogeaters, Light The World.

09

2016-Feb

[AVR] 루프 실행시간 측정 (아두이노의 Millis(), Micros() 분석)

작성자: title: MoonBlonix IP ADRESS: *.148.87.98 조회 수: 1456

출처 :: http://www.avrfreaks.net/forum/millis-and-micros-8bits


밑에는 복잡하게 분석을 해뒀는데 사실 단순히 AVR 코드로 Millis() 함수의 기능을 구현하는건 아주아주 간단하다.

그냥 uint32_t 형의 정수를 전역으로 선언해두고 정확히 1ms 마다 오버플로되는 타이머를 만들어서 이 변수를 매 인터럽트마다 1씩 올려주면 된다.

그리고 이 변수를 필요한곳에서 끌어다가 써주면 된다. 끝.

근데 uint32_t 자료형의 한계로 1ms 마다 1씩 상승시킬 경우 가동후 49.7일이 지나면 오버플로된다. 이게 문제될 상황이라면 알아서 대안을 생각해 해결한 뒤에 본 게시글에 댓글을 작성해주기 바란다. (당장 머리속에 떠오르는 바로는 루프dt가 비정상적으로 큰값이 나올 때, 루프 한번을 쉬게 하면 될 것 같다. 물론 센서 적분값에 약간 큰 오차가 누적되겠지만, 그 이전에 49일 연속기동을 해놓고 오차가 누적되지 않기를 바라진 않겠지?)


만약 타이머가 부족해서 도저히 1ms 로 오버플로되는 타이머를 못만들 상황이라면 아래 코드를 분석해보라. 오차보정도 포함된 코드다.


이 글이 필요한 사람중 모르는 사람은 없겠지만, 2016년 현재 avr studio 에서는 인터럽트를 SIGNAL 이 아니라 ISR 로 표기한다.




On the 88/168/328, TIMER0 is set to mode 3, fast PWM, with prescaler 64. At 16 MHz, this gives an overflow interrupt every 1024 uS. The ISR updates three volatiles:

volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;

SIGNAL(TIMER0_OVF_vect)
{
	unsigned long m = timer0_millis;
	unsigned char f = timer0_fract;

	m += MILLIS_INC;
	f += FRACT_INC;
	if (f >= FRACT_MAX) {
		f -= FRACT_MAX;
		m += 1;
	}

	timer0_fract = f;
	timer0_millis = m;
	timer0_overflow_count++;
}

... where MILLIS_INC, FRACT_INC, and FRACT_MAX are macros:

#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)

... and the function millis() simply returns the value of timer0_millis:

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

The function micros() is somewhat more involved:

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;
	
	cli();
	m = timer0_overflow_count;
	t = TCNT0;

  
	if ((TIFR0 & _BV(TOV0)) && (t < 255))
		m++;

	SREG = oldSREG;
	
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

... and has a resolution of 4 uS at 16 MHz.

So, at the expense of an actual millis() resolution of 1024 uS, the two PWM channels on TIMER0 retain a full 8-bits of resolution for use by analogWrite(). For boards running at 8 MHz (like a Pro Mini 3.3V), millis() resolution drops to 2048 uS, and micros() resolution drops to 8 uS.

profile
List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 [Web] 클라우드 IDE + 2 title: MoonBlonix 2017-06-25 15128
32 [AVR] HC_SR04 초음파센서 사용 file title: MoonBlonix 2016-02-13 1669
31 [AVR] 피에조 부저 활용 file + 1 title: MoonBlonix 2016-02-12 1956
30 칼만필터(Kalman Filter) + 2 title: MoonBlonix 2016-02-11 4377
29 low pass filter, high pass filter (저역통과필터, 고역통과필터) file title: MoonBlonix 2016-02-11 1456
» [AVR] 루프 실행시간 측정 (아두이노의 Millis(), Micros() 분석) title: MoonBlonix 2016-02-09 1456
27 상보필터(Complementary Filter) file title: MoonBlonix 2016-02-09 1740
26 가속도, 자이로 센서에 대해 title: MoonBlonix 2016-02-09 1572
25 [AVR] UART 통신 file title: MoonBlonix 2016-02-07 1609
24 C++ 과 C 를 같은 프로젝트에서 사용하기 title: MoonBlonix 2016-02-07 1506
23 라즈베리파이 운영체제에 관하여 title: MoonBlonix 2016-02-05 1459
22 [리눅스] 기본 명령어 title: MoonBlonix 2016-02-05 1632
21 [리눅스] C 언어 개발환경 구축 title: MoonBlonix 2016-02-05 1864
20 라즈베리파이 GPIO 핀 배열 file title: MoonBlonix 2016-02-05 2061
19 C++ 멤버 함수 포인터 title: MoonBlonix 2016-01-23 1775
18 AVR 직접만든 DC모터 라이브러리 (C++ Class) file title: MoonBlonix 2016-01-16 1518
17 [AVR] I/O 포트 메뉴얼 (ATMega128) file title: MoonBlonix 2016-01-16 1594
16 AVR delay 함수 (_delay_ms, _delay_us) title: MoonBlonix 2016-01-15 1641
15 AVR 멀티채널 PWM (타이머 하나로 여러 PWM 구동) title: MoonBlonix 2016-01-15 1651
14 AVR 초패스트 PWM title: MoonBlonix 2016-01-14 1566
13 AVR 타이머 응용 여러 PWM 방식과 예제 file + 1 title: MoonBlonix 2016-01-14 1652