目次

3相誘導電動機処理

 3相誘導電動機を動かすためには、次のブロック図を
 見て、始動処理、速度制御を考えます。



 左が交流→直流のコンバータで、右が直流→交流のインバータです。

 コンバータには、ダイオードアレイを利用します。
 3相誘導電動機に利用するコンバータは、ディスクリートで
 組むことはなく、下のようなユニットを使います。



 インバータには、パワーMOSFETアレイを利用します。
 3相誘導電動機のパワーにより、コンバータの写真に
 あるようなユニットを使うこともあります。



 誘導電動機の回転数は、電動機に供給する電源周波数に
 比例します。回転数は、次式で求めることができます。

  N = (120 x f) / P

   N:回転数 f:周波数(Hz) P:極数

 回転数制御には、電動機に供給する電源周波数を変えます。
 電源側をインバータにすると、速度を制御する可変速制御と
 呼ばれている方式になります。

 インバーターによる速度制御の範囲は広く、 5〜100%の
 安定した速度を得られるので、最近の3相誘導電動機の
 速度制御は、ほぼインバータ制御です。

 かご形三相誘導電動機の制御方式は、ほぼインバータ制御です。


インバーター制御

 3相インバータのスイッチング方式は、つぎの2方式  があります。  180度導通型のインバータで、スイッチングすると  次のタイミングチャートになります。  180度ごとに、3相誘導電動機に与える電圧を切替えて  いきます。  半導体のスイッチングでは、逆起電力発生を見込んで  ONディレイを入れ、3相誘導電動機のU、V、W相と中点N  の電圧の関係は、下図となります(1相分)。  120度導通型のインバータで、スイッチングすると  次のタイミングチャートになります。  120度ごとに、3相誘導電動機に与える電圧を切替えて  いきます。3相誘導電動機のU、V、W相と中点Nの電圧の  関係は、下図となります(1相分)。  180度導通型と異なり、120度の後の60度にOFFを入れる  ので、ONディレイを挟まないでよくなります。  60度の区間に、中間電圧が発生します。  180度導通型と120度導通型のスイッチングパルスを  発生するファームウエアを考えます。  2つの導通のパターンを拾い出します。  180度導通型では、パルスの出力パターンは  以下となります。
  1. 0x19 (0 1 1 0 0 1)
  2. 0x29 (1 0 1 0 0 1)
  3. 0x25 (1 0 0 1 0 1)
  4. 0x26 (1 0 0 1 1 0)
  5. 0x16 (0 1 0 1 1 0)
  6. 0x1C (0 1 1 1 0 0)
 120度導通型では、パルスの出力パターンは  以下となります。
  1. 0x09 (0 0 1 0 0 1)
  2. 0x21 (1 0 0 0 0 1)
  3. 0x24 (1 0 0 1 0 0)
  4. 0x06 (0 0 0 1 1 0)
  5. 0x12 (0 1 0 0 1 0)
  6. 0x18 (0 1 1 0 0 0)
 マイコンのポートBから、パルスを出力する  仕様で、ファームウエアを考えます。  マイコンとしてATtiny2313を利用するとして  ていねいに作成していきます。  ポートBを出力に設定するので、初期値と  方向設定します。  PORTB = 0b00000000 ; /* 00000000 */  DDRB = 0b11111111 ; /* oooooooo */  ポートDに、120度導通と180度導通を  選べるようにスイッチを用意します。  ポートDを入力に設定するので、初期値と  方向設定します。  PORTD = 0b11110000 ; /* 11110000 */  DDRD = 0b00001111 ; /* iiiioooo */  上位4ビット(物理上は3ビット)を入力に  設定し、内蔵プルアップ抵抗を使います。  PD4に、120度導通と180度導通の指定スイッチ  を接続し、PD5にパルス出力するかどうかを  指定するスイッチを接続します。  タイマー割込みを利用し、パルス出力を制御します。  タイマー割込み発生のトリガーを捕らえて、ポートB  にビットパターンを出力する仕様にします。 if ( tflag ) { tflag = OFF ; /* get mode */ ptr = pat180 ; if ( PIND & 0x10 ) { ptr = pat120 ; } /* get bit pattern */ bport = *(ptr+state); /* judge */ if ( !(PIND & 0x20) ) { bport = 0x00 ; } /* impress */ PORTB = bport ; /* update state */ state++ ; if ( state == PAT_MAX ) { state = 0 ; } }  120度導通か180度導通かを判定し、ビットパターンを  配列領域から取り出します。配列があるので、添字を  stateとして、stateは0〜5を繰返すように構成して  います。  ENABLEが1でパルスを出力し、0で出力はすべて0に  します。  周波数可変の前に、固定周波数でパルス出力が  設計通りかを確認するファームウエアのソース  は以下です(周波数は、12MHz)。 #include <avr/io.h> #include <avr/interrupt.h> #define OFF 0 #define ON OFF+1 typedef unsigned char UBYTE ; typedef unsigned short UWORD ; typedef signed char SBYTE ; typedef signed short SWORD ; volatile UBYTE tflag ; /* timer interrupt flag */ volatile UBYTE *ptr ; /* bit pattern pointer */ volatile UBYTE state ; /* state */ volatile UBYTE bport ; /* temporary */ #define NO 0 #define YES NO+1 #define MASKFF 0xff #define MASK0F 0x0f #define MASKF0 0xf0 #define PAT_MAX 6 volatile UBYTE pat120[PAT_MAX] = {0x09,0x21,0x24,0x06,0x12,0x18} ; volatile UBYTE pat180[PAT_MAX] = {0x19,0x29,0x25,0x26,0x16,0x1A} ; /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); /*------*/ /* main */ /*------*/ int main(void) { /* initialize port and variables */ user_initialize(); /* enable interrupt */ sei(); /* endless loop */ while ( ON ) { /* timer handling */ if ( tflag ) { tflag = OFF ; /* get mode */ ptr = pat180 ; if ( PIND & 0x10 ) { ptr = pat120 ; } /* get bit pattern */ bport = *(ptr+state); /* judge */ if ( !(PIND & 0x20) ) { bport = 0x00 ; } /* impress */ PORTB = bport ; /* update state */ state++ ; if ( state == PAT_MAX ) { state = 0 ; } } } /* dummy */ return 0 ; } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ void user_initialize(void) { /* PORT B */ PORTB = 0b00000000 ; /* 00000000 */ DDRB = 0b11111111 ; /* oooooooo */ /* PORT D */ PORTD = 0b11110000 ; /* 11110000 */ DDRD = 0b00001111 ; /* iiiioooo */ /* initialize flags */ tflag = OFF ; ptr = pat180 ; state = 0 ; bport = 0 ; /* initialize timer/counter1 */ { /* compare match (1/8) -> 500kHz */ TCCR1B = (1 << WGM12) | (1 << CS10) ; TCNT1 = 0 ; OCR1A = 29999 ; OCR1B = 60000 ; } /* set TIMER1 interrupt */ TIMSK = (1 << OCIE1A) ; } /* timer1 interrupt */ ISR(TIMER1_COMPA_vect) { tflag = ON ; }  ファームウエアは、ソフトウエアでのパルス出力ですが  ハードウエアによるパルス出力も可能です。  ハードウエアによるパルス出力のブロック図を  描いて、ハードウエアを考えます。  VHDLでパルス出力するコードは、以下。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity tptst is port ( -- system CLOCK : in std_logic; nRESET : in std_logic; -- input SEL120 : in std_logic ; ENABLE : in std_logic ; -- output POUT : out std_logic_vector(5 downto 0) -- ; ); end tptst ; architecture Behavioral of tptst is signal iSTATE : std_logic_vector(2 downto 0) ; signal iPOUT : std_logic_vector(5 downto 0) ; begin -- output POUT <= iPOUT when ( ENABLE = '1' ) else (others => '0') ; -- internal decoder iPOUT <= "001001" when ( iSTATE = "000" and SEL120 = '1' ) else -- 0x09 "100001" when ( iSTATE = "001" and SEL120 = '1' ) else -- 0x21 "100100" when ( iSTATE = "011" and SEL120 = '1' ) else -- 0x24 "000110" when ( iSTATE = "111" and SEL120 = '1' ) else -- 0x06 "010010" when ( iSTATE = "110" and SEL120 = '1' ) else -- 0x12 "011000" when ( iSTATE = "100" and SEL120 = '1' ) else -- 0x18 "011001" when ( iSTATE = "000" and SEL120 = '0' ) else -- 0x19 "101001" when ( iSTATE = "001" and SEL120 = '0' ) else -- 0x29 "100101" when ( iSTATE = "011" and SEL120 = '0' ) else -- 0x25 "100110" when ( iSTATE = "111" and SEL120 = '0' ) else -- 0x26 "010110" when ( iSTATE = "110" and SEL120 = '0' ) else -- 0x16 "011010" when ( iSTATE = "100" and SEL120 = '0' ) else -- 0x1A "000000" ; -- sequencer process (nRESET,CLOCK) begin if ( nRESET = '0' ) then iSTATE <= "000" ; elsif rising_edge( CLOCK ) then case conv_integer( iSTATE ) is when 0 => iSTATE <= "001" ; when 1 => iSTATE <= "011" ; when 3 => iSTATE <= "111" ; when 7 => iSTATE <= "110" ; when 6 => iSTATE <= "100" ; when 4 => iSTATE <= "000" ; when others => iSTATE <= "000" ; end case ; end if ; end process ; end Behavioral;  デジタル回路、ファームウエアでパルス出力部分を  構成できたので、パルスの出力周波数を可変にする  方法を考えます。  デジタル回路のカウンタを利用し、0~100Hzのクロック  を生成してみます。100Hzの1000倍である、100kHzを使い  カウント値を可変し、パルスのHとLの時間を調整する  方式で周波数を制御します。  パルスのHとLを、指定時間分だけを生成するシーケンス  処理を考えると、以下。
  1. カウント値設定、1ビットの値反転
  2. カウント値が0なら3に遷移
  3. カウント値に−1を加えて、2に遷移
  4. 1に遷移
 デジタル回路をFPGA、CPLD内に入れるために  VHDLコードを記述します。 process (nRESET,iPCLK) begin if ( nRESET = '0' ) then iSCNT <= 0 ; iMCLK <= '0' ; iCNTX <= (others => '0'); elsif rising_edge(iPCLK) then case iSCNT is -- set counter when 0 => iSCNT <= 1 ; iCNTX <= iCNT ; iMCLK <= not iMCLK ; -- decrement when 1 => if ( conv_integer(iCNTX) = 0 ) then iSCNT <= 2 ; else iCNTX <= iCNTX - '1' ; end if ; -- return first state when 2 => iSCNT <= 0 ; -- default when others => iSCNT <= 0 ; end case ; end if ; end process ;  指定時間に相当するカウント値は、デコーダで記述します。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity divcntx is port ( -- input DIN : in std_logic_vector(6 downto 0) ; -- output DOUT : out std_logic_vector(15 downto 0) --; ); end divcntx; architecture Behavioral of divcntx is signal iDOUT : std_logic_vector(15 downto 0); begin -- output DOUT <= iDOUT ; -- convert iDOUT <= X"C350" when ( conv_integer(DIN) = 1 ) else X"61A8" when ( conv_integer(DIN) = 2 ) else X"411A" when ( conv_integer(DIN) = 3 ) else X"30D4" when ( conv_integer(DIN) = 4 ) else X"2710" when ( conv_integer(DIN) = 5 ) else X"208D" when ( conv_integer(DIN) = 6 ) else X"1BE6" when ( conv_integer(DIN) = 7 ) else X"186A" when ( conv_integer(DIN) = 8 ) else X"15B3" when ( conv_integer(DIN) = 9 ) else X"1388" when ( conv_integer(DIN) = 10 ) else X"11C1" when ( conv_integer(DIN) = 11 ) else X"1046" when ( conv_integer(DIN) = 12 ) else X"0F06" when ( conv_integer(DIN) = 13 ) else X"0DF3" when ( conv_integer(DIN) = 14 ) else X"0D05" when ( conv_integer(DIN) = 15 ) else X"0C35" when ( conv_integer(DIN) = 16 ) else X"0B7D" when ( conv_integer(DIN) = 17 ) else X"0AD9" when ( conv_integer(DIN) = 18 ) else X"0A47" when ( conv_integer(DIN) = 19 ) else X"09C4" when ( conv_integer(DIN) = 20 ) else X"094C" when ( conv_integer(DIN) = 21 ) else X"08E0" when ( conv_integer(DIN) = 22 ) else X"087D" when ( conv_integer(DIN) = 23 ) else X"0823" when ( conv_integer(DIN) = 24 ) else X"07D0" when ( conv_integer(DIN) = 25 ) else X"0783" when ( conv_integer(DIN) = 26 ) else X"073B" when ( conv_integer(DIN) = 27 ) else X"06F9" when ( conv_integer(DIN) = 28 ) else X"06BC" when ( conv_integer(DIN) = 29 ) else X"0682" when ( conv_integer(DIN) = 30 ) else X"064C" when ( conv_integer(DIN) = 31 ) else X"061A" when ( conv_integer(DIN) = 32 ) else X"05EB" when ( conv_integer(DIN) = 33 ) else X"05BE" when ( conv_integer(DIN) = 34 ) else X"0594" when ( conv_integer(DIN) = 35 ) else X"056C" when ( conv_integer(DIN) = 36 ) else X"0547" when ( conv_integer(DIN) = 37 ) else X"0523" when ( conv_integer(DIN) = 38 ) else X"0502" when ( conv_integer(DIN) = 39 ) else X"04E2" when ( conv_integer(DIN) = 40 ) else X"04C3" when ( conv_integer(DIN) = 41 ) else X"04A6" when ( conv_integer(DIN) = 42 ) else X"048A" when ( conv_integer(DIN) = 43 ) else X"0470" when ( conv_integer(DIN) = 44 ) else X"0457" when ( conv_integer(DIN) = 45 ) else X"043E" when ( conv_integer(DIN) = 46 ) else X"0427" when ( conv_integer(DIN) = 47 ) else X"0411" when ( conv_integer(DIN) = 48 ) else X"03FC" when ( conv_integer(DIN) = 49 ) else X"03E8" when ( conv_integer(DIN) = 50 ) else X"03D4" when ( conv_integer(DIN) = 51 ) else X"03C1" when ( conv_integer(DIN) = 52 ) else X"03AF" when ( conv_integer(DIN) = 53 ) else X"039D" when ( conv_integer(DIN) = 54 ) else X"038D" when ( conv_integer(DIN) = 55 ) else X"037C" when ( conv_integer(DIN) = 56 ) else X"036D" when ( conv_integer(DIN) = 57 ) else X"035E" when ( conv_integer(DIN) = 58 ) else X"034F" when ( conv_integer(DIN) = 59 ) else X"0341" when ( conv_integer(DIN) = 60 ) else X"0333" when ( conv_integer(DIN) = 61 ) else X"0326" when ( conv_integer(DIN) = 62 ) else X"0319" when ( conv_integer(DIN) = 63 ) else X"030D" when ( conv_integer(DIN) = 64 ) else X"0301" when ( conv_integer(DIN) = 65 ) else X"02F5" when ( conv_integer(DIN) = 66 ) else X"02EA" when ( conv_integer(DIN) = 67 ) else X"02DF" when ( conv_integer(DIN) = 68 ) else X"02D4" when ( conv_integer(DIN) = 69 ) else X"02CA" when ( conv_integer(DIN) = 70 ) else X"02C0" when ( conv_integer(DIN) = 71 ) else X"02B6" when ( conv_integer(DIN) = 72 ) else X"02AC" when ( conv_integer(DIN) = 73 ) else X"02A3" when ( conv_integer(DIN) = 74 ) else X"029A" when ( conv_integer(DIN) = 75 ) else X"0291" when ( conv_integer(DIN) = 76 ) else X"0289" when ( conv_integer(DIN) = 77 ) else X"0281" when ( conv_integer(DIN) = 78 ) else X"0278" when ( conv_integer(DIN) = 79 ) else X"0271" when ( conv_integer(DIN) = 80 ) else X"0269" when ( conv_integer(DIN) = 81 ) else X"0261" when ( conv_integer(DIN) = 82 ) else X"025A" when ( conv_integer(DIN) = 83 ) else X"0253" when ( conv_integer(DIN) = 84 ) else X"024C" when ( conv_integer(DIN) = 85 ) else X"0245" when ( conv_integer(DIN) = 86 ) else X"023E" when ( conv_integer(DIN) = 87 ) else X"0238" when ( conv_integer(DIN) = 88 ) else X"0231" when ( conv_integer(DIN) = 89 ) else X"022B" when ( conv_integer(DIN) = 90 ) else X"0225" when ( conv_integer(DIN) = 91 ) else X"021F" when ( conv_integer(DIN) = 92 ) else X"0219" when ( conv_integer(DIN) = 93 ) else X"0213" when ( conv_integer(DIN) = 94 ) else X"020E" when ( conv_integer(DIN) = 95 ) else X"0208" when ( conv_integer(DIN) = 96 ) else X"0203" when ( conv_integer(DIN) = 97 ) else X"01FE" when ( conv_integer(DIN) = 98 ) else X"01F9" when ( conv_integer(DIN) = 99 ) else X"01F4" when ( conv_integer(DIN) = 100 ) else X"0000" ; end Behavioral;  16進データは、Tcl/Tkを利用して作成しました。  Tcl/Tkのコードは、以下です。 set fosc 50000 for {set i 1} {$i < 102} {incr i} { # calculate if { $i < 101 } { set tmp [expr $fosc / $i] set tmp [format " X\"%04X\" when ( conv_integer(DIN) = %d ) else " $tmp $i] } else { set tmp " X\"0000\" ;" } # show puts $tmp }  DIPスイッチで、0~100Hzを0~100の2進数で設定し  120度導通か180度導通のパルス出力するVHDLコード  は、以下です。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity invtst is generic ( TOPX : integer := 8 ; XMAX : integer := 239 --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- counter input ADR : in std_logic_vector(6 downto 0) ; -- pulse output POUT : out std_logic_vector(5 downto 0) ; -- input SEL120 : in std_logic ; ENABLE : in std_logic ; -- monitor MADR : out std_logic_vector(6 downto 0) ; MCLK : out std_logic --; ); end invtst ; architecture Behavioral of invtst is -- component clock generator component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; -- component divide counter component divcntx is port ( -- input DIN : in std_logic_vector(6 downto 0) ; -- output DOUT : out std_logic_vector(15 downto 0) --; ); end component ; -- clock signal iPCLK : std_logic ; signal iMCLK : std_logic ; -- divide counter signal iADR : std_logic_vector( 6 downto 0) ; signal iCNT : std_logic_vector(15 downto 0) ; signal iSCNT : integer range 0 to 2 ; signal iCNTX : std_logic_vector(15 downto 0) ; -- sequencer signal iPOUT : std_logic_vector(5 downto 0) ; signal iSTATE : std_logic_vector(2 downto 0) ; begin -- component clock generator (48MHz/480 = 100kHz) CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,CLOCK,iPCLK); -- divide counter DIVX : divcntx port map (iADR,iCNT) ; -- input iADR <= ADR ; -- output POUT <= iPOUT when ( ENABLE = '1' ) else (others => '0') ; -- monitor MCLK <= iPCLK ; MADR <= not iADR ; -- internal decoder iPOUT <= "001001" when ( iSTATE = "000" and SEL120 = '1' ) else -- 0x09 "100001" when ( iSTATE = "001" and SEL120 = '1' ) else -- 0x21 "100100" when ( iSTATE = "011" and SEL120 = '1' ) else -- 0x24 "000110" when ( iSTATE = "111" and SEL120 = '1' ) else -- 0x06 "010010" when ( iSTATE = "110" and SEL120 = '1' ) else -- 0x12 "011000" when ( iSTATE = "100" and SEL120 = '1' ) else -- 0x18 "011001" when ( iSTATE = "000" and SEL120 = '0' ) else -- 0x19 "101001" when ( iSTATE = "001" and SEL120 = '0' ) else -- 0x29 "100101" when ( iSTATE = "011" and SEL120 = '0' ) else -- 0x25 "100110" when ( iSTATE = "111" and SEL120 = '0' ) else -- 0x26 "010110" when ( iSTATE = "110" and SEL120 = '0' ) else -- 0x16 "011010" when ( iSTATE = "100" and SEL120 = '0' ) else -- 0x1A "000000" ; -- sequencer process (nRESET,iMCLK) begin if ( nRESET = '0' ) then iSTATE <= "000" ; elsif rising_edge( iMCLK ) then case conv_integer( iSTATE ) is when 0 => iSTATE <= "001" ; when 1 => iSTATE <= "011" ; when 3 => iSTATE <= "111" ; when 7 => iSTATE <= "110" ; when 6 => iSTATE <= "100" ; when 4 => iSTATE <= "000" ; when others => iSTATE <= "000" ; end case ; end if ; end process ; -- generate clock process (nRESET,iPCLK) begin if ( nRESET = '0' ) then iSCNT <= 0 ; iMCLK <= '0' ; iCNTX <= (others => '0'); elsif rising_edge(iPCLK) then case iSCNT is -- set counter when 0 => iSCNT <= 1 ; iCNTX <= iCNT ; iMCLK <= not iMCLK ; -- decrement when 1 => if ( conv_integer(iCNTX) = 0 ) then iSCNT <= 2 ; else iCNTX <= iCNTX - '1' ; end if ; -- return first state when 2 => iSCNT <= 0 ; -- default when others => iSCNT <= 0 ; end case ; end if ; end process ; end Behavioral;

目次

inserted by FC2 system