Clarification on Sampling Rate vs. Control Bandwidth in Average Current Mode Control for Buck Converter

I am implementing Average Current Mode Control for a Buck converter. According to control theory, the voltage loop (outer loop) is typically designed to be 5–10 times slower than the current loop (inner loop) to ensure stability and proper decoupling.
However, in my current simulation setup, the ADC for both voltage and current is triggered at the same time. Does this imply that the execution frequency (sampling rate) of both control loops must be identical?
How can I implement a slower voltage loop while maintaining the same ADC sampling frequency for both signals in Simulink/Embedded C? Any insights on whether this 'simultaneous sampling' contradicts the principle of having a slower outer loop would be greatly appreciated

 Accepted Answer

Hi @Cuong, Thanks for the detailed questions on your Buck converter setup — really good thinking on your part to question this. Let me go through everything clearly. FIRST DOES SIMULTANEOUS ADC SAMPLING FORCE BOTH LOOPS TO RUN AT THE SAME RATE No it does not. This is the most important thing to understand. The ADC sampling rate and the control loop execution rate are two completely separate things. Your two ADC blocks (Voltage Vout_FB and Current I_FB) are both triggered by the same ePWM event, which just means fresh data for both signals is available every switching cycle. It does not mean you are forced to act on that data every cycle. The voltage loop is perfectly free to read a new Vout sample every cycle but only compute a new Iref every 10 cycles, for example. The data simply waits in memory until the voltage loop runs again. This is completely standard practice. So simultaneous sampling does not contradict the 5–10x slower outer loop principle at all — in fact, it is the recommended approach. You always want the freshest possible data going into your controllers, regardless of how often each controller executes. SECOND THE REAL PROBLEM IN YOUR CURRENT DIAGRAM Looking at your Simulink model carefully, the issue is not the ADC — it is the single CLA_TASK block driving the entire model. Right now, both your Voltage PI and your Current PI sit inside that one task, which means they both execute every single PWM cycle at exactly the same rate. That is what is actually violating the cascade control principle, not the ADC setup. The [Enable] signals you already have in the diagram are PWM output enable/disable signals — they are not doing anything to slow down the voltage loop execution, in case you were wondering about those. THIRD THREE WAYS TO FIX THIS Here are three practical options, ordered from simplest to most architecturally complete: Option 1 — Software Decimation Counter (Simplest, no restructuring needed) Add a counter inside your Voltage PI subsystem. The counter increments every CLA task execution, and the Voltage PI only computes a new Iref when the counter reaches your decimation target (e.g., every 10 cycles). Between updates, Iref simply holds its last value — this is called Zero-Order Hold behaviour and it is exactly what you want. The Current PI keeps running every cycle tracking that slowly changing Iref at full speed. In C code this looks like: static uint16_t volt_counter = 0; static float32 Iref = 0.0f; volt_counter++; if (volt_counter >= 10) { volt_counter = 0; Iref = VoltagePIController(Vref, Vfb); } DutyCycle_PU = CurrentPIController(Iref, ILfb); Option 2 — Split Voltage PI to CPU ISR (Cleanest architecture) Move the Voltage PI subsystem out of the CLA task entirely and put it under a CPU timer interrupt running at the slower rate. The CLA handles the fast current loop every PWM cycle, the CPU handles the slow voltage loop at 1/10th the rate. Both ADCs still sample every cycle — nothing changes there. This is the cleanest approach because it uses the F2837x hardware exactly as TI intended: CLA for hard real-time fast tasks, CPU for supervisory slower tasks. In Simulink this means placing the Voltage PI under a Hardware Interrupt block configured to a CPU timer, separate from the CLA_TASK. Option 3 — Rate Transition Block in Simulink (Best for simulation fidelity) Set the Voltage PI subsystem sample time to N times your switching period, set the Current PI to the base switching period, then insert a Rate Transition block on the Iref signal line between the two. Enable "Ensure data integrity during data transfer" in the Rate Transition block parameters. In your model Configuration Parameters, go to Solver and enable "Treat each discrete rate as a separate task" — this schedules both loops as genuinely separate tasks in the generated code. You can verify this is set up correctly by right-clicking the canvas, going to Sample Time Display, and selecting Colors. Your two PI subsystems should appear in two different colours, confirming they are running at different rates. OFFICIAL MATHWORKS REFERENCE MathWorks actually has an official reference model for exactly your situation. It is called f28379D_DCDC_Buck_CLA.slx and it implements Average Current Mode Control on the F28379D using the CLA. I strongly recommend opening it and comparing its CLA task partitioning against your own diagram — it will make the recommended architecture immediately clear. You can find it by running this in MATLAB: openExample('c2b/DCDCBuckConverterExample','supportingFile','f28379D_DCDC_Buck_CLA.slx') QUICK SUMMARY * Simultaneous ADC sampling does NOT force the same loop execution rate — this is fine * Your real issue is both PI controllers sharing one CLA_TASK running at the same rate * The [Enable] tags in your diagram are PWM enable signals, not loop rate control * Recommended fix: start with the decimation counter approach (Option 1) as it requires the least restructuring * For a cleaner long-term architecture: move Voltage PI to a CPU ISR (Option 2) * Check the official MathWorks f28379D_DCDC_Buck_CLA.slx reference model Hope this clears everything up.

