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')
    
    
    

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