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 = 1self.Vk = 2/3*self.Udcself.pwm_act_percent = 0.5self.V_ref = np.sqrt(3)/2*self.Vk*self.pwm_act_percentself.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 = Noneself.elecAng = Noneself.elecAng_p = Noneself.sector_no = Noneself.v_theta = Noneself.vector_a = Noneself.vector_b = Noneself.Ta = Noneself.Tb = Noneself.Tv7 = Noneself.pwm1_percent = Noneself.pwm2_percent = Noneself.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 Angleself.machine_position_x = Noneself.machine_position_y = Noneself.electric_position_x = Noneself.electric_position_y = Noneself.fig = Noneself.pwm_total_period = 1000self.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_numdef get_elec_sectorno(self):self.elecAng_p = self.elecAngwhile(self.elecAng>=2*np.pi):self.elecAng = self.elecAng - 2*np.piif(self.elecAng >= 5*np.pi/3):self.sector_no = 5self.vector_a = 5*np.pi/3return 0elif(self.elecAng >= 4*np.pi/3):self.sector_no = 4self.vector_a = 4*np.pi/3return 0elif(self.elecAng >= np.pi):self.sector_no = 3self.vector_a = np.pireturn 0elif(self.elecAng >= 2*np.pi/3):self.sector_no = 2self.vector_a = 2*np.pi/3return 0elif(self.elecAng>= np.pi/3):self.sector_no = 1self.vector_a = np.pi/3return 0elif(self.elecAng>=0):self.sector_no = 0self.vector_a = 0return 0def 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_aself.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)/2def 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 2self.pwm2_percent = self.Tb + self.Tv7 # bit 1self.pwm1_percent = self.Tv7 # bit 0elif(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 2self.pwm2_percent = self.Tb + self.Ta + self.Tv7 # bit 1self.pwm1_percent = self.Tv7 # bit 0elif(self.sector_no == 2):# -0-2-3-7-7-3-2-0-# 2(010) 3(011) 7(111)self.pwm3_percent = self.Tv7 # bit 2self.pwm2_percent = self.Ta + self.Tb + self.Tv7 # bit 1self.pwm1_percent = self.Tb + self.Tv7 # bit 0elif(self.sector_no == 3):# -0-1-3-7-7-3-1-0-# 1(001) 3(011) 7(111)self.pwm3_percent = self.Tv7 # bit 2self.pwm2_percent = self.Ta + self.Tv7 # bit 1self.pwm1_percent = self.Tb + self.Ta + self.Tv7 # bit 0elif(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 2self.pwm2_percent = self.Tv7 # bit 1self.pwm1_percent = self.Ta + self.Tb + self.Tv7 # bit 0elif(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 2self.pwm2_percent = self.Tv7 # bit 1self.pwm1_percent = self.Ta + self.Tv7 # bit 0def motor_record_p(self, t):self.machineAng = t*self.motor_omigaself.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_halfc = []a = [0]*duty_low_halfb = [1]*duty_highc.extend(a)c.extend(b)c.extend(a)return np.array(c)def plot_gif_init(self):# 7.8-5.5; 5-3.5self.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_lineself.pwm_wave_1_line_y_list = pwm1_yself.pwm_wave_2_line_y_list = pwm2_yself.pwm_wave_3_line_y_list = pwm3_yself.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')