AnsweredAssumed Answered

Problem with ADC

Question asked by boeh.frank on Mar 18, 2015
Latest reply on Mar 23, 2015 by boeh.frank
I am currently stuck with a strange phenomenon, and I am not sure anymore if what I do is how I should do it...

In my appliaction with the ST FOC library 4.0, I need to do some additional A/D conversions. This needs to be done as fast as possible. First I tried to use MC_RequestRegularConv/MC_GetRegularConv. This seemed to work, but was too slow as the conversions take place in TSK_SafetyTask at a 2kHz rate only.

I figured that the code there is using PWMC_ExecRegularConv to actually do the conversion. So I wrote the following function:

uint16_t doADC( uint8_t u8Channel )
    ADConv_t ADConv_struct;

    ADConv_struct.Channel = u8Channel;
    ADConv_struct.SamplTime = ADC_SampleTime_56Cycles;
    PWMC_ADC_SetSamplingTime( oCurrSensor[M1], ADConv_struct );
    return PWMC_ExecRegularConv( oCurrSensor[M1], u8Channel );

I call this function from within main() in a loop for several different channels:

#define ADC_I_BAT   ADC_Channel_8  // PB0
#define ADC_T_MOTOR ADC_Channel_9  // PB1
#define ADC_AIN_1   ADC_Channel_10 // PC0
#define ADC_AIN_2   ADC_Channel_11 // PC1
#define ADC_AIN_3   ADC_Channel_12 // PC2
#define ADC_T_BOARD ADC_Channel_13 // PC3
#define ADC_V_BAT   ADC_Channel_15 // PC5

while (1)
    u16Throttle = doADC( ADC_AIN_1 );
    u16Brake    = doADC( ADC_AIN_2 );
    u16Temp     = doADC( ADC_T_BOARD );
    fBoardTemp  = calcNTC( u16Temp );
    u16Temp     = 65535 - doADC( ADC_T_MOTOR );
    fMotorTemp  = calcNTC( u16Temp );
    fBattCurrent= ((float)doADC( ADC_I_BAT ) - 32768.0) / 65536.0 * 3.3 / 55e-3;
    fBattVoltage= (float)doADC( ADC_V_BAT ) / 65536.0 * 3.3 / 0.0279;


There are no calls from other locations, and I do not use the MC_RequestRegularConv/MC_GetRegularConv mechanism anymore.

Basically this works fine, but there are some irregularities. On one of the channels I sometimes (maybe once out of 100 times) get a wrong result. Instead of the real value (a few 100 counts) I get something in the range of 42000. Unfortunately this is the throttle input, meaning my motor receives an audible current "kick" from this. I checked carefully, the signal is not present on the analog input.

I know that the phase current measurement is performed simultaneously, and basically asynchronously to the above code, using regular / injected conversion "preempting".

Furthermore, I have read ST's errata sheet for the used STM32F405RGT6, which explains something exactly in this direction, but I do not understand what is exactly meant and if this applies to my problem.

So my question: is my implementation correct, is this the intended use of these FOC library calls, is maybe that device errata causing trouble here? I also wonder why only that first channel is affected.