Digital Power Starter Kit 3 Firmware
dsPIC33C Buck Converter Voltage Mode Control Example
dev_buck_substates.c
1 /*
2  * File: dev_buck_substates.c
3  * Author: M91406
4  * Comments: Buck converter operation sub-states header file
5  * Revision history:
6  * 10/28/20 1.0 initial version
7  */
8 
9 #include <xc.h> // include processor files - each processor file is guarded.
10 #include <stdint.h> // include standard integer data types
11 #include <stdbool.h> // include standard boolean data types
12 
13 #include "dev_buck_pconfig.h" // include buck converter
14 #include "dev_buck_typedef.h" // include buck converter data object declarations
15 
16 // Private function prototypes of sub-state functions
17 volatile uint16_t __attribute__((always_inline)) SubState_PowerOnDelay(volatile struct BUCK_CONVERTER_s *buckInstance);
18 volatile uint16_t __attribute__((always_inline)) SubState_PrepareVRampUp(volatile struct BUCK_CONVERTER_s *buckInstance);
19 volatile uint16_t __attribute__((always_inline)) SubState_VRampUp(volatile struct BUCK_CONVERTER_s *buckInstance);
20 volatile uint16_t __attribute__((always_inline)) SubState_IRampUp(volatile struct BUCK_CONVERTER_s *buckInstance);
21 volatile uint16_t __attribute__((always_inline)) SubState_PowerGoodDelay(volatile struct BUCK_CONVERTER_s *buckInstance);
22 
23 
24 // Declaration of function pointer array listing sub-state functions in order of execution
25 volatile uint16_t (*BuckConverterRampUpSubStateMachine[])(volatile struct BUCK_CONVERTER_s *buckInstance) =
26 {
32 };
33 
34 // Declaration variable capturing the size of the sub-state function pointer array
36 
37 
50 volatile uint16_t SubState_PowerOnDelay(volatile struct BUCK_CONVERTER_s *buckInstance)
51 {
52  volatile uint16_t retval=0;
53 
54  // Set BUSY bit until process is complete
55  buckInstance->status.bits.busy = true;
56 
57  // delay startup until POWER ON DELAY has expired
58  if(buckInstance->startup.power_on_delay.counter++ > buckInstance->startup.power_on_delay.period)
59  {
60  // Clamp POD counter to EXPIRED
61  buckInstance->startup.power_on_delay.counter =
62  (buckInstance->startup.power_on_delay.period + 1); // Saturate power on counter
63 
64  retval = BUCK_OPSRET_COMPLETE;
65  }
66  else
67  // When the period has not expired yet, return to this function
68  {
69  retval = BUCK_OPSRET_REPEAT;
70  }
71 
72  return(retval);
73 }
74 
75 
95 volatile uint16_t SubState_PrepareVRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
96 {
97  volatile uint16_t _i=0;
98  volatile uint32_t _vout=0;
99  volatile uint32_t _vin=0;
100  volatile uint32_t _start_dc=0;
101 
102  // Set BUSY bit until process is complete
103  buckInstance->status.bits.busy = true;
104 
105  // Copy user setting of voltage reference into loop reference
106  buckInstance->v_loop.reference = buckInstance->set_values.v_ref;
107 
108  // Hijack voltage loop controller reference
109  buckInstance->startup.v_ramp.reference = 0; // Reset Soft-Start Voltage Reference
110  buckInstance->startup.i_ramp.reference = 0; // Reset Soft-Start Current Reference
111  buckInstance->v_loop.controller->Ports.ptrControlReference =
112  &buckInstance->startup.v_ramp.reference; // Voltage loop is pointing to Soft-Start Reference
113 
114  // Pre-charge reference
115  // Never start above the pre-biased output voltage.
116  // Always start at or slightly below the pre-biased output voltage
117  buckInstance->startup.v_ramp.reference = buckInstance->data.v_out;
118 
119  // In average current mode, set current reference limit to max startup current level
120  if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_ACMC)
121  { // Disable all current control loops and reset control loop histories
122  buckInstance->v_loop.maximum = buckInstance->set_values.i_ref;
123  buckInstance->v_loop.controller->Limits.MaxOutput = buckInstance->v_loop.maximum;
124  }
125 
126  // Pre-charge PWM and control loop history
127  if(((buckInstance->data.v_in - buckInstance->feedback.ad_vin.scaling.offset) > 0) &&
128  ((buckInstance->data.v_out - buckInstance->feedback.ad_vout.scaling.offset) > 0) )
129  {
130  _vout = __builtin_muluu(
131  (buckInstance->data.v_out - buckInstance->feedback.ad_vout.scaling.offset),
132  buckInstance->feedback.ad_vout.scaling.factor);
133  _vout >>= (16 - buckInstance->feedback.ad_vout.scaling.scaler);
134 
135  _vin = __builtin_muluu(
136  (buckInstance->data.v_in - buckInstance->feedback.ad_vin.scaling.offset),
137  buckInstance->feedback.ad_vin.scaling.factor);
138  _vin >>= (16 - buckInstance->feedback.ad_vin.scaling.scaler);
139 
140  // Protect against negative duty cycle results
141  if (_vout > _vin) _vout = _vin;
142 
143  // CALCULATE BUCK CONVERTER STARTUP DUTY RATIO
144  // DC = VOUT / VIN, where DC = D * PERIOD
145 
146  if(_vin > 0)
147  {
148  _start_dc = __builtin_muluu((_vout), buckInstance->sw_node[0].period);
149  _start_dc = __builtin_divud(_start_dc, (uint16_t)_vin);
150  }
151  else
152  { _start_dc = (uint16_t)buckInstance->sw_node[_i].duty_ratio_min; }
153  }
154  else
155  // If there is no input voltage or no output voltage, start with minimum duty ratio
156  {
157  for (_i=0; _i<buckInstance->set_values.no_of_phases; _i++) {
158  _start_dc = (uint16_t)buckInstance->sw_node[_i].duty_ratio_min;
159  }
160  }
161 
162  // Program PWM module and pre-charge control loop
163  if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_VMC)
164  {
165  if(_start_dc < buckInstance->v_loop.minimum)
166  { _start_dc = buckInstance->v_loop.minimum; }
167  else if(_start_dc > buckInstance->v_loop.maximum)
168  { _start_dc = buckInstance->v_loop.maximum; }
169  else { /* continue */ }
170 
171  buckInstance->v_loop.ctrl_Precharge(buckInstance->v_loop.controller, 0, _start_dc);
172  *buckInstance->v_loop.controller->Ports.Target.ptrAddress = _start_dc; // set initial PWM duty ratio
173  if(buckInstance->v_loop.controller->Ports.AltTarget.ptrAddress != NULL)
174  *buckInstance->v_loop.controller->Ports.AltTarget.ptrAddress = _start_dc; // set initial PWM duty ratio
175  else { /* continue */ }
176 
177  }
178  else if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_ACMC)
179  {
180  // Limit startup duty cycle to largest minimum/smallest maximum
181  for (_i=0; _i<buckInstance->set_values.no_of_phases; _i++) {
182 
183  if(_start_dc < buckInstance->i_loop[_i].minimum)
184  { _start_dc = buckInstance->i_loop[_i].minimum; }
185  else if(_start_dc > buckInstance->i_loop[_i].maximum)
186  { _start_dc = buckInstance->i_loop[_i].maximum; }
187  else { /* continue */ }
188  }
189 
190  // Set initial duty cycle
191  for (_i=0; _i<buckInstance->set_values.no_of_phases; _i++)
192  {
193  // pre-charge current loop control histories with ideal duty cycle
194  buckInstance->i_loop[_i].ctrl_Precharge(
195  buckInstance->i_loop[_i].controller, 0, _start_dc
196  );
197 
198  // pre-charge PWM outputs with ideal duty cycle
199  *buckInstance->i_loop[_i].controller->Ports.Target.ptrAddress = _start_dc; // set initial PWM duty ratio
200  if(buckInstance->i_loop[_i].controller->Ports.AltTarget.ptrAddress != NULL)
201  *buckInstance->i_loop[_i].controller->Ports.AltTarget.ptrAddress = _start_dc; // set initial PWM duty ratio
202  else { /* continue */ }
203  }
204  }
205  else
206  {
207  return(BUCK_OPSRET_ERROR);
208  }
209 
210  return(BUCK_OPSRET_COMPLETE);
211 
212 }
213 
214 
230 volatile uint16_t SubState_VRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
231 {
232  volatile uint16_t retval=1;
233  volatile uint16_t _i=0;
234 
235  // Set BUSY bit until process is complete
236  buckInstance->status.bits.busy = true;
237 
238  // ensure control loop is enabled
239  if(!buckInstance->v_loop.controller->status.bits.enabled) {
240 
241  // Enable all PWM channels
242  retval &= buckPWM_Resume(buckInstance); // Enable PWM outputs
243 
244  // In voltage mode control...
245  if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_VMC)
246  { // only enable voltage loop
247  buckInstance->v_loop.controller->status.bits.enabled = true; // enable voltage loop controller
248  }
249  // In average current mode control...
250  else if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_ACMC)
251  {
252  // enable voltage loop controller
253  buckInstance->v_loop.controller->status.bits.enabled = true;
254 
255  // enable all phase current loop controllers
256  for (_i=0; _i<buckInstance->set_values.no_of_phases; _i++) {
257  buckInstance->i_loop[_i].controller->status.bits.enabled = true;
258  }
259  }
260  // IF control mode is set to unsupported control mode, return error
261  else
262  {
263  return(BUCK_OPSRET_ERROR);
264  }
265 
266  }
267 
268  // increment reference
269  buckInstance->startup.v_ramp.reference += buckInstance->startup.v_ramp.ref_inc_step;
270 
271  // check if ramp is complete
272  if (buckInstance->startup.v_ramp.reference > buckInstance->v_loop.reference)
273  {
274  // Set reference to the desired level
275  buckInstance->startup.v_ramp.reference = buckInstance->v_loop.reference;
276 
277  // Reconnect API reference to controller
278  buckInstance->v_loop.controller->Ports.ptrControlReference = &buckInstance->v_loop.reference;
279 
280  retval = BUCK_OPSRET_COMPLETE;
281 
282  }
283  else
284  // remain in this state until ramp is complete
285  {
286  retval = BUCK_OPSRET_REPEAT;
287  }
288 
289 
290  return(retval);
291 
292 }
293 
294 
313 volatile uint16_t SubState_IRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
314 {
315  volatile uint16_t retval=0;
316 
317  // Set BUSY bit until process is complete
318  buckInstance->status.bits.busy = true;
319 
320  // in average current mode if voltage limit is hit, increment
321  // voltage loop limit to ramp up current loop
322  if (buckInstance->set_values.control_mode == BUCK_CONTROL_MODE_ACMC)
323  {
324  // Increment maximum current limit
325  buckInstance->v_loop.controller->Limits.MaxOutput += buckInstance->startup.i_ramp.ref_inc_step;
326 
327  if (buckInstance->v_loop.controller->Limits.MaxOutput >= buckInstance->set_values.i_ref)
328  // check if ramp is complete
329  {
330  buckInstance->v_loop.maximum = buckInstance->set_values.i_ref;
331  buckInstance->v_loop.controller->Limits.MaxOutput = buckInstance->v_loop.maximum;
332  retval = BUCK_OPSRET_COMPLETE;
333  }
334  else
335  // if ramp is not complete yet, remain in this state
336  {
337  retval = BUCK_OPSRET_REPEAT;
338  }
339  }
340  else // In Non-Current Mode ramp-up ends up here and needs to be lifted to PG_DELAY
341  {
342  buckInstance->v_loop.controller->Limits.MaxOutput = buckInstance->v_loop.maximum;
343  retval = BUCK_OPSRET_COMPLETE;
344  }
345 
346  return(retval);
347 
348 }
349 
350 
363 volatile uint16_t SubState_PowerGoodDelay(volatile struct BUCK_CONVERTER_s *buckInstance)
364 {
365  volatile uint16_t retval=0;
366 
367  // Set BUSY bit until process is complete
368  buckInstance->status.bits.busy = true;
369 
370  // increment delay counter until the GOWER GOOD delay has expired
371  if(buckInstance->startup.power_good_delay.counter++ > buckInstance->startup.power_good_delay.period)
372  {
373  buckInstance->startup.power_good_delay.counter =
374  (buckInstance->startup.power_good_delay.period + 1); // Clamp to PERIOD_EXPIRED for future startups
375 
376  // If defined, set POWER_GOOD output
377  if(buckInstance->gpio.PowerGood.enabled)
378  {
379  retval = buckGPIO_Set(&buckInstance->gpio.PowerGood);
380  if(!retval)
381  return(BUCK_OPSTATE_ERROR);
382  }
383 
384  retval = BUCK_OPSRET_COMPLETE;
385  }
386  else
387  // if period has not expired yet, remain in this state
388  {
389  retval = BUCK_OPSRET_REPEAT;
390  }
391 
392  return(retval);
393 
394 }
395 
396 // end of file
BUCK_STARTUP_PERIOD_HANDLER_s::period
volatile uint16_t period
Soft-Start Period (POD, RAMP PERIOD, PGD, etc.)
Definition: dev_buck_typedef.h:266
v_loop
volatile struct NPNZ16b_s v_loop
External reference to user-defined NPNZ16b controller data object 'v_loop'.
Definition: v_loop.c:94
BUCK_LOOP_SETTINGS_s::reference
volatile uint16_t reference
Control loop reference variable.
Definition: dev_buck_typedef.h:347
BUCK_CONVERTER_s::startup
volatile struct BUCK_CONVERTER_STARTUP_s startup
BUCK startup timing settings.
Definition: dev_buck_typedef.h:504
BUCK_STARTUP_PERIOD_HANDLER_s::counter
volatile uint16_t counter
Soft-Start Execution Counter (read only)
Definition: dev_buck_typedef.h:265
BUCK_CONVERTER_STARTUP_s::v_ramp
volatile struct BUCK_STARTUP_PERIOD_HANDLER_s v_ramp
Definition: dev_buck_typedef.h:284
BUCK_CONVERTER_s::feedback
volatile struct BUCK_FEEDBACK_SETTINGS_s feedback
BUCK converter feedback settings.
Definition: dev_buck_typedef.h:507
BUCK_ADC_INPUT_SCALING_s::factor
volatile int16_t factor
Fractional scaling factor (range -1 ... 0.99969)
Definition: dev_buck_typedef.h:412
BUCK_CONVERTER_SETTINGS_s::control_mode
enum BUCK_CONTROL_MODE_e control_mode
Fundamental control mode.
Definition: dev_buck_typedef.h:324
BUCK_CONVERTER_DATA_s::v_in
volatile uint16_t v_in
BUCK input voltage.
Definition: dev_buck_typedef.h:300
BUCK_CONVERTER_s::i_loop
volatile struct BUCK_LOOP_SETTINGS_s i_loop[BUCK_MPHASE_COUNT]
BUCK Current control loop objects.
Definition: dev_buck_typedef.h:513
BUCK_CONVERTER_s::status
volatile struct BUCK_CONVERTER_STATUS_s status
BUCK operation status bits.
Definition: dev_buck_typedef.h:502
BUCK_SWITCH_NODE_SETTINGS_s::duty_ratio_min
volatile uint16_t duty_ratio_min
Absolute duty cycle minimum during normal operation.
Definition: dev_buck_typedef.h:388
BUCK_CONVERTER_STATUS_s::busy
volatile bool busy
Bit #7: Flag bit indicating that the state machine is executing a process (e.g. startup-ramp)
Definition: dev_buck_typedef.h:215
NPNZ_PORTS_s::Target
volatile struct NPNZ_PORT_s Target
Primary data output port declaration.
Definition: npnz16b.h:263
SubState_PowerGoodDelay
volatile uint16_t SubState_PowerGoodDelay(volatile struct BUCK_CONVERTER_s *buckInstance)
In this function, a counter is incremented until the power good delay has expired.
Definition: dev_buck_substates.c:363
SubState_PowerOnDelay
volatile uint16_t SubState_PowerOnDelay(volatile struct BUCK_CONVERTER_s *buckInstance)
This function delays the startup until the Power-on Delay has expired.
Definition: dev_buck_substates.c:50
BUCK_STARTUP_PERIOD_HANDLER_s::reference
volatile uint16_t reference
Internal dummy reference used to increment/decrement controller reference.
Definition: dev_buck_typedef.h:267
NPNZ_PORTS_s::AltTarget
volatile struct NPNZ_PORT_s AltTarget
Secondary data output port declaration.
Definition: npnz16b.h:264
BUCK_LOOP_SETTINGS_s::minimum
volatile uint16_t minimum
output clamping value (minimum)
Definition: dev_buck_typedef.h:350
NPNZ16b_s::status
volatile struct NPNZ_STATUS_s status
Control Loop Status and Control flags.
Definition: npnz16b.h:504
NPNZ_LIMITS_s::MaxOutput
volatile int16_t MaxOutput
Maximum output value used for clamping (R/W)
Definition: npnz16b.h:330
BUCK_FEEDBACK_SETTINGS_s::ad_vout
volatile struct BUCK_ADC_INPUT_SETTINGS_s ad_vout
ADC input sampling output voltage.
Definition: dev_buck_typedef.h:452
BUCK_CONVERTER_STARTUP_s::power_on_delay
volatile struct BUCK_STARTUP_PERIOD_HANDLER_s power_on_delay
Definition: dev_buck_typedef.h:281
BUCK_GPIO_INSTANCE_s::enabled
volatile bool enabled
Specifies, if this IO is used or not.
Definition: dev_buck_typedef.h:472
NPNZ_STATUS_s::enabled
volatile bool enabled
Bit 15: enables/disables control loop execution.
Definition: npnz16b.h:202
BuckConverterRampUpSubStateMachine
volatile uint16_t(* BuckConverterRampUpSubStateMachine[])(volatile struct BUCK_CONVERTER_s *buckInstance)
Buck converter state machine function pointer array.
BUCK_FEEDBACK_SETTINGS_s::ad_vin
volatile struct BUCK_ADC_INPUT_SETTINGS_s ad_vin
ADC input sampling input voltage.
Definition: dev_buck_typedef.h:451
BUCK_CONVERTER_STARTUP_s::i_ramp
volatile struct BUCK_STARTUP_PERIOD_HANDLER_s i_ramp
Definition: dev_buck_typedef.h:283
BUCK_CONVERTER_s::sw_node
volatile struct BUCK_SWITCH_NODE_SETTINGS_s sw_node[BUCK_MPHASE_COUNT]
BUCK converter switch node settings.
Definition: dev_buck_typedef.h:509
BUCK_CONVERTER_s::data
volatile struct BUCK_CONVERTER_DATA_s data
BUCK runtime data.
Definition: dev_buck_typedef.h:506
BUCK_ADC_INPUT_SCALING_s::offset
volatile int16_t offset
Signal offset as signed integer to be subtracted from ADC input.
Definition: dev_buck_typedef.h:414
BUCK_CONVERTER_s::gpio
volatile struct BUCK_GPIO_SETTINGS_s gpio
BUCK converter additional GPIO specification.
Definition: dev_buck_typedef.h:510
BUCK_LOOP_SETTINGS_s::maximum
volatile uint16_t maximum
output clamping value (maximum)
Definition: dev_buck_typedef.h:351
BUCK_LOOP_SETTINGS_s::ctrl_Precharge
void(* ctrl_Precharge)(volatile struct NPNZ16b_s *, volatile fractional, volatile fractional)
Function pointer to PRECHARGE routine.
Definition: dev_buck_typedef.h:358
SubState_PrepareVRampUp
volatile uint16_t SubState_PrepareVRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
This function calculate and pre-charge PWM outputs with ideal duty cycle.
Definition: dev_buck_substates.c:95
BUCK_CONVERTER_SETTINGS_s::v_ref
volatile uint16_t v_ref
User reference setting used to control the power converter controller.
Definition: dev_buck_typedef.h:326
BUCK_ADC_INPUT_SCALING_s::scaler
volatile int16_t scaler
Feedback bit-shift scaler used for number normalization.
Definition: dev_buck_typedef.h:413
buckPWM_Resume
volatile uint16_t buckPWM_Resume(volatile struct BUCK_CONVERTER_s *buckInstance)
This function resumes the buck PWM operation.
Definition: dev_buck_pconfig.c:369
BUCK_STARTUP_PERIOD_HANDLER_s::ref_inc_step
volatile uint16_t ref_inc_step
Size/value of one reference increment/decrement or this period.
Definition: dev_buck_typedef.h:268
BUCK_CONVERTER_s::set_values
volatile struct BUCK_CONVERTER_SETTINGS_s set_values
Control field for global access to references.
Definition: dev_buck_typedef.h:505
BUCK_GPIO_SETTINGS_s::PowerGood
volatile struct BUCK_GPIO_INSTANCE_s PowerGood
Power Good Output.
Definition: dev_buck_typedef.h:490
BuckRampUpSubStateList_size
volatile uint16_t BuckRampUpSubStateList_size
Buck converter sub-state machine function pointer array size.
Definition: dev_buck_substates.c:35
BUCK_CONVERTER_SETTINGS_s::i_ref
volatile uint16_t i_ref
User reference setting used to control the power converter controller.
Definition: dev_buck_typedef.h:327
BUCK_LOOP_SETTINGS_s::controller
volatile struct NPNZ16b_s * controller
pointer to control loop object data structure
Definition: dev_buck_typedef.h:353
NPNZ16b_s::Limits
volatile struct NPNZ_LIMITS_s Limits
Input and output clamping values.
Definition: npnz16b.h:508
BUCK_CONVERTER_s
BUCK control & monitoring data structure.
Definition: dev_buck_typedef.h:501
BUCK_CONVERTER_STARTUP_s::power_good_delay
volatile struct BUCK_STARTUP_PERIOD_HANDLER_s power_good_delay
Definition: dev_buck_typedef.h:282
SubState_IRampUp
volatile uint16_t SubState_IRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
This function is for the average current mode control where the output current is ramped up to nomina...
Definition: dev_buck_substates.c:313
BUCK_CONVERTER_s::v_loop
volatile struct BUCK_LOOP_SETTINGS_s v_loop
BUCK voltage control loop object.
Definition: dev_buck_typedef.h:512
buckGPIO_Set
volatile uint16_t buckGPIO_Set(volatile struct BUCK_GPIO_INSTANCE_s *buckGPIOInstance)
This function sets the selected general purpose input/ouput pins.
Definition: dev_buck_pconfig.c:653
SubState_VRampUp
volatile uint16_t SubState_VRampUp(volatile struct BUCK_CONVERTER_s *buckInstance)
This function ramps up the output voltage to its nominal regulation point.
Definition: dev_buck_substates.c:230
NPNZ16b_s::Ports
volatile struct NPNZ_PORTS_s Ports
Controller input and output ports.
Definition: npnz16b.h:505
BUCK_ADC_INPUT_SETTINGS_s::scaling
volatile struct BUCK_ADC_INPUT_SCALING_s scaling
normalization scaling settings
Definition: dev_buck_typedef.h:438
BUCK_CONVERTER_SETTINGS_s::no_of_phases
volatile uint16_t no_of_phases
number of converter phases
Definition: dev_buck_typedef.h:325
BUCK_SWITCH_NODE_SETTINGS_s::period
volatile uint16_t period
Switching period.
Definition: dev_buck_typedef.h:385
NPNZ_PORT_s::ptrAddress
volatile uint16_t * ptrAddress
Pointer to register or variable where the value is read from (e.g. ADCBUFx) or written to (e....
Definition: npnz16b.h:228
BUCK_CONVERTER_DATA_s::v_out
volatile uint16_t v_out
BUCK output voltage.
Definition: dev_buck_typedef.h:301
NPNZ_PORTS_s::ptrControlReference
volatile uint16_t * ptrControlReference
Pointer to global variable of input register holding the controller reference value (e....
Definition: npnz16b.h:265