개발환경 : 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

-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
Posted by 나무길 :