Je dois lire la valeur d'entrée d'une source externe qui est une balance utilisant le processeur STM32F107. Cette balance est externe à la carte qui contient le processeur et communique avec elle via PA4.comment réparer les oscillations de l'entrée analogique lues par STM32F107
Voici ma première tentative de lecture de l'entrée de la balance.
J'utilise cette fonction pour configurer l'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));
}
J'utilise cette fonction pour obtenir l'entrée:
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);
}
Le problème est que dans les mesures N du même poids, je obtenir N résultats différents. Par exemple, le poids est de 70kg et la sortie du readADC1 (ADC_Channel_4) est 715,760,748,711,759 etc.
Qu'est-ce que je fais mal?
Modifier. J'ai ajouté cette fonction (qui simule un filtre lp) pour stabiliser l'entrée et cela fonctionne bien. Le problème est de savoir comment convertir la valeur renvoyée par cette fonction en kilogrammes. L'utilisation d'un coefficient de coût (déterminé en mesurant un objet connu) donne une erreur de croissance proportionnelle au poids croissant de l'intrant. Tout suggère d'avoir une meilleure conversion?
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;
}
Il est temps d'ajouter du moyennage/filtrage ... –
Si vous voulez que les gens lisent votre code, une convention de retrait commune et cohérente et un peu d'espace vertical seraient utiles. – Clifford