SVPWM波的原理不再过多介绍。
最近在学习SVPWM,仿真了一下马鞍波。
python源码贡献出来。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anim
#############################################
# 我们的目的是根据机械角度,生成电角度,然后根据电角度算出Ta,Tb,Tv0,Tv7
# 动态图部分:机械角度-->电角度-->Ta/Tb/Tv0/Tv7-->马鞍波-->PWM波
class SVPWM_WAVE():
def __init__(self):
self.Udc = 1
self.Vk = 2/3*self.Udc
self.pwm_act_percent = 0.5
self.V_ref = np.sqrt(3)/2*self.Vk*self.pwm_act_percent
self.pole_num = 3 # 电机的磁极对数
# 电机旋转的角速度
self.motor_omiga = 10*2*np.pi
# 电机旋转的总时长
self.total_time = 0.1 # 单位:s
# 电机旋转的总角度
self.total_macAng = self.total_time*self.motor_omiga
# 仿真时间精度
self.time_precision = 0.0002 # 单位:s
# 仿真总数据点
self.sim_N = np.uint32(self.total_time/self.time_precision)
# 仿真时间所有的刻度
self.sim_t = np.array([i*self.total_time/self.sim_N for i in range(self.sim_N)])
self.machineAng = None
self.elecAng = None
self.elecAng_p = None
self.sector_no = None
self.v_theta = None
self.vector_a = None
self.vector_b = None
self.Ta = None
self.Tb = None
self.Tv7 = None
self.pwm1_percent = None
self.pwm2_percent = None
self.pwm3_percent = None
# 每一个点的数据记录
self.machineAng_record = []
self.elecAng_record = []
self.vector_a_record = []
self.v_theta_record = []
self.Ta_record = []
self.Tb_record = []
self.Tv0_record = []
self.Tv7_record = []
self.pwm1_percent_record = []
self.pwm2_percent_record = []
self.pwm3_percent_record = []
# 绘制 电机的 Machine Angle
self.machine_position_x = None
self.machine_position_y = None
self.electric_position_x = None
self.electric_position_y = None
self.fig = None
self.pwm_total_period = 1000
self.pwm_wave_x_line = np.array([i*100/self.pwm_total_period for i in range(self.pwm_total_period)])
def machineAng_2_electricAng(self, macAng):
self.elecAng = macAng*self.pole_num
def get_elec_sectorno(self):
self.elecAng_p = self.elecAng
while(self.elecAng>=2*np.pi):
self.elecAng = self.elecAng - 2*np.pi
if(self.elecAng >= 5*np.pi/3):
self.sector_no = 5
self.vector_a = 5*np.pi/3
return 0
elif(self.elecAng >= 4*np.pi/3):
self.sector_no = 4
self.vector_a = 4*np.pi/3
return 0
elif(self.elecAng >= np.pi):
self.sector_no = 3
self.vector_a = np.pi
return 0
elif(self.elecAng >= 2*np.pi/3):
self.sector_no = 2
self.vector_a = 2*np.pi/3
return 0
elif(self.elecAng>= np.pi/3):
self.sector_no = 1
self.vector_a = np.pi/3
return 0
elif(self.elecAng>=0):
self.sector_no = 0
self.vector_a = 0
return 0
def get_TaTb_Tv7(self):
'''
计算Ta Tb Tv7
'''
# 公式 Tb*Vk/sin(theta) = Ta*Vk/sin(pi/3-theta) = Vref/sin(2*pi/3)
self.v_theta = self.elecAng - self.vector_a
self.Ta = self.V_ref/self.Vk*np.sin(np.pi/3-self.v_theta)/np.sin(2*np.pi/3)
self.Tb = self.V_ref/self.Vk*np.sin(self.v_theta)/np.sin(2*np.pi/3)
self.Tv7 = (self.pwm_act_percent - self.Ta - self.Tb)/2
def trans_TaTbTv7_PWM(self):
'''
...-100-110-010-011-001-101-100-...
'''
if(self.sector_no == 0):
# -0-4-6-7-7-6-4-0-
# 4(100) 6(110) 7(111)
self.pwm3_percent = self.Ta + self.Tb + self.Tv7 # bit 2
self.pwm2_percent = self.Tb + self.Tv7 # bit 1
self.pwm1_percent = self.Tv7 # bit 0
elif(self.sector_no == 1):
# -0-2-6-7-7-6-2-0-
# 2(010) 6(110) 7(111)
self.pwm3_percent = self.Ta + self.Tv7 # bit 2
self.pwm2_percent = self.Tb + self.Ta + self.Tv7 # bit 1
self.pwm1_percent = self.Tv7 # bit 0
elif(self.sector_no == 2):
# -0-2-3-7-7-3-2-0-
# 2(010) 3(011) 7(111)
self.pwm3_percent = self.Tv7 # bit 2
self.pwm2_percent = self.Ta + self.Tb + self.Tv7 # bit 1
self.pwm1_percent = self.Tb + self.Tv7 # bit 0
elif(self.sector_no == 3):
# -0-1-3-7-7-3-1-0-
# 1(001) 3(011) 7(111)
self.pwm3_percent = self.Tv7 # bit 2
self.pwm2_percent = self.Ta + self.Tv7 # bit 1
self.pwm1_percent = self.Tb + self.Ta + self.Tv7 # bit 0
elif(self.sector_no == 4):
# -0-1-5-7-7-5-1-0-
# 1(001) 5(101) 7(111)
self.pwm3_percent = self.Tb + self.Tv7 # bit 2
self.pwm2_percent = self.Tv7 # bit 1
self.pwm1_percent = self.Ta + self.Tb + self.Tv7 # bit 0
elif(self.sector_no == 5):
# -0-4-5-7-7-5-4-0-
# 4(100) 5(101) 7(111)
self.pwm3_percent = self.Tb + self.Ta + self.Tv7 # bit 2
self.pwm2_percent = self.Tv7 # bit 1
self.pwm1_percent = self.Ta + self.Tv7 # bit 0
def motor_record_p(self, t):
self.machineAng = t*self.motor_omiga
self.machineAng_2_electricAng(self.machineAng)
self.get_elec_sectorno()
self.get_TaTb_Tv7()
self.trans_TaTbTv7_PWM()
def motor_record(self):
for t_i in self.sim_t:
self.motor_record_p(t_i)
self.machineAng_record.append(self.machineAng)
self.elecAng_record.append(self.elecAng_p)
self.vector_a_record.append(self.vector_a)
self.v_theta_record.append(self.v_theta)
self.Ta_record.append(self.Ta)
self.Tb_record.append(self.Tb)
self.Tv0_record.append(self.Tv7)
self.Tv7_record.append(self.Tv7)
self.pwm1_percent_record.append(self.pwm1_percent)
self.pwm2_percent_record.append(self.pwm2_percent)
self.pwm3_percent_record.append(self.pwm3_percent)
svpwm.pwm1_percent_record = np.array(svpwm.pwm1_percent_record)
svpwm.pwm2_percent_record = np.array(svpwm.pwm2_percent_record)
svpwm.pwm3_percent_record = np.array(svpwm.pwm3_percent_record)
def graph_pwm_duty(self, duty):
duty_low_half = np.uint32(self.pwm_total_period*(1-duty)/2)
duty_high = self.pwm_total_period - 2*duty_low_half
c = []
a = [0]*duty_low_half
b = [1]*duty_high
c.extend(a)
c.extend(b)
c.extend(a)
return np.array(c)
def plot_gif_init(self):
# 7.8-5.5; 5-3.5
self.fig = plt.figure(figsize=(7.8,5))
self.machine_position_x = np.cos(self.machineAng_record)
self.machine_position_y = np.sin(self.machineAng_record)
self.electric_position_x = np.cos(self.elecAng_record)
self.electric_position_y = np.sin(self.elecAng_record)
pwm1_y = self.graph_pwm_duty(self.pwm1_percent_record[0])
pwm2_y = self.graph_pwm_duty(self.pwm2_percent_record[0])
pwm3_y = self.graph_pwm_duty(self.pwm3_percent_record[0])
plt.subplot(2,3,1)
plt.plot(self.machine_position_x, self.machine_position_y, color='k',ls='-.')
self.mac_pos_point_x_list = []
self.mac_pos_point_y_list = []
self.mac_pos_point, = plt.plot(self.machine_position_x[0], self.machine_position_y[0],color='k', marker='o')
self.mac_pos_vector_line_x_list = []
self.mac_pos_vector_line_y_list = []
self.mac_pos_vector_line, = plt.plot([0,self.machine_position_x[0]], [0, self.machine_position_y[0]], color='k')
plt.ylabel("Machine Angle")
plt.subplot(2,3,4)
plt.plot(self.electric_position_x, self.electric_position_y, color='gray',ls='-.')
self.ele_pos_point_x_list = []
self.ele_pos_point_y_list = []
self.ele_pos_point, = plt.plot(self.electric_position_x[0], self.electric_position_y[0], color='gray', marker='o')
self.ele_pos_vector_line_x_list = []
self.ele_pos_vector_line_y_list = []
self.ele_pos_vector_line, = plt.plot([0,self.electric_position_x[0]], [0, self.electric_position_y[0]], color='gray')
plt.ylabel("Electric Angle")
plt.subplot(3,3,2)
plt.plot(self.elecAng_record, self.pwm1_percent_record, color='r')
self.pwmx_point_x_list = []
self.pwm1_point_y_list = []
self.pwm1_point, = plt.plot(self.elecAng_record[0], self.pwm1_percent_record[0], color='r', marker='o',ls='')
self.pwmx_marker_line_x_list = []
self.pwmx_marker_line_y_list = []
self.pwm1_marker_line, = plt.plot([self.elecAng_record[0], self.elecAng_record[0]], [-0.1, 1.1], color='r', ls='-.', alpha= 0.5)
plt.subplot(3,3,5)
plt.plot(self.elecAng_record, self.pwm2_percent_record, color='g')
self.pwm2_point_y_list = []
self.pwm2_point, = plt.plot(self.elecAng_record[0], self.pwm2_percent_record[0], color='g', marker='o', ls='')
self.pwm2_marker_line, = plt.plot([self.elecAng_record[0], self.elecAng_record[0]], [-0.1, 1.1], color='g', ls='-.', alpha= 0.5)
plt.subplot(3,3,8)
plt.plot(self.elecAng_record, self.pwm3_percent_record, color='b')
self.pwm3_point_y_list = []
self.pwm3_point, = plt.plot(self.elecAng_record[0], self.pwm3_percent_record[0], color='b', marker='o', ls='')
self.pwm3_marker_line, = plt.plot([self.elecAng_record[0], self.elecAng_record[0]], [-0.1, 1.1], color='b', ls='-.', alpha= 0.5)
plt.xlabel("U/V/W Voltage")
plt.subplot(3,3,3)
self.pwm_wave_x_line_x_list = []
self.pwm_wave_1_line_y_list = []
self.pwm_wave_1_line, = plt.plot(self.pwm_wave_x_line, pwm1_y, color='r')
plt.ylim(-0.5,1.5)
plt.subplot(3,3,6)
self.pwm_wave_2_line_y_list = []
self.pwm_wave_2_line, = plt.plot(self.pwm_wave_x_line, pwm2_y, color='g')
plt.ylim(-0.5,1.5)
plt.subplot(3,3,9)
self.pwm_wave_3_line_y_list = []
self.pwm_wave_3_line, = plt.plot(self.pwm_wave_x_line, pwm3_y, color='b')
plt.ylim(-0.5,1.5)
plt.xlabel("SVPWM Duty")
def update_plot(self, num):
##############################################################################
self.mac_pos_point_x_list = self.machine_position_x[num]
self.mac_pos_point_y_list = self.machine_position_y[num]
self.mac_pos_vector_line_x_list = [0, self.machine_position_x[num]]
self.mac_pos_vector_line_y_list = [0, self.machine_position_y[num]]
self.mac_pos_point.set_data(self.mac_pos_point_x_list, self.mac_pos_point_y_list)
self.mac_pos_vector_line.set_data(self.mac_pos_vector_line_x_list, self.mac_pos_vector_line_y_list)
##############################################################################
self.ele_pos_point_x_list = self.electric_position_x[num]
self.ele_pos_point_y_list = self.electric_position_y[num]
self.ele_pos_vector_line_x_list = [0, self.electric_position_x[num]]
self.ele_pos_vector_line_y_list = [0, self.electric_position_y[num]]
self.ele_pos_point.set_data(self.ele_pos_point_x_list, self.ele_pos_point_y_list)
self.ele_pos_vector_line.set_data(self.ele_pos_vector_line_x_list, self.ele_pos_vector_line_y_list)
##############################################################################
# 更新SVPWM波的占空比
self.pwmx_point_x_list = self.elecAng_record[num]
self.pwm1_point_y_list = self.pwm1_percent_record[num]
self.pwm2_point_y_list = self.pwm2_percent_record[num]
self.pwm3_point_y_list = self.pwm3_percent_record[num]
self.pwm1_point.set_data(self.pwmx_point_x_list, self.pwm1_point_y_list)
self.pwm2_point.set_data(self.pwmx_point_x_list, self.pwm2_point_y_list)
self.pwm3_point.set_data(self.pwmx_point_x_list, self.pwm3_point_y_list)
# 更新当前角度在SVPWM波的位置
self.pwmx_marker_line_x_list = [self.elecAng_record[num], self.elecAng_record[num]]
self.pwmx_marker_line_y_list = [-0.1, 1.1]
self.pwm1_marker_line.set_data(self.pwmx_marker_line_x_list, self.pwmx_marker_line_y_list)
self.pwm2_marker_line.set_data(self.pwmx_marker_line_x_list, self.pwmx_marker_line_y_list)
self.pwm3_marker_line.set_data(self.pwmx_marker_line_x_list, self.pwmx_marker_line_y_list)
##############################################################################
# PWM方波
pwm1_y = self.graph_pwm_duty(self.pwm1_percent_record[num])
pwm2_y = self.graph_pwm_duty(self.pwm2_percent_record[num])
pwm3_y = self.graph_pwm_duty(self.pwm3_percent_record[num])
self.pwm_wave_x_line_x_list = self.pwm_wave_x_line
self.pwm_wave_1_line_y_list = pwm1_y
self.pwm_wave_2_line_y_list = pwm2_y
self.pwm_wave_3_line_y_list = pwm3_y
self.pwm_wave_1_line.set_data(self.pwm_wave_x_line_x_list, self.pwm_wave_1_line_y_list)
self.pwm_wave_2_line.set_data(self.pwm_wave_x_line_x_list, self.pwm_wave_2_line_y_list)
self.pwm_wave_3_line.set_data(self.pwm_wave_x_line_x_list, self.pwm_wave_3_line_y_list)
def gen_gif_plot(self, save_path):
ani = anim.FuncAnimation(fig=self.fig, func=self.update_plot, frames=np.arange(1, self.sim_N), interval=10)
# ani.save(save_path)
plt.show()
if __name__ == "__main__":
svpwm = SVPWM_WAVE()
svpwm.motor_record()
svpwm.plot_gif_init()
# plt.show()
svpwm.gen_gif_plot('svpwm.gif')