動作
Arduinoボードのピンの出力電圧をアナログ制御します。
「出力電圧のアナログ制御」とは、ピンの出力電圧をONとOFFの中間の電圧状態に制御する、というイメージです。例えば、LEDの明るさを50%にしたり、モーターを半分の速度で回転させたりする制御ができます。
Arduinoボードのアナログ制御方法は「PWM制御」と「DAC制御」の2種類があります。ボード/ピンによって対応している制御方法が異なります。対応している制御方法は「補足:analogWriteが使用できるピンとPWM周波数」をご参照ください。
PWM制御
PWM制御ピンは、実際に中間の電圧(例えば2.5V)が出力されるわけではありません。PWM(Pulse Width Modulation・パルス幅変調)という方式で、ONとOFFを高速に繰り返すことで、見かけ上の中間的な出力を実現しています。
PWMでは、一定の周期の中で「ONの時間」の割合を変えて制御します。この比率のことをデューティ比と呼びます。(半分の時間をONにした場合、デューティー比は0.5または50%になります)

例えば、LEDの場合、ONとOFFが高速に切り替わると、人間の目にはその切り替わりが認識できず、平均的な明るさとして見えます。デューティ比が大きいほど明るく、小さいほど暗く見えます。
analogWrite関数では、このデューティ比を割合ではなく(パーセントではなく)、0〜255の数値で指定します(この数値範囲はデフォルト設定の場合で、analogWriteResolution関数で変更することができます)。
0を指定すると常にOFF(デューティ比0%)、255を指定すると常にON(デューティ比100%)、127を指定すると約50%のデューティ比になります。
analogWrite関数が利用できるピンは限られています。
一般的にピン番号の横に「〜」マーク(波マーク)が付いているピンが対応しています。具体的に使用できるピンはArduinoボードによって異なりますので「補足:analogWriteが使用できるピンとPWM周波数」を参照ください。
DAC制御
DAC制御ピンは、実際に中間の電圧を出力することができます。
5V動作のArduinoボードであれば、analogWrite(pin, 127)で約2.5Vの一定の電圧を出力することができます。
デフォルトでは、0〜255の範囲で設定できますので、設定できる電圧の刻み幅は約19.6mV(5V ÷ 255 ≒ 0.0196V)となります。
DAC制御ピンでLEDの明るさ調整をすると、PWM制御のようなチラつきがなくなります。
主な用途
- LEDの明るさ調整(調光)
- DCモーターの回転速度制御
- 圧電スピーカーの音程制御
- サーボモーターの制御信号生成など
LEDの点灯・消灯やモーターのON・OFFのように、ONかOFFかの2つの状態だけを制御する場合はdigitalWrite関数を使います。
書式
analogWrite(pin, value);| 引数 | pin | 制御するピンを指定します。ピン番号(10など)で指定します。 ※ analogWrite対応ピンを指定する必要があります |
value | デューティ比を0〜255の範囲で指定します(デフォルト設定の場合)。 0は常にOFF(0V)、255は常にON(5Vまたは3.3V)です。 analogWriteResolution関数で分解能を設定すると、設定範囲を変更することができます(12ビットに指定した場合、0〜1023の範囲で指定できる)。 | |
| 戻り値 | なし | |
analogWrite関数を使用する場合、事前にpinMode関数でピンを出力モードに設定する必要はありません(analogWrite関数内の処理で自動的に出力モードに設定されます)。
ただし、明示的にpinMode(pin, OUTPUT);を記述しておくと、スケッチの可読性が高くなるため記述しておくことをおすすめします。
使用例
次のコードにより、指定したピンの出力をアナログ制御することができます。
analogWrite(9, 127); // 9番ピンのデューティ比を約50%に設定
analogWrite(5, 0); // 5番ピンをOFF(デューティ比0%・digitalWrite(5, LOW)と同じ効果)
analogWrite(3, 255); // 3番ピンをON(デューティ比100%・digitalWrite(3, HIGH)と同じ効果)サンプルスケッチ
5番ピンに接続したLEDの明るさをフェードイン・フェードアウトする(徐々に明るく徐々に暗くする)制御をします。
ボタンをクリックするとシミュレーターが動作します。スケッチを変更することもできます。変更した場合、シミュレーションを一度
ボタンをクリックして停止してから再度シミュレーターを開始してください。
シミュレーターでは、LEDの明るさの変化を視覚的にわかりやすくするために、シミュレーター回路のLEDの物理特性を変更し、さらにスケッチではanalogWriteで指定する数値範囲を調整しています。
実際のLEDで同様の制御を行うと、急に明るくなったり急に暗くなる現象が発生します。analogWriteでLEDの明るさを一定の間隔(例えば5ずつ)変化させても、人間の目には急に明るくなったり急に暗くなったり感じます。これは人間の目が暗い領域は変化に対する感度が高く、明るい領域は変化に対する感度が低くなることが原因です。(目の感覚は対数的な感度を持っています)
実際のLEDを徐々に変化させる場合、ガンマテーブル(数値のテーブル)を作成して、そのテーブルの数値でanalogWriteの引数valueを指定するようにします。詳しくは実践テクニックのセクションを参照してください。
トラブルシューティング
analogWriteで制御できない
analogWrite関数でLEDの明るさやモーターの速度が変化しない場合、PWM非対応ピンを使用していることが考えられます。
analogWrite関数はすべてのピンで使用できるわけではありません。PWMに対応したピンでのみ使用できます。
例えばArduino Uno R3の場合、PWM対応ピンは3、5、6、9、10、11番ピンです。これらのピンはボード上のピン番号の前に「〜」マーク(波線マーク)が付いています。
PWM非対応のピンに対してanalogWrite関数を使用した場合、値が127以下であればLOW(0V)、128以上であればHIGH(5Vまたは3.3V)が出力されます。つまり、デジタル出力のような動作になります。(純正Arduinoボードの場合)
また、ESP32のGPIO34、35、36、39ピンは入力専用ですので、出力制御はできません。
対応ピンについては「補足:analogWriteが使用できるピン」セクションを参照ください。
LEDがちらつく
analogWrite関数でLEDの明るさ制御をした際に、ちらつきが見えることがあります。
これはPWMの周波数が低いことが原因です。
Arduino Uno R3のPWM周波数は約490Hzですが、周囲の環境や人によってはこの周波数のちらつきが見えることがあります。特にLEDを素早く動かした場合(振った場合など)、点滅が見えやすくなります。
PWMの周波数を変更するにはタイマーレジスタを直接操作する必要がありますが、タイマーレジスタを変更すると、delay関数やmillis関数の動作に影響することがありますので注意が必要です。
実践テクニック
analogWrite関数でデジタル制御を行う際のテクニック集です。
ボリュームを使ってLEDの明るさを調整する
ボリューム(可変抵抗)の状態をanalogRead関数で読み取り、その値をanalogWrite関数に渡すことで、ボリュームでLEDの明るさを調整できます。
analogRead関数の読み取り値は0〜1023(10ビット分解能の場合)、analogWrite関数の指定値は0〜255ですので、数値範囲を変換する必要があります。
このような数値範囲の変換はmap関数を使うと便利です。
int sensorValue = analogRead(A0); // ボリュームの値を読み取り(0〜1023)
int pwmValue = map(sensorValue, 0, 1023, 0, 255); // 0〜1023を0〜255に変換
analogWrite(10, pwmValue); // LEDの明るさを制御なお、0〜1023を0〜255に変換する場合は、次のように4で割る方法でも同様の結果が得られます。 (10ビットから8ビットの変換のため、22 = 4で割ることにより計算できます)
int pwmValue = analogRead(A0) / 4; // 簡易的な変換
analogWrite(10, pwmValue);LEDのフェードイン・フェードアウトをスムーズに制御する
以下のスケッチと回路では、6番ピンに接続したLEDの明るさをフェードイン・フェードアウトする(徐々に明るく徐々に暗くする)制御をします。
analogWrite関数で実際のLED制御を行うと、例えばanalogWrite(pin, 127)の明るさは、analogWrite(pin, 255)の明るさの半分には見えません(実際にはほとんど変わらない明るさに見えます)。
これは人間の目の特性によるもので、スムーズにフェードイン・フェードアウト制御するには数値の補正を行う必要があります(ガンマ補正と呼ばれています)。
以下のスケッチでは、数値の補正表を配列として作成して、その配列の値を使用してanalogWrite関数で制御しています。なお、配列はRAMではなくプログラム領域に書き込んでいますので、RAMの消費量が少なくなるように工夫されています。
補足
analogWriteが使用できるピンとPWM周波数
analogWrite関数でアナログ制御(PWM制御/DAC制御)ができるピンは、Arduinoボードによって異なります。代表的なボードの対応ピンは次のとおりです。
ボードによってはPWM周波数がピンによって異なっていますので、高い周波数が必要な場合は使用するピンに注意が必要です。
| ボード | PWM対応ピン | PWM周波数 |
|---|---|---|
| Arduino Uno R3 Arduino Nano Arduino Mini | 3, 5, 6, 9, 10, 11 | 490Hz (5, 6番ピンは980Hz) |
| Arduino Uno R4 | 3, 5, 6, 9, 10, 11(PWM) A0(DAC) | 490Hz |
| Arduino Mega | 2 〜 13, 44 〜 46 | 490Hz (4, 13番ピンは980Hz) |
| Arduino Leonardo Arduino Micro | 3, 5, 6, 9, 10, 11, 13 | 490Hz (3, 11番ピンは980Hz) |
| Arduino MKRシリーズ | 0 〜 8, 10, 12, A3, A4(PWM) A0(DAC) | 732Hz |
| Arduino Zero | 3 〜 6, 8 〜 13(PWM) A0(DAC) | 732Hz |
| Arduino Due | 2〜13(PWM) DAC0, DAC1(DAC) | 1000Hz |
| ESP32 DevKitCシリーズ | 出力ピンであれば制御可能 | 1000Hz (使用する関数、プログラミング言語に依存) |
| Raspberry Pi Pico | 出力ピンであれば制御可能 | プログラムで設定 |
ArduinoのPWM出力は、マイコン内部のハードウェアタイマーを利用しています。一つのボード(マイコン)には複数のハードウェアタイマーが搭載されていて、各PWMピンはいずれかのタイマーに紐付けられています。
例えばArduino Uno R3では、PWM出力に使われるタイマーが3つあり、ピンごとに割り当てられたタイマーが異なるため、PWM周波数にも違いが生じます。具体的には、Timer0は5・6番ピン、Timer1は9・10番ピン、Timer2は3・11番ピンに対応しています。Timer0はシステムの時間管理(millis()やdelay())にも使用されるため、ハードウェアタイマーの設定(プリスケーラ設定)が他と異なり、5・6番ピンだけ約980Hz、それ以外のPWMピンは約490Hzで動作するようになっています。
この仕組みはAVRマイコンのハードウェア構成に由来します。そのため、他のマイコンの場合は一般的にどのPWMピンも同じ周波数で動作するようになっています。
analogWriteの分解能
analogWrite関数では、出力値をデフォルトで0〜255の範囲で設定できますが、この数値範囲をanalogWriteResolution関数で変更することができます。
analogWriteResolution関数では、引数に分解能をビット数で指定します。デフォルトは8ビットで0〜255ですが、10ビットに指定すると0〜1023の数値範囲で、より細かく制御することができます。
Arduinoボード内部動作
Arduinoボードの内部動作は次のようになっています。次のイラストは、例としてArduino Uno R3のようすを示しています。

Arduinoボードの中にはタイマーと呼ばれる、数を数えるモジュール(カウンター)が3個内蔵されています。
例えば、5番ピンと6番ピンは、Timer0の出力がPWM波形生成モジュールを通して接続されています。例えば、analogWrite(5, 100)とした場合、次のような動作になります。
Timer0は、0、1、2と0から1ずつ増加させながら数を数えてその数値をPWM波形生成モジュールに伝えています。Timer0は255まで数えると0に戻ってまた255まで数えます。
5番ピンに接続されているPWM波形生成モジュールは、Timer0から受け取った数値に応じて次の動作をします。
・0を受け取った時、5番ピンをONにする
・100を受け取った時、5番ピンをOFFにする(100はanalogWriteの引数で指定した値)
Timer0とPWM波形生成モジュールはこのように連携しながらPWM波形を生成しています。
なお、analogWrite関数を実行すると、Arduinoボード内部は上のように指定した端子にPWM波形生成モジュールが接続されますが、digitalWriteなどを実行すると、上の接続は解除されてdigitalWriteで制御できる回路に切り替わります。
