Thông báo

Collapse
No announcement yet.

lập trình SPWM cho động cơ AC bằng VHDL

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • lập trình SPWM cho động cơ AC bằng VHDL

    Chào các anh!
    Hôm trước em có hỏi về lập trình PWM nhưng mà em nhầm mất, cái đồ án của em là phải điều chế SPWM tựa sin để điều khiển động cơ AC 1 pha. anh chị nào biết cách làm để điều chế ra SPWM thì hướng dẫn giúp em với ạ. em sắp phải nộp rồi mà chưa điều chế ra được,của em dùng bộ đếm 9 bít.
    EM cảm ơn!

    Hình dạng xung cần điều chế được như thế này:







    Các anh giúp em với, em điều chế mãi mà chả ra. dây là bài của em, các anh xem sai ở chỗ nào

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity taoxungPWM is
    generic (
    pwm_max : integer := 8
    );
    port
    (
    clk,reset,enable : in std_logic ;
    dutyCycle : in std_logic_vector (3 downto 0);
    PWM: out std_logic
    );
    end taoxungPWM;
    architecture Behavioral of taoxungPWM is
    begin
    process (clk,reset,enable)
    variable counter : integer range 0 to pwm_max-1;
    variable counter1 : integer range 0 to pwm_max-1;
    begin
    if (reset='1' )then
    PWM <= '0' ;
    elsif(clk'event and clk = '1') then
    if (enable = '1') then
    if (counter1 < dutyCycle ) then
    counter := counter +1;

    if (counter = 1) then
    PWM <='1' ;
    end if;
    if (counter = 2) then
    PWM <='0';
    end if;
    if (counter = 3 ) then
    PWM <='1';
    end if;
    if (counter = 4 ) then
    PWM <='1';
    end if;
    if (counter = 5 ) then
    PWM <='0';
    end if;
    if (counter = 6 ) then
    PWM <='0';
    end if;
    if (counter = 7 ) then
    PWM <='1';
    end if;
    if (counter = 8 ) then
    PWM <='1';
    end if;

    elsif (counter1 > dutyCycle ) then
    counter := counter - 1;
    if (counter = 7 ) then
    PWM <='1';
    end if;
    if (counter = 6 ) then
    PWM <='0';
    end if;
    if (counter = 5 ) then
    PWM <='0';
    end if;
    if (counter = 4 ) then
    PWM <='1';
    end if;
    if (counter = 3 ) then
    PWM <='1';
    end if;
    if (counter = 2 ) then
    PWM <='0';
    end if;
    if (counter = 1 ) then
    PWM <='1';
    end if;
    end if;

    --/////////////////////
    if (counter1 = pwm_max-1) then
    counter :=0;
    else
    counter1 := counter1 + 1;
    end if;

    if (counter = pwm_max-1) then
    counter :=0;
    else
    counter := counter+1;
    end if;

    end if;
    end if;

    end process ;

    end Behavioral;
    Last edited by FPGA_9572XL; 27-05-2011, 12:44.

  • #2
    Tôi viết thử bằng C++ và code dưới đây chạy khá chuẩn. Bạn dựa theo để viết VHDL nhe.

    Code:
    #define CMAX 8
    void top(bool &out)
    {
    	static int cclk = 0;
    	static int threshold = 0;
    	static bool up = 1;
    	
    	if (cclk <= threshold)
    		out = 1;
    	else
    		out = 0;
    	
    	if (cclk == CMAX-1)
    		cclk = 0;
    	else
    		cclk++;
    	
    	if (cclk ==  CMAX-1)
    	{
    		if (up)
    			threshold++;
    		else
    			threshold--;
    		
    		if (threshold == CMAX-2)
    			up = 0;
    		if (threshold == 0)
    			up = 1;
    	}
    }
    #include <iostream>
    int main(int *argc, char *argv[])
    {
    	bool out;
    	for (int i=0; i<500; i++)
    	{
    		top(out);
    		std::cout << out;
    		if ((i%CMAX)? false : true)
    			std::cout << std::endl;
    	}
    	return(0);
    }
    Bài in ra
    Code:
    00000001
    10000001
    11000001
    11100001
    11110001
    11111001
    11111101
    11111001
    11110001
    11100001
    11000001
    10000001
    00000001
    10000001
    11000001
    11100001
    11110001
    11111001
    11111101
    11111001
    11110001
    11100001
    11000001
    10000001
    00000001
    10000001
    11000001
    11100001
    11110001
    11111001
    11111101
    11111001
    11110001
    11100001
    11000001
    10000001
    00000001
    10000001
    11000001
    11100001
    11110001
    11111001
    11111101
    11111001
    11110001
    11100001
    11000001
    10000001
    00000001
    10000001
    11000001
    11100001
    11110001
    11111001
    11111101
    11111001
    11110001
    11100001
    11000001
    10000001
    Chúc một ngày vui vẻ
    Tony
    email : dientu_vip@yahoo.com

    Comment


    • #3
      Nguyên văn bởi tonyvandinh Xem bài viết
      Tôi viết thử bằng C++ và code dưới đây chạy khá chuẩn. Bạn dựa theo để viết VHDL nhe.

      Code:
      #define CMAX 8
      void top(bool &out)
      {
      	static int cclk = 0;
      	static int threshold = 0;
      	static bool up = 1;
      	
      	if (cclk <= threshold)
      		out = 1;
      	else
      		out = 0;
      	
      	if (cclk == CMAX-1)
      		cclk = 0;
      	else
      		cclk++;
      	
      	if (cclk ==  CMAX-1)
      	{
      		if (up)
      			threshold++;
      		else
      			threshold--;
      		
      		if (threshold == CMAX-2)
      			up = 0;
      		if (threshold == 0)
      			up = 1;
      	}
      }
      #include <iostream>
      int main(int *argc, char *argv[])
      {
      	bool out;
      	for (int i=0; i<500; i++)
      	{
      		top(out);
      		std::cout << out;
      		if ((i%CMAX)? false : true)
      			std::cout << std::endl;
      	}
      	return(0);
      }
      Bài in ra
      Code:
      00000001
      10000001
      11000001
      11100001
      11110001
      11111001
      11111101
      11111001
      11110001
      11100001
      11000001
      10000001
      00000001
      10000001
      11000001
      11100001
      11110001
      11111001
      11111101
      11111001
      11110001
      11100001
      11000001
      10000001
      00000001
      10000001
      11000001
      11100001
      11110001
      11111001
      11111101
      11111001
      11110001
      11100001
      11000001
      10000001
      00000001
      10000001
      11000001
      11100001
      11110001
      11111001
      11111101
      11111001
      11110001
      11100001
      11000001
      10000001
      00000001
      10000001
      11000001
      11100001
      11110001
      11111001
      11111101
      11111001
      11110001
      11100001
      11000001
      10000001
      anh ơi, em chuyển sang VHDL được đến đoạn này rồi, còn đoạn cuối em không chuyển được. anh có thể sửa thêm vào giúp em không a?
      em cám ơn anh nhiều!
      entity SPWM is
      generic ( Cmax : integer :=8
      up : boolean := true
      );

      port ( clk : in std_logic;
      reset : in std_logic;
      enable : in std_logic;
      duty : in std_logic_vector (2 downto 0);
      PWM : out std_logic
      );
      end SPWM;

      architecture Behavioral of SPWM is
      begin
      process (ck)
      variable count : integer ;
      begin
      if ((reset = '1' or (enable = '0')) then
      PWM <= '0';
      else
      if (clk'event and clk ='1') then
      count := count +1;
      if (count <= duty) then
      PWM <= '1''
      else
      PWM <= '0';
      end if;

      --;;;;;;;;;;;;;;;;;;;

      if (count = Cmax-1) then
      count := 0;
      else
      count := count +1;
      end if;

      --;;;;;;;;;;;;;;;;;;;

      if (count = Cmax-1) then
      if (up = '1') then
      duty <= duty+1;
      else
      duty <= duty-1;
      end if;
      if (duty = Cmax - 2) then
      up <= '0';
      end if;
      if (duty = '0') then
      up <= '1';
      end if;





      end Behavioral;

      Comment


      • #4
        Đây là code tôi viết lại bằng VHDL. Nó hơi khác chút đỉnh với code ở C.

        Code:
        library IEEE;
        use IEEE.STD_LOGIC_1164.ALL;
        use IEEE.STD_LOGIC_ARITH.ALL;
        use IEEE.STD_LOGIC_UNSIGNED.ALL;
        
        entity SPWM is 
        	generic ( Cmax : integer :=8);
        
        	port ( 
        		clk : in std_logic;
        		reset : in std_logic;
        		enable : in std_logic;
        		PWM : out std_logic);
        end SPWM;
        
        architecture Behavioral of SPWM is
        	signal cclk : integer range 0 to Cmax;
        	signal threshold : integer range 0 to Cmax;
        	signal up : std_logic;
        	
        begin
        	process (clk, reset)
        	begin
        	if (reset = '1') then
        		PWM <= '0';
        		cclk <= 0;
        		threshold <= 0;
        		up <= '1';
        	elsif (clk'event and clk ='1') then
        		if (enable = '1') then
        			if (cclk <= threshold) then
        				PWM <= '1';
        			else
        				PWM <= '0';
        			end if;
        			
        			if (cclk = Cmax-1) then
        				cclk <= 0;
        			else
        				cclk <= cclk + 1;
        			end if;
        			
        			if (cclk = Cmax-1) then
        				if (threshold = Cmax-3) then
        					up <= '0';	
        				end if;
        				
        				if (threshold = 1) then
        					up <= '1';
        				end if;
        				
        				if (up = '1') then
        					threshold <= threshold + 1;
        				else
        					threshold <= threshold - 1;
        				end if;				
        			end if; -- 
        		end if; --enable
        	end if;
        end process;
        end Behavioral;
        Chúc một ngày vui vẻ
        Tony
        email : dientu_vip@yahoo.com

        Comment


        • #5
          Cám ơn anh nhé,bài của em làm dài lắm, em cũng làm 8bit mà dài tới 2 hay 3 trang ý. Có gi em sẽ hỏi anh nữa, phiền anh
          Last edited by FPGA_9572XL; 27-05-2011, 22:57.

          Comment


          • #6
            Nguyên văn bởi FPGA_9572XL Xem bài viết
            Cám ơn anh nhé,bài của em làm dài lắm, em cũng làm 8bit mà dài tới 2 hay 3 trang ý. Có gi em sẽ hỏi anh nữa, phiền anh
            Tôi thích chỉ cách câu cá hơn là cho cá cho nên bạn cố gắng để học hỏi nhe.
            Chúc một ngày vui vẻ
            Tony
            email : dientu_vip@yahoo.com

            Comment


            • #7
              dạ vâng, em cũng mới chỉ được học cái này có 1 tuần, nên cũng biết không nhiều, có nhiều bài em làm thủ công nên dài lắm, chẳng thấy tối ưu chút nào, những cách làm của a thật dể hiểu và rất ngắn gọn, nó giúp cho em học được rất nhiều.Cám ơn anh!

              Comment


              • #8
                Nguyên văn bởi FPGA_9572XL Xem bài viết
                dạ vâng, em cũng mới chỉ được học cái này có 1 tuần, nên cũng biết không nhiều, có nhiều bài em làm thủ công nên dài lắm, chẳng thấy tối ưu chút nào, những cách làm của a thật dể hiểu và rất ngắn gọn, nó giúp cho em học được rất nhiều.Cám ơn anh!
                Dễ hiểu hơn có lẽ vì tôi mô phỏng bằng C trước. C có cấu chúc tuần tự (sequential), còn VHDL dựa vào sự kiện (event). VHDL đòi hỏi cách suy nghĩ đồng bộ cho nên khó hiểu hơn nếu không có nhiều kinh nghiệm
                Chúc một ngày vui vẻ
                Tony
                email : dientu_vip@yahoo.com

                Comment


                • #9
                  anh ơi cho em hỏi cách tính được tần số xung CK đầu vào cái, board thực tập của em dùng board spartand 3, tần số thạch anh là 50Mhz.
                  Nếu em muốn tạo ra tần số từ 0-50Hz từ tần số xung ck dao động của board thì phải làm như thế nào ạ?
                  Anh hướng dẫn cho em với.

                  Comment


                  • #10
                    Nguyên văn bởi FPGA_9572XL Xem bài viết
                    anh ơi cho em hỏi cách tính được tần số xung CK đầu vào cái, board thực tập của em dùng board spartand 3, tần số thạch anh là 50Mhz.
                    Nếu em muốn tạo ra tần số từ 0-50Hz từ tần số xung ck dao động của board thì phải làm như thế nào ạ?
                    Anh hướng dẫn cho em với.
                    Tôi không rành về board Spartant 3 nên không biết nó có cho ra xung clk và ở tầng số nào. Nếu bạn có schematic thì up lên đây, hy vọng tôi có thể cho ý kiến
                    Chúc một ngày vui vẻ
                    Tony
                    email : dientu_vip@yahoo.com

                    Comment


                    • #11
                      đây là code và schematic cua em
                      entity Chontanso is
                      port (
                      clk_in:in std_logic ;
                      tanso : in std_logic_vector(2 downto 0);
                      clk : out std_logic
                      );
                      end Chontanso;

                      --tan so dao dong dau vao la tu 1khz den 10 khz

                      architecture Behavioral of Chontanso is
                      signal clk_out: std_logic;
                      signal dem : std_logic_vector (13 downto 0);
                      begin
                      process(clk_in,tanso,clk_out,dem)
                      begin
                      if (clk_in'event and clk_in = '1') then
                      dem <= dem +1;
                      end if;

                      case tanso is
                      when "000" => clk_out <= clk_in; --- tan so dao dong dau vao
                      when "001" => clk_out <= dem(7); --- 1/(2^8)clk_in = 50Hz
                      when "010" => clk_out <= dem(8);
                      when "011" => clk_out <= dem(9);
                      when "100" => clk_out <= dem(10);
                      when "101" => clk_out <= dem(11);
                      when "110" => clk_out <= dem(12);
                      when "111" => clk_out <= dem(13);
                      when others =>clk_out <= clk_in;
                      end case;
                      clk <= clk_out;
                      end process;
                      end Behavioral;
                      schematic của khối chon tần số (chia xung)



                      schematic của cả bài toán



                      ý của em là sẽ điều chỉnh tần số đầu vào dưới dang vô cấp bằng cách sẽ sử dụng 1 IC dao động (4060 hay LM 331)tạo dao động tần số đầu vào từ 1Khz đến 10khz sau đó chia tần đó ra theo các cấp khác nhau qua bộ "chọn tần sô" để lấy ra được tần số mong muốn trong dải từ 1Hz đến 50Hz bằng cách điều chỉnh biến trở. để từ đó ta lấy xug ck đưa vào các bộ tạo PWM có duty = 50% và ck của bộ tạo ra SPWM. Sau đó ta nhân PWM và SPWM qua cổng "and" để lấy ra SPWM1 để điều khiển 1 vế của mạch cầu H. Vế còn lại là SPWM2 được lấy từ đảo (not) của PWM nhân với SPWM qua cổng "and".

                      Nhưng mà khi em mô phỏng thì lại không có được xug ck sau bộ chọn tần.

                      Comment


                      • #12
                        Để chọn tầng số từ 1hz tới 50 hz, cần 6 bits (2^6=64). Để bảo đảm có 50% duty cycle, chỉ cần chia đôi, vì vậy bạn cần đường vào với tầng số có thể chia chẵn từ 1 tới 50. Bạn có thể phải cần nhiều tầng số vào khác nhau
                        1) Bộ đếm từ 0 tới 49.
                        if (count = 49) then
                        count <= 0;
                        else
                        count <= count+1;
                        end if;
                        2) Khi bộ đếm bằng tầng số chọn thì cho ra '1', ngoài ra thì cho ra '0'
                        if (conv_std_logic_vector(count,6) = tanso) then
                        clkx2 <= '1';
                        else
                        clkx2 <= '0';
                        end if;
                        3) Bộ chia đôi sẽ đổi chiều mỗi khi thấy đường ra trước là 1.
                        if (clkx2 = '1') then
                        clkout <= ~clkout;
                        end if;
                        Last edited by tonyvandinh; 31-05-2011, 11:45.
                        Chúc một ngày vui vẻ
                        Tony
                        email : dientu_vip@yahoo.com

                        Comment


                        • #13
                          Bạn theo thread dưới đây để tìm hiểu thêm nhe.

                          http://www.dientuvietnam.net/forums/...ock?highlight=
                          Chúc một ngày vui vẻ
                          Tony
                          email : dientu_vip@yahoo.com

                          Comment


                          • #14
                            Cái đó khó hiểu quá, em đọc 5 lần rồi mà vẫn không hiểu. Em muốn là tần số thay đổi tử 1 đến 50hz khi ta chỉnh biến trở của mạch tạo xung clock input. Có lẽ em nên làm theo cách đếm xung và chia tần thôi, với tần số đầu vào có thể thay đổi từ 300hz (tương ứng 1 Hz đầu ra) đến 13Khz (tương ứng 50 Hz đầu ra). mặc dù clock không đẹp nhưng e nghĩ là có thể điều khiển được thằng động cơ AC 1 phase này. vì hnay em thử napk vào board thì vẫn thấy chia được xung anh a`. nhưng mà em chưa thử điều khiển mạch cầu vì còn sợ nó mà không ổn định thì ra đi cái động cơ mất.

                            Comment


                            • #15
                              Ví dụ tôi chọn tầng số vào là 3200hz (64x50). Số 64 ở đây là vì sẽ dự định chia cho 64 để duty cycle ít sai số hơn.

                              Cho đường ra 1hz thì cần phải nhân cho 64 và chia cho 3200

                              Code:
                              out (hz)     N       D
                              1              1        50
                              2              2        50
                              3              3        50
                              4              4        50
                              ...
                              Dựa vào đề tài chia lẻ mà tôi hướng dẫn ở trên, bạn có thể chỉ cần tần số vào là 6 bits (N). Số chia có thể hard code là 50

                              1) Reset R=0 (R : remainder)
                              2) R = R+N (N : tầng số chọn) - 1 tới 50
                              3) if (R<50) then
                              clkx64 <= '0';
                              else
                              clkx64 <= '1';
                              R = R-50;
                              end if;
                              4) Lấy clkx64 làm xung enable cho khối chia 64
                              5) Lấy bit cuối (MSB) của bộ đếm của chia 64 làm xung ra

                              Độ sai chu kỳ sẽ là 1/64%. Nếu bạn muốn ít hơn thì tăng tần số vào lên rồi chia đều ra trở lại. Ví dụ 6400hz và chiacho 128
                              Last edited by tonyvandinh; 01-06-2011, 05:06.
                              Chúc một ngày vui vẻ
                              Tony
                              email : dientu_vip@yahoo.com

                              Comment

                              Về tác giả

                              Collapse

                              FPGA_9572XL Tìm hiểu thêm về FPGA_9572XL

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X