目次
前
次
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度導通型では、パルスの出力パターンは
以下となります。
- 0x19 (0 1 1 0 0 1)
- 0x29 (1 0 1 0 0 1)
- 0x25 (1 0 0 1 0 1)
- 0x26 (1 0 0 1 1 0)
- 0x16 (0 1 0 1 1 0)
- 0x1C (0 1 1 1 0 0)
120度導通型では、パルスの出力パターンは
以下となります。
- 0x09 (0 0 1 0 0 1)
- 0x21 (1 0 0 0 0 1)
- 0x24 (1 0 0 1 0 0)
- 0x06 (0 0 0 1 1 0)
- 0x12 (0 1 0 0 1 0)
- 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ビットの値反転
- カウント値が0なら3に遷移
- カウント値に−1を加えて、2に遷移
- 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;
目次
前
次