4 Comments

Hi Umar, thank you for your helpful advice. I’ve decided to go with the timer interrupt approach as you suggested. I have already integrated the Hardware Interrupt block and configured the CPU and PIE for Timer 0, using a Function-Call Subsystem to execute the voltage control loop. However, I’m still unclear on where to configure the actual interrupt period (frequency) for the timer. Could you point me to where those settings are located? Thanks again!
Hi @Cuong,
Good question — this part trips a lot of people up because there is no separate "timer period" box anywhere obvious in Simulink. The short answer is: you do not set it directly. Embedded Coder figures out the correct Timer 0 hardware settings automatically, based on the sample time you assign to your subsystem. So the real control knob is just the sample time on your Function-Call Subsystem.
Here is what is happening under the hood. By default, the generated code uses CPU Timer 0 as the base rate scheduler. The blockset reads your model's base sample time, works backwards to calculate the right timer period and prescaler values, and writes those to the hardware registers at startup. You never touch a register yourself. This is confirmed in the MathWorks scheduling documentation linked in the references below.
So in your case, if your switching frequency is 100 kHz and you want the voltage loop ten times slower, just set your Function-Call Subsystem's sample time to one tenth of the switching period. That is literally all you need to change on the Simulink side. The toolchain handles the rest.
To confirm that Timer 0 is set as your base rate trigger, go here in Simulink: Modeling → Model Settings → Configuration Parameters → Hardware Implementation → Target Hardware Resources → Operating System / Scheduler → Base rate trigger: Timer 0
That is the C28x Scheduler Options panel. As long as Timer 0 is selected there, you are good to go. The blockset does the rest automatically. One thing to be careful about though — and this is actually called out in the official docs as a warning. If Timer 0 is your base rate trigger, do not also add a separate Hardware Interrupt block pointing at the Timer 0 interrupt. That would cause a conflict because you would be trying to handle the same interrupt in two places at once. Keep Timer 0 purely as the scheduler trigger for your slow voltage loop, and leave your CLA handling the fast current loop exactly as it already is.
After you have set the sample time on your voltage loop subsystem, there are two quick things to sort out in Simulink. First, put a Rate Transition block on the signal line that carries the current reference from the output of your Voltage PI into the Current PI input. In the block parameters, tick the option that ensures data integrity during transfer. Second, go to Configuration Parameters, find the Solver section, and enable the option called "Treat each discrete rate as a separate task." Once you have done that, right-click on the canvas, go to Sample Time Display, and click Colors. Your two subsystems should show up in two different colours. If they do, Simulink is treating them as genuinely separate tasks and you are all set.
Hope that clears it up completely. Let us know how it goes!
References — MathWorks Official Documentation:
Scheduling and Timing — C2000 Microcontroller Blockset
https://www.mathworks.com/help/ti-c2000/ug/scheduling-and-timing.html
C28x-Scheduler Options — Base Rate Trigger / Timer 0
https://www.mathworks.com/help/ti-c2000/ref/sect-hw-imp-pane-c28x-scheduler-options.html
C28x Hardware Interrupt Block Reference
https://www.mathworks.com/help/ti-c2000/ref/c28xhardwareinterrupt.html
Model Configuration Parameters for Texas Instruments C2000 Processors
https://www.mathworks.com/help/ti-c2000/ref/model-configuration-parameters-for-texas-instruments-c2000-processors.html
Hi@Cuong, Please let me know if you need any further assistance.
Hi Umar! Thanks so much for the follow-up. Everything is sorted out now and working perfectly. Thanks again for your support

Sign in to comment.

More Answers (0)

Asked:

on 13 Mar 2026 at 3:47

Commented:

about 11 hours ago

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!