5 PWM(Analog Output)
今回の講義の目的は、マイコンを使って電圧を制御することです。電圧を上げたり下げたりできると、LEDの光る強さを変えたり、モータの回転速度を変えたりすることができます。 ※10月24日の演習には、未使用の単3電池4本を持参してください。持ってきていない場合には、演習時間内に購入しに行ってもらいます。 目次 5.1 PWM 5.2 モータの基礎 5.3 実習 5.1 PWM マイコンの世界はデジタルなので、プログラムで電圧を制御するのは、ちょっと難しいことです。そこで、PWMという手法が登場します。 これは擬似的にアナログ出力を実現する方法だと思ってください。 仕組み マイコンのデジタルピンからの出力は、HIGH(例えば3V)かLOW(例えば0V)のどちらかだけです。しかし、0Vから3Vまでの間で電圧を自由に変えたいという場合があります。例えば、LEDの明るさを調整したい場合などです。こういう時には、PWM(Pulse Width Modulation)という方法を用います。 PWMの仕組みを一言で説明すると、HIGHとLOWを素早く切り替えることによって、HIGHとLOWの間の電圧を擬似的に作り出す方法です。以下の図をみてください。 このようにHIGHとLOWを規則的に繰り返す信号を、パルス波と言います。上記の図で示しているパルス波は、ある一定時間で同じパターンを繰り返していますね。このような繰り返しの間隔を周期と呼び、1秒間に何周期あるかを周波数と呼びます。周期の始まりは、LOWからHIGHに変わる瞬間で、周期の終わりは、次にLOWからHIGHに変わる瞬間です。周波数1kHzと言ったら、1秒間に1000回の周期が起こるような波形を意味します。 図で示したパルス波は、1周期におけるHIGH(3V)とLOW(0V)の間隔が、ちょうど1/2ずつになっています。周波数が十分に高い場合,このデジタルピンにかかる電圧は、3V / 2 = 1.5Vとなります。これがPWMです。実際に電圧を変えるのではなくて、擬似的に電圧を変えているのです。 PWMを使った場合にデジタルピンにかかる電圧は,デューティ比(duty ratio) によって決まります。デューティ比とは,1周期の間にHIGHになっている割合のことです。HIGHが3Vの場合、デューティ比50%ならば1.5V,10%ならば0.3Vとなります。 PWMを使用する場合、どのくらいの周波数が必要かは難しい問題なので、あまり深入りしないことにしますが,1Hzではだめなことは明らかです。1Hzということは、HIGHとLOWが同じ時間であるとすると1周期内で0.5秒ずつです。LEDで実験すると単に点滅するだけです。PWMの周波数は、デジタルピンの用途によって変わるとされています。例えばLEDを使う際に必要な周波数,モータを使う際に必要な周波数という具合です。モータの場合には10kHzから20kH位が適当でしょう。LEDだと、数100Hzでも大丈夫だと思います。 PWMを使って電圧を制御するには、パルス波を作り出す必要があります。パルス波は、タイマを使って作ります。非常に微小な時間をタイマによって作りだし,デジタル出力をHIGHにしたりLOWにしたりします。 例えば、1kHzの周波数でPWM 制御をしたいとしましょう。1秒間に1,000周期ですから,1周期は1msです。1周期を10段階に分けると、1段階100µsになります。この100µsをタイマを使って作り1単位とすれば、10%刻みでデューティ比が設定できるようになります。 試してみよう mbedの基本ライブラリには、PWMを簡単に使うためのPwmOutというクラスが用意されています。よって、自分でタイマを使って波形を作る必要はありません。GPIOはPWMピンとして使うことができます。ただし、P11は使えません。また、PWMピンとして指定できるのは3つまでという制約があります。 ソース電流を使った回路でLEDを光らせることを考えます。定電流ダイオードではなくて330Ωの抵抗を使っていることに注意してください。 以下のようなプログラムを作成して、実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "mbed.h" PwmOut pwm(P13); int main() { pwm.period_ms(1); while(1) { pwm = 0.2; // 20% wait(1); pwm = 1.0; // 100% wait(1); } } |
LEDをよく見ていると、1秒ごとに光る強さが変わるのが観察できるはずです。暗い時にはPWMのデューティ比は20%になっています。 myled.period_ms(1);に注目してください。これは、PWMの周期を、1msの幅に設定しています。1周期が1msということは、1kHzということですね。それでは、これを100msにしたら、どうなるでしょうか。これは、演習で実際に実験することにしましょう。 デューティ比を変化させてLEDの明るさを連続して変化させて見ましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include "mbed.h" #define BRIGHTNESS_MAX 100 #define BRIGHTNESS_MIN 0 PwmOut myled(P13); int main() { int brightness = 20; // initial brightness value int increment = 5; myled.period_ms(1); while(1) { brightness += increment; if(brightness > BRIGHTNESS_MAX) { brightness = BRIGHTNESS_MAX; increment = -increment; } else if(brightness < BRIGHTNESS_MIN) { brightness = BRIGHTNESS_MIN; increment = -increment; } myled = brightness / 100.0; wait(0.1); } } |
LEDの明るさが滑らかに変わることが観測されるはずです。 PWMを使う際にもう1つ頭に入れておいて欲しいことがあります。それは、デューティ比を変化させる際には少し間隔をおく必要があるということです。5msくらいあれば大丈夫だと思います。上記の例ではwait(0.1)で100msの間隔を空けています。 もう1つ気をつけるべきことは、すべてのGPIOがPwmOutに使える訳ではないことです。P11は使えません。 5.2 モータの基礎 この講義では、DCモータとサーボモータという2種類のモータを使います。 DCモータ 家庭にある電源コンセントを、AC100Vと呼ぶことは知っていると思います。このACとはAlternating Currentの略で、電流の向きが変わることを意味しています。日本語では、交流あるいは交流電流と言います。 一方、乾電池やUSB電源などは、直流あるいは直流電流と呼ばれます。DCというのは、Direct Currentの略で、直流電流を意味します。直流の場合、電流の向きは常に一定です。 DCモータは、直流電流で動くモータです。模型でよく使用するマブチモータは、皆さんも一度は見たことがあると思います。 乾電池でDCモータを動かすのは簡単です。 しかしモータを、マイコンに繋いで制御するとなると、ちょっと難しいです。まず、DCモータに限らずモータというものは、少なくとも数百mA、多ければ数Aの電流を必要とします。マイコンのピンから供給できる電流は5mAくらいなので、マイコンのデジタル出力を使い直接DCモータを駆動することはできません。使用するモータによって、別途、適した電源を用意する必要があります。また、正転、逆転、停止、回転速度などの制御を行う必要もあります。 そこで、それらのことを簡単に解決するための、モータドライバというデバイスが存在します。この講義では、TA7291Pというモータドライバを使います。TA7291Pは、mbedをはじめようキットには含まれていないので注意してください。 […]