평균을 구할 때 혼자서 튀어나와 있는 값들이 있죠.
그런 값들을 배제하고 병균을 구하는 방법은 보다 실제 평균에 가깝게 해 줍니다.
다음은 전에 포스팅 했던 ATmega128의 A/D 변환기에 Sorting 과정을 거져 잡음을 보다 확실하게 잡아낼 수 있는 알고리즘 입니다.
다음은 Sorting를 활용해 코딩하여 ADC의 오차를 보다 완벽하게 정리한 코드 입니다.
// 버블 알고리즘 적용 함수
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
// 이상치 배제 후 평균 계산 함수
double calculateMean(int arr[], int n) {
if (n == 0) return 0;
// 이상치를 배제할 범위 설정 (예: 상위 및 하위 10% 배제)
int excludeCount = n / 10; // 상위 및 하위 10%를 배제
int start = excludeCount;
int end = n - excludeCount;
if (end <= start) return 0; // 유효한 값이 없는 경우
double sum = 0;
int count = 0;
for (int i = start; i < end; i++) {
sum += arr[i];
count++;
}
return (count > 0) ? (sum / count) : 0;
}
void InitADC(void)
{
ADMUX = 0x00; //00 0 00000
ADCSR = 0xE5; //ADC enable, ADC start conversion, Free_run mode, Prescaler 32
// ADMUX:
// 00 => 기준전압으로 AREF핀을 사용한다.
// 0 => ADCH, ADCL의 하위비트부터 10비트를 채웁니다. ADCH는 비트 1 ~ 0을, ADCL은 비트 7 ~ 0을 사용한다.
// 00000 => 단일 입력채널 ADC0 ~ ADC7을 사용한다.
// ADCSR:
// ADEN = 1 => ADC 동작을 허용합니다. ADSC = 1 => AD변환을 시작한다.
// ADFR = 1 => ADC가 프리러닝 모드로 동작한다.
// ADIE = 0 => ADC 인터럽트는 사용하지 않는다.
// ADPS2 ~ 0 = 101 => ADC 입력 클럭의 분주비를 32분주로 설정한다.
}
unsigned int ReadADC(unsigned char channel)
{
// 변수 설정이다.
unsigned int AdcDet = 0;
unsigned int getADCresult = 0;
unsigned int deta[20]; // 20개의 값을 저장할 배열
unsigned char i, AdcDetL, AdcDetH = 0;
// 읽어낼 단일 입력 채널을 설정합니다. 트 4 ~ 0은 00000 ~ 00111의 값을 가진다.
ADMUX = channel; // Select Channel
for (i = 0; i < 20; i++) { // A/D 값을 20회 읽어서 평균값을 낸다.
// ADCSR 레지스터의 ADIF 비트가 1이 될 때까지 기다린다. 즉, AD 변환이 완료될 때까지 기다린다.
while (!(ADCSR & 0x10));
Delay(70); // 결과값을 읽기 전에 약간의 딜레이를 건다. 20회 읽는 시간을 벌고 값을 갱신하는 시간을 보장하기 위함이다.
ADCSR |= 0x10; // ADIF 비트에 1을 써서 강제로 지운다.
// 결과값을 넣어 20회 축적한다.
AdcDetL = ADCL;
AdcDetH = ADCH;
AdcDet = (((AdcDetH & 0xff) << 8) | (AdcDetL & 0xff));
deta[i] = AdcDet;
}
// 배열을 정렬하여 이상치를 배제하기 쉽게 한다.
int n = sizeof(deta) / sizeof(deta[0]);
bubbleSort(deta, n);
// 앞서 만든 함수를 활용하여 이상치를 배제하여 계산한 값을 얻는다.
double mean = calculateMean(deta, n);
return (unsigned int)mean; // 검출한 변환값을 반환한다.
}
위의 코드로 간단하게 sorting 할 수 있습니다.