0

프로세서 STM32F107을 사용하여 외부 소스에서 입력 값을 읽어야합니다. 이 저울은 프로세서가 포함 된 보드 외부에 있으며 PA4를 통해 프로세서와 통신합니다.STM32F107에서 읽는 아날로그 입력의 진동을 고정하는 방법

여기 저울에서 입력을 읽으려는 시도가 있습니다.

나는 설정이 기능을 ADC를 사용

void ADC_Configuration(void) { 

    ADC_InitTypeDef ADC_InitStructure; 
    /* PCLK2 is the APB2 clock */ 
    /* ADCCLK = PCLK2/6 = 72/6 = 12MHz*/ 
    RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
    /* Enable ADC1 clock so that we can talk to it */ 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
    /* Put everything back to power-on defaults */ 
    ADC_DeInit(ADC1); 

    /* ADC1 Configuration ------------------------------------------------------*/ 
    /* ADC1 and ADC2 operate independently */ 
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
    /* Disable the scan conversion so we do one at a time */ 
    ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
    /* Don't do contimuous conversions - do them on demand */ 
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
    /* Start conversin by software, not an external trigger */ 
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
    /* Conversions are 12 bit - put them in the lower 12 bits of the result */ 
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
    /* Say how many channels would be used by the sequencer */ 
    ADC_InitStructure.ADC_NbrOfChannel = 1; 

    /* Now do the setup */ 
    ADC_Init(ADC1, &ADC_InitStructure); 
    /* Enable ADC1 */ 
    ADC_Cmd(ADC1, ENABLE); 
    /* Enable ADC1 reset calibaration register */ 
    ADC_ResetCalibration(ADC1); 
    /* Check the end of ADC1 reset calibration register */ 
    while(ADC_GetResetCalibrationStatus(ADC1)); 
    /* Start ADC1 calibaration */ 
    ADC_StartCalibration(ADC1); 
    /* Check the end of ADC1 calibration */ 
    while(ADC_GetCalibrationStatus(ADC1)); 
} 

을 그리고 입력 얻기 위해이 기능을 사용 :

u16 readADC1(u8 channel) { 

    ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_1Cycles5); 

    // Start the conversion 
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
    // Wait until conversion completion 
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); 
    // Get the conversion value 

    return ADC_GetConversionValue(ADC1); 
} 

문제가를 그 같은 무게의 N 측정에서, I N 개의 다른 결과를 얻으십시오. 예를 들어, 무게가 70kg이고 readADC1 (ADC_Channel_4)의 출력은 715,760,748,711,759입니다.

내가 뭘 잘못하고 있니?

편집. 입력을 안정화시키는이 함수 (lp 필터를 시뮬레이트 함)를 추가 했으므로 정상적으로 작동합니다. 문제는이 함수에서 반환 된 값을 킬로그램으로 변환하는 방법입니다. 공리 계수 (알려진 물체를 측정함으로써 결정됨)를 사용하면 입력의 증가하는 무게에 비례하여 증가하는 오차가 발생합니다. 더 나은 전환이 있다고 제안하는 사람이 있습니까?

double fix_oscillations(){ 
    int i; 
    double LPOUT=0,LPACC=0; 
    int K = 5000; 

    for(i=0;i<5000;i++){ 
     LPACC = LPACC + readADC1(ADC_Channel_4) - LPOUT; 
     LPOUT = LPACC/K; 
    } 
    return LPOUT; 
} 
+0

평균/필터링을 추가 할 때 ... –

+0

사람들이 코드를 읽으려면 공통적이고 일관된 들여 쓰기 규칙과 약간의 공백 문자가 도움이됩니다. – Clifford

답변

2

입력이 본질적으로 잡음이 있거나 다른 장비에서 잡음이 발생할 수 있습니다. 최상의 솔루션에 영향을 미칠 수 있으므로 신호의 간섭 또는 잡음을 판단하려면 오실로스코프로 신호를 관찰 할 가치가 있습니다.

가능한 한 외부 간섭의 근원을 없애고 외부 아날로그 신호 조건을 적용해야합니다. 이상적인 샘플링 속도의 절반 이하의 차단 주파수를 가진 저역 통과 필터가 이상적입니다. 그런 다음 필요한 경우 디지털 도메인에서 필터링을 적용 할 수 있습니다. 정적 신호 (전압 레벨)의 경우 간단한 블록 평균이면 충분합니다. 움직이는 신호의 이동 평균 (상자 카 필터)이 더 좋을 수 있습니다. 특정 주파수를 추출해야하는 복잡한 신호의 경우보다 복잡한 필터가 필요하지만이 경우에는 그렇지 않을 수 있습니다.

+0

질문에 몇 가지 새로운 정보를 추가했습니다. 좀 봐 줄래? 지원해 주셔서 감사합니다. –

+1

일명 '커패시터를 입력에 걸쳐 놓으십시오.':) –

1

편집. 입력을 안정화시키는이 함수 (lp 필터를 시뮬레이트 함)를 추가 했으므로 정상적으로 작동합니다. 문제는이 함수에서 반환 된 값을 킬로그램으로 변환하는 방법입니다. 공리 계수 (알려진 물체를 측정함으로써 결정됨)를 사용하면 입력의 증가하는 무게에 비례하여 증가하는 오차가 발생합니다. 더 나은 전환이 있다고 제안하는 사람이 있습니까?

이것은 분명히 질문 제목과 관련이 없기 때문에 별도의 질문을 게시 할 가치가있었습니다.

출력이 비선형 인 경우 점 사이에서 선형 보간을 사용하여 여러 보정 점을 사용할 수 있지만 곡선은 방정식으로 특성화 될 수 있습니다. 관심 분야에 대해 여러 가지 측정을 한 다음 Excel 또는 OpenOffice.org Calc와 같은 스프레드 시트 도구에 이러한 점을 그립니다. 차트 작성 도구에는 다양한 유형의 "경향 선"플로팅이 포함되어 있으며 곡선의 등식을 표시 할 수 있습니다. 가장 적합한 가장 적합한 곡선 유형을 선택하십시오. 두 개 이상의 항이있는 다항식을 사용해야하는 경우, 소수점 이하의 수식 항을 표시하는 것이 중요 할 수 있으므로이를 확인하십시오. 방정식을 사용하여 곡선을 생성하고 추세선과 얼마나 잘 맞는지 확인하여 충분한 정밀도를 가지고 있는지 테스트 할 수 있습니다.방정식을 그려 보는 것은 충분한 정밀도 테스트를위한 곡선의 좋은 아이디어 일 것입니다. 코드를 작성할 때는 충분한 정밀도를 가진 데이터 유형을 사용해야합니다.

라인에 대한 참고 사항 : (샘플 시간의 비용으로) 효과적으로에 대한 12 비트하여 ADC 해상도를 증가 5000 개 샘플을 채취하여

LPOUT = LPACC/K; 

하지만 K로 나누어, 당신은 것을 잃었다 정밀도가 불필요하게, 잘리는 부분으로 잘립니다. 변환되지 않은 합계를 Kg로 변환하는 데 직접 사용하는 것이 좋습니다. 나는 나누기가 값을 "안정적"으로 보이게하지만 신호에 관한 것입니다. 잡음 비율은 절대적인 잡음 크기가 아닙니다. Kg로 변환하고 필요한 실제 정밀도로 표시하는 것은 결과를 "안정화"하는 것과 동일한 효과를 가지지 만 누적 오차는 더 적습니다.

+0

하지만 K로 나누지 않으면 오류를 제거 할 수 없습니다. 합만을 고려하면 오류가 계속 발생합니다. 권리? –

+0

@BoonTobias : 아니요. 내가 말했듯이 S/N 비에 관한 것입니다. 실수 값이 4.5이지만 정수 샘플이 4,5,3,6 인 경우 합계는 18 - 제로 오차 (4.5 * 4 = 18)입니다. 정수로 나누면 4가 4.5가 아니므로 지금은 4.5입니다. 당신의 실수는 0.5입니다. ADC 단위는 임의이며 실제 값과 관련이 없습니다. 0 ~ 255 범위의 8 비트 ADC를 사용하고 4 개의 샘플을 합산하면이 범위는 이제 0 ~ 1023 -보다 우수한 S/N 비를 가진 12 비트 ADC가됩니다. 이 고해상도 값을 실제 단위로 직접 변환하십시오. – Clifford

+0

내 부서는 두 배의 LPOUT과 정수 K 사이에 있습니다. 따라서 정밀도를 잃지 않는다고 가정합니다. –

1

ADC 정확도 향상을위한 STM32 애플리케이션 노트를 보았습니까? 해상도가 올라 가기위한 응용 프로그램 노트와 몇 가지 다른 응용 프로그램 노트도 있습니다.

이 링크는 here입니다. "ADC"에 대한 스크롤 상자 내에서 페이지 검색을 수행하십시오.

STMicro의 응용 프로그램 노트는 나중에 제품을 빨리 꺼내고 나중에 문서/지원을 추가하려는 경우에 유용합니다.

0

이 평균의 유용한 방법 찾을 수 있습니다

float FilteredValue; 
#define TIME_CONSTANT 100 
FilteredValue += ((float)ADCreading - FilteredValue)/TIME_CONSTANT; 

이 TIME_CONSTANT의 X 샘플 주파수의 시정과 함께 진정한 로우 패스 필터를 구현합니다. ADCreading에 단계 변경이 있으면 FilteredValue가 새 값으로 점차 변경됩니다. 이론적으로 역 지수 필터를 구현하기 때문에 절대 도달하지 않습니다. TIME_CONSTANT의 값이 클수록 노이즈 제거가 좋지만 안정화하는 데 오래 걸립니다.