개발환경 : CodeVisionAVR (Version : 2.05.0 Evaluation)
------------------------------------- mov_avg_recursion.h -----------------------------------
#ifndef __MOV_AVG_RECURSION__
#define __MOV_AVG_RECURSION__
#define MOV_FILTERSIZE 4
#define CHANNEL 4
void MovAvgRecursion(int input);
#endif //__MOV_AVG_RECURSION__
------------------------------------------------------------------------------------------
------------------------------------- mov_avg_recursion.c -----------------------------------
#include "my_header.h"
int average;
void MovAvgRecursion(int input)
{
static int data[MOV_FILTERSIZE];
unsigned char i;
int temp;
temp = input - data[0];
if (temp < 0) temp += 3;
average += temp >> 2;
for (i = 0; i < MOV_FILTERSIZE - 1; i++)
data[i] = data[i+1];
data[i] = input;
}
------------------------------------------------------------------------------------------
위 코드중에 빨간색 친 부분을 보면 음수일 때 또다른 연산을 해준다. 그 이유는 '/' 와 '>>' 음수 부분에서 차이점이 있는데
'/' 연산은 음수에서 버림같은 느낌이고 '>>' 연산은 같은 나눗셈이지만 올림같은 느낌이다.
예를 들면 Data 를 4로 나누기(/) , 2 로 쉬프트(>>) 시킨다고 했을때 아래 표와 같은 결과가 나온다.
Data |
0 |
-1 |
-2 |
-3 |
-4 |
-5 |
-6 |
-7 |
-8 |
Device |
0 |
0 |
0 |
0 |
-1 |
-1 |
-1 |
-1 |
-2 |
Shift |
0 |
-1 |
-1 |
-1 |
-1 |
-2 |
-2 |
-2 |
-2 |
쉬프트 연산과 같이 올림 연산을 하게되면 오차가 누적이 되는데 이동평균 필터는 조그만 오차라도 누적이되기 시작하면 나중에 그 오차들이 없어지는 것이 아니라 유지된다. 그래서 위에 빨간색과 같은 음수부분에서 연산을 해줘야 한다.
* 쉬프트 연산으로 3배, 9배, 15배, 60배 하는 방법 (쉬프트 연산은 기본적으로 2에 승수배씩 연산을 할 수 있다.)
3배 : (a << 1) + a;
9배 : (a << 3) + a;
15배 : (a << 4) - a;
60배 : (a << 6) - (a << 2);
'project > 씨름로봇' 카테고리의 다른 글
2. 이동평균필터와 재귀식 (0) | 2015.11.02 |
---|---|
1. 평균필터와 재귀식 (0) | 2015.11.02 |
ATmega128 전원부 캐패시터와 콘덴서 역할 (0) | 2015.10.24 |
DC 모터 주파수 설정 (0) | 2015.10.21 |
분해능과 분주비 (0) | 2015.10.21 |