MSP430G2553 - PWM制御
概要
PWM (Pulse Width Modulation, パルス幅変調) は、電力を制御するための技術である。
PWMMは、ON / OFFを高速で切り替えることにより、平均電力を制御したり、パルスのデューティ比 (ON時間とOFF時間の比率) を変えることで出力を調整することができる。
DCモータの速度制御、LEDの調光制御、ヒータ等の温度制御、オーディオ信号の増幅 (Class Dアンプ)等にPWM制御の技術が利用されている。
PWMの特徴を以下に示す。
- デジタル信号 (ON / OFF) で制御可能なため、マイコン等で容易に実装できる。
- 効率が良く、電力損失が少ない。
- モータの速度制御、LEDの調光制御等に広く利用されている。
PWMの利点を以下に示す。
- シンプルな制御方式で、コストが低い。
- 高効率で、電力損失が少ない。
- デジタル制御が可能で、マイコンとの親和性が高い。
PWMは、シンプルな原理でありながら、幅広い分野で活用されている重要な技術である。
デューティ比を変化させることにより出力を連続的に制御できるため、様々な用途に適している。
PWMの周波数とデューティ比
PWMの周波数とデューティ比は、PWM信号の特性を決定する重要な要素である。
PWMの周波数とデューティ比を適切に設定することにより、効率的かつ高精度な制御が可能になる。
用途に応じて最適な値を選択することが重要である。
PWMの周波数
PWMの周波数は、1秒間のパルスの数を表す。 (単位は[Hz])
周波数が高いほど、ON / OFFの切り替えが速くなる。
周波数が高すぎる場合は、制御対象 (モータやLED等) が応答しきれなくなる場合がある。
周波数が低すぎる場合は、制御対象の動作が粗くなったり、ノイズが発生したりすることがある。
適切な周波数は、制御対象や用途によって異なる。
デューティ比
デューティ比は、1周期におけるON時間の割合を表しており、0~100%の範囲で表現される。
デューティ比が0%の場合、常にOFF状態となり、出力は最小 (0) になる。
デューティ比が100%の場合、常にON状態となり、出力は最大になる。
デューティ比を変化させることにより、出力を連続的に制御できる。
周波数とデューティ比の関係
周波数が一定の場合、デューティ比を変化させることにより、平均電力を制御できる。
デューティ比が大きいほどON時間が長くなるため、平均電力が増加する。
周波数が高いほど、デューティ比の変化に対する応答性が向上する。
具体例
- DCモータの速度制御の場合、周波数を数[kHz]~数十[kHz]に設定して、デューティ比を変化させて速度を制御する。
- LEDの調光制御の場合、周波数を数百[Hz]~数[kHz]に設定して、デューティ比を変化させて明るさを調整する。
注意点
- 制御対象により、適切な周波数とデューティ比の範囲が異なる。
- 周波数が高すぎると、スイッチング損失が増加して、効率が低下する場合がある。
- デューティ比が0%や100%に近づくと、制御の分解能が低下する。
デューティ比の計算
クロックが1.1[MHz]の場合、TA0CCR0レジスタの値を999、TA0CCR1レジスタの値を100に設定することにより、デューティ比を10%に設定することができる。
ただし、クロックが16[MHz]の場合、TA0CCR0レジスタに15999999を代入することはできない。
MSP430G2553のタイマA0は、16ビットタイマであり、最大値は65535 (0xFFFF) だからである。
したがって、16[MHz]のクロックを使用する場合、以下に示すようにTA0CCR0レジスタとTA0CCR1レジスタの値を設定することができる。
// タイマA0の設定
TA0CTL = TASSEL_2 | MC_1 | ID_3; // SMCLK (16[MHz]), アップモード, 分周 1/8 = 2[MHz]のクロックを生成
TA0CCR0 = 20000 - 1; // PWM周期を1[mS] (1[kHz]) に設定
TA0CCR1 = 2000; // デューティ比を10%に設定
上記の設定では、以下のように計算される。
このように、クロックが16[MHz]の場合は、分周器を使用してクロックを分周して、適切なTA0CCR0とTA0CCR1の値を設定することにより、目的のPWM周期とデューティ比を達成することができる。
また、上記のサンプルコードでは、、タイマA0のクロックソースとしてSMCLK (Sub-Main Clock) を選択している。
SMCLKは、DCOを分周して生成されるクロックであり、タイマや周辺機器のクロックとして使用されるクロックである。
TA0CTL = TASSEL_2 | MC_1 | ID_0; // SMCLK (1MHz), アップモード, 分周なし
ここで、TASSEL_2レジスタはクロックソース選択ビットであり、以下のように定義されている。
- TASSEL_0
- TAxCLK (外部クロック)
- TASSEL_1
- ACLK (補助クロック、32.768[kHz])
- TASSEL_2
- SMCLK (サブメインクロック、DCOを分周)
- TASSEL_3
- INCLK (外部クロック)
一方、MCLK (Main Clock) は、CPUやその他の一部の周辺機器のクロックとして使用される。
MCLKは、DCOを直接使用する、または、DCOを分周して生成される。
デフォルトではDCOが1.1[MHz]に設定されており、SMCLKとMCLKはこの周波数で動作する。
ただし、DCOの周波数を変更することにより、SMCLKとMCLKの周波数を変更することができる。
サンプルコード : LEDの調光制御
以下の例では、タイマA0を使用してPWM信号を生成して、LEDの明るさを制御している。
PWM周期を1[mS] (1[kHz]) に設定して、デューティ比は50%に設定している。
LEDは、MSP430G2553マイコンのP1.6に接続している。
- ウォッチドッグタイマを停止する。
- LEDに接続しているピンP1.6を出力に設定する。
- タイマA0を設定する。
- 以下の例で使用しているPWM制御の設定を示す。
- SMCLK (1[MHz]) を選択する。
- アップモードで動作する。
- 分周なし。
- PWM周期を1[ms] (1[kHz]) に設定する。
- デューティ比を50%に設定する。
- リセット / セットモードに設定する。
- LEDに接続しているピンP1.6をタイマA0の出力に設定する。
- 低電力モード0に遷移する。
- タイマA0の割り込みベクタを定義する。 (以下の例では、未使用)
必要に応じて、TA0CCR1レジスタの値を変更することにより、デューティ比を調整することができる。
#include <msp430.h>
#define LED_PIN BIT6 // P1.6ピンにLEDを接続
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマを停止
P1DIR |= LED_PIN; // LEDピンを出力に設定
// タイマA0の設定
TA0CTL = TASSEL_2 | MC_1 | ID_0; // SMCLK (1[MHz]), アップモード, 分周なし
TA0CCR0 = 1000 - 1; // PWM周期を1[mS] (1[kHz]) に設定
// タイマA0のカウント値が0から999までカウントアップするのに1[mS]掛かるため、-1減算している
TA0CCR1 = 500; // デューティ比を50%に設定
// デューティ比を10%に設定する場合は、100を指定する
TA0CCTL1 = OUTMOD_7; // リセット / セットモード
P1SEL |= LED_PIN; // LEDピンをタイマA0の出力に設定
__bis_SR_register(LPM0_bits); // 低電力モード0に遷移
}
// タイマA0割り込み
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
}
// タイマA0 CCR1割り込み
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
}
PWM信号の生成は、タイマA0のハードウェア機能により自動的に行われる。
1度設定されたPWM信号は、割り込みを使用しなくても継続的に出力される。
上記の例では、PWMのデューティ比を動的に変更する必要がないため、割り込みを使用してPWM設定を更新していない。
以下に示すような場合には、割り込みを使用することが有効である。
- PWMのデューティ比を動的に変更する必要がある場合
- 他の処理と同期してPWM信号を制御する必要がある場合
- 外部イベントに応じてPWM信号を変更する必要がある場合
割り込みを使用する場合は、対応する割り込みベクタ内で必要な処理を行う。
例えば、タイマA0の割り込みを使用してPWMのデューティ比を変更する場合は、Timer_A0関数内でTA0CCR1の値を更新する。
サンプルコード : LEDの調光制御 (割り込み処理)
以下の例では、PWMのLED調光制御を割り込みを使用して並列に実行して、メイン処理では他の処理を実行している。
メイン処理で変数duty_cycleの値を変更することにより、割り込み処理でPWMのデューティ比が更新されて、LEDの超高制御を動的に調整できる。
- タイマA0の設定を行う。
- TA0CCR1の値を設定する。
- グローバル割り込みを有効化する。
- 以下の例では、必要に応じて、変数duty_cycleの値を変更することにより、LEDの調光制御が調整できる。
- タイマA0 CCR1割り込み内で、TA0IVレジスタ (タイマA0の割り込みベクタレジスタ) の値に応じて処理を行う。
以下の例では、TA0CCR1レジスタの割り込みが発生した場合に、変数duty_cycleの値でTA0CCR1レジスタを更新する。
※注意
volatile
を付加して変数duty_cycleを宣言しているが、これは割り込み処理とメイン処理の両方からアクセスされるためである。
これにより、最適化によって問題が発生することを防ぐ。
#include <msp430.h>
#define LED_PIN BIT6 // P1.6ピンにLEDを接続
volatile unsigned int duty_cycle = 100; // デューティ比の初期値を10%に設定
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマを停止
P1DIR |= LED_PIN; // LEDピンを出力に設定
// タイマA0の設定
TA0CTL = TASSEL_2 | MC_1 | ID_0; // SMCLK (1MHz), アップモード, 分周なし
TA0CCR0 = 1000 - 1; // PWM周期を1[mS] (1[kHz]) に設定
TA0CCR1 = duty_cycle; // デューティ比を設定
TA0CCTL1 = OUTMOD_7; // リセット / セットモード
P1SEL |= LED_PIN; // LEDピンをタイマA0の出力に設定
__enable_interrupt(); // グローバル割り込みを有効化
while (1) {
// ...略
// 例: 変数duty_cycleの値を変更することにより、LEDの調光制御が調整可能
// duty_cycle = 500; // デューティ比を50%に変更する場合
}
}
// タイマA0 CCR1割り込み
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
switch (TA0IV) {
case 0x02: // タイマA0のカウンタが、TA0CCR1レジスタの値に達した場合に発生する割り込みがある時、TA0IVレジスタの値は0x02となる
// TA0IVレジスタの値が0x02になる場合は、PWM周期ごとにTA0CCR1に関連する割り込みが発生していること
TA0CCR1 = duty_cycle; // デューティ比を更新
break;
}
}