Skip to content

Instantly share code, notes, and snippets.

@bradysalz
Created March 4, 2018 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradysalz/9e4f57db8305da5b4587774161be1c35 to your computer and use it in GitHub Desktop.
Save bradysalz/9e4f57db8305da5b4587774161be1c35 to your computer and use it in GitHub Desktop.
Interleaving Power Converters
"""
Interleaved Buck Converter Simulations
Brady Salz
March 3 2018
This script helps us visualize the improvements in the output current ripple
of interleaved buck converters. We can view this as a 2D optimization over
the phase difference between the converters and the duty cycle of each
converter.
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
mpl.style.use('research')
def gen_wave(duty_cycle: float, num_points: int = 100,
cycles: int = 1) -> np.ndarray:
"""Creates a triangle wave
Args:
duty_cycle: on-time percentage (50% ontime would be 0.5)
num_points: number of points in one period
cycles: how many times to repeat the waveform
Returns:
1D waveform
"""
on_length = int(duty_cycle * num_points)
off_length = num_points - on_length
i_out = np.append(
np.linspace(-1, 1, num=on_length), np.linspace(1, -1, num=off_length))
i_out = np.tile(i_out, cycles)
return i_out
def interleave(waveform: np.ndarray, num_conv: int,
phase: float) -> np.ndarray:
"""Interleaves N copies of waveform by phase amount
Args:
waveform: 1D numpy array (usually triangular)
num_conv: the number of parallel converters to emulate
phase: offset in degrees of each converter.
Returns:
1D interleaved waveform
Note the phase offset is modular, e.g. 4 converters, each with a phase
offset of 100 degrees woud result in the 4th one having a '400 degree
offset', which wraps back around to 40 degrees.
"""
v_sum = np.zeros(waveform.shape)
length = waveform.size
for conv in range(num_conv):
shift = int(phase / 360 * conv * length)
v_sum += np.roll(waveform, shift)
return v_sum
def calc_ripple_reduction(num_conv: int, num_phase_points: int,
num_duty_points: int):
"""Plots ripple reduction contour plot!
Args:
num_conv: how many converters to interleave
num_phase_points: number of phase points
(steps in increments of 360/num_points)
num_duty_points: number of duty cycle points
(steps in increments of 100/num_points)
"""
degrees = np.linspace(0, 360, num_phase_points)
duty_cycles = np.linspace(0, 1, num_duty_points)
rvals = np.zeros((degrees.size, duty_cycles.size))
for idx, deg_shift in enumerate(degrees):
for idy, duty in enumerate(duty_cycles):
v_out = gen_wave(duty)
v_sum = interleave(v_out, num_conv, deg_shift)
ripple = np.amax(v_sum) - np.amin(v_sum)
rvals[idx, idy] = ripple
rvals = rvals / np.amax(rvals) * 100 # normalize to 100% ripple
levels = np.array([0, 10, 25, 50, 75, 100])
plt.set_cmap("plasma")
plt.contour(100 * duty_cycles, degrees, rvals, levels=levels)
cs = plt.contourf(100 * duty_cycles, degrees, rvals, levels=levels)
proxy = [
plt.Rectangle((0, 0), 1, 1, fc=pc.get_facecolor()[0])
for pc in cs.collections
]
plt.legend(proxy,
["0 - 10%", "10 - 25%", "25 - 50%", "50 - 75%", "75 - 100%"])
plt.xlabel("Duty Cycle [%]")
plt.ylabel("Phase Shift [deg]")
plt.title("Ripple Reduction with %d Converters" % num_conv)
plt.tight_layout()
plt.show()
if __name__ == '__main__':
calc_ripple_reduction(4, 360, 100)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment