Skip to main content
Associate
July 13, 2026
Question

ADC DMA real value reading STM32F103c8t6

  • July 13, 2026
  • 3 replies
  • 46 views

this is my code ADC real value read and calculation part but ADC real value not real when input dr

void process_adc_averages_and_filter(void)

{



for (uint8_t ch = 0; ch < ADC_CHANNELS; ch++)

{

uint32_t sum = 0;

for (uint8_t i = 0; i < ADC_SAMPLES; i++)

{

sum += adc_dma_buf[i * ADC_CHANNELS + ch];

}

adc_avg[ch] = sum / ADC_SAMPLES;



// Apply exponential low-pass filter

//float alpha = 0.1f; // Filter strength

/// adc_filtered[ch] = (1 - alpha) * adc_filtered[ch] + alpha * adc_avg[ch];

// adc_hist[ch] = (adc_hist[ch] * 31 + adc_avg[ch]) / 32;

// adc_filtered[ch] = adc_hist[ch];

// Fast stable filter

// single smooth filter

// adc_filtered[ch] = (adc_filtered[ch] * 0.95f) +

/// (adc_avg[ch] * 0.05f);



adc_filtered[ch] = (adc_filtered[ch] * 31 + adc_avg[ch])/32;



}

vfb_adc_fixed = (adc_filtered[3] + 2) / 5 * 5;

Vref = 160.0f + (adc_filtered[1] * 100.0f / 4095.0f);

Gain = 0.5f + (adc_filtered[2] * 30.5f / 4095.0f);



Adjust = 0.5f + (adc_filtered[0] * 4.5f / 4095.0f);



int32_t difference = (int32_t)vfb_adc_fixed - (int32_t)stable_adc_value;

if(difference > NOISE_THRESHOLD || difference < -NOISE_THRESHOLD ){

stable_adc_value = vfb_adc_fixed;

}





Vfb = (stable_adc_value * ADC_REF ) / 4095.0f;

Vfb = Vfb * (43.5+10)/10;

Vfbl = (Vfb + ((Vfb/10000)/0.047))/1.405;

///Voltage = Vfb;

// Voltage = (Vfbl * VFB_SCALE);

Voltage = stable_adc_value * VFB_SCALE;

///Vfb_Filter = 0.95f * Vfb_Filter + 0.05f * Vfb;



error = Vref - Voltage;



if (fabsf(error) < 0.5f)

{

error = 0;

}

// Gain adjustment

Kp = Gain * 120.0f;

Ki = Gain * 0.25f * Adjust;



// Integral

integral += error * 0.1f;



// Anti-windup

if (integral > 300.0f)

integral = 300.0f;

if (integral < -300.0f)

integral = -300.0f;



// PI output

control = (Kp * error) + (Ki * integral);



// Convert PI output to SCR firing delay

dim_delay = 4000 - control;



int32_t difference_firing_delay = (int32_t)dim_delay - (int32_t)stable_dim_delay;

if(difference_firing_delay > NOISE_THRESHOLD_DELAY || difference_firing_delay < -NOISE_THRESHOLD_DELAY ){

stable_dim_delay = dim_delay;

}



// Limit firing angle

if (stable_dim_delay < 300)

stable_dim_delay = 300;



if (stable_dim_delay > 5000)

stable_dim_delay = 5000;



}

op to 187V Voltage variable show 202v and when input is 227 voltage shows 210v 🤷🏽
 

 

3 replies

Karl Yamashita
Principal
July 14, 2026

When adding code, use the Code in the 3 ellipse. This will properly format the code to make it easier to read.

 

  

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
ST Technical Moderator
July 15, 2026

Hello ​@Neran88 

For now, it is more probable that the issue comes from your code rather than the ADC itself.
For example, what do the 43.5 and 10 values refer to?
It looks like a voltage divider, so they are likely resistors.
You should verify that the resistor values are really those values, because resistors have tolerances, typically ±5% or ±10%, depending on the part used.
Also, how much is VFB_SCALE, your final voltage depends entirely on VFB_SCALE, which may not match the real divider math.

If VFB_SCALE is not precisely correct, the displayed value will be wrong.

I recommend that you tweak your code and fine tune it.

Compute the voltage directly from the raw averaged ADC value.

If the voltage becomes correct, then the issue is likely in the filtering logic.
BR
Gyessine

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question.
Neran88Author
Associate
July 15, 2026

Thank you

i think i found the error i changed 10uf smoothing capacitor after voltage divider i think now its working with correct value