ESP32は、LEDの明るさ調整やモーター制御などで利用されるPWM(Pulse Width Modulation)機能を搭載しています。
ESP32では、このPWM機能は**LEDC(LED Control)**という周辺機能で提供されています。
名前だけを見るとLED専用のように思えますが、実際にはLEDだけでなく、DCモーターやサーボモーター、ブザーなど幅広い用途で利用できます。
ESP32で開発を始めると、
- PWMとはどのような仕組みなの?
- デューティ比とは?
- LEDCとは何ができるの?
- 周波数と分解能はどう設定すればよいの?
といった疑問を持つ方も多いでしょう。
この記事では、PWMの基本からESP32のLEDC機能、実務で役立つ設計ポイントまで分かりやすく解説します。
PWMとは?
PWM(Pulse Width Modulation)は、デジタル出力を高速でON・OFFすることで、アナログ的な制御を実現する技術です。
例えばLEDでは、
- 常にONなら100%の明るさ
- 常にOFFなら消灯
になります。
その中間の明るさを実現するために、短時間でON・OFFを繰り返します。
人の目には高速で点滅しているようには見えず、明るさが変化しているように感じられます。
同じ考え方はモーターやブザーの制御にも利用されています。
デューティ比とは?
PWMで最も重要な考え方が**デューティ比(Duty Cycle)**です。
デューティ比とは、1周期のうち出力がONになっている割合を表します。
例えば、
- 0%:常にOFF
- 25%:4分の1だけON
- 50%:半分ON
- 75%:4分の3だけON
- 100%:常にON
となります。
LEDでは明るさ、DCモーターでは回転速度などを、このデューティ比で調整します。
ESP32のLEDCとは?
ESP32ではPWM機能としてLEDC(LED Control)を搭載しています。
LEDCは高い柔軟性を持ち、
- 周波数の設定
- デューティ比の変更
- 複数チャネルの制御
などを簡単に行えます。
そのため、LEDだけでなく、さまざまなPWM制御を1つの周辺機能で実現できます。
また、GPIOマトリクスにより、多くのGPIOへPWM出力を割り当てられるため、基板設計の自由度も高くなっています。
周波数と分解能の関係
LEDCでは、PWMの周波数と分解能を設定できます。
ここで重要なのは、この2つは自由に最大値を設定できるわけではなく、互いに関係しているという点です。
一般的には、
- 周波数を高くすると分解能は下がる
- 分解能を高くすると設定できる周波数は低くなる
というトレードオフがあります。
そのため、用途に応じて適切な設定を選ぶことが重要です。
PWMが使われる場面
ESP32では、PWMは次のような用途で広く利用されています。
- LEDの明るさ調整
- DCモーターの速度制御
- サーボモーターの位置制御
- ブザー・スピーカーの音階出力
- 電源制御
PWMは単にLEDを光らせるだけでなく、多くの組み込み機器で重要な役割を担っています。
用途に応じて周波数やデューティ比を適切に設定することで、より高品質な制御を実現できます。
ESP-IDFでLEDCを使用する方法
ESP-IDFでは、LEDCを利用するために以下のヘッダファイルをインクルードします。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
また、CMakeLists.txtではLEDCドライバを利用するため、以下のように記述します。
idf_component_register(
SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES esp_driver_ledc
)
ESP-IDF v5.xでは、LEDCドライバはesp_driver_ledcコンポーネントとして提供されています。
PWM出力のサンプルコード
以下はGPIO2から5kHzのPWMを出力し、LEDを徐々に明るくしたり暗くしたりするサンプルです。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#define LED_GPIO GPIO_NUM_2
#define LEDC_FREQ_HZ 5000
#define LEDC_RESOLUTION LEDC_TIMER_10_BIT
void app_main(void)
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_RESOLUTION,
.freq_hz = LEDC_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
ledc_channel_config_t ledc_channel = {
.gpio_num = LED_GPIO,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
while (1)
{
for (int duty = 0; duty <= 1023; duty += 10)
{
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_0,duty));
ESP_ERROR_CHECK(ledc_update_duty(
LEDC_LOW_SPEED_MODE,
LEDC_CHANNEL_0));
vTaskDelay(pdMS_TO_TICKS(20));
}
for (int duty = 1023; duty >= 0; duty -= 10)
{
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_0,duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_0));
vTaskDelay(pdMS_TO_TICKS(20));
}
}
}
このプログラムを実行すると、GPIO2から5kHzのPWMが出力され、LEDがゆっくりと明るくなり、その後ゆっくり暗くなります。
※LEDがHIGH ACTIVE(点灯)する接続想定です。
コードのポイント
LEDCを利用する場合は、次の3つの手順で設定します。
- タイマー設定
- PWM周波数
- 分解能
- クロック設定
- チャネル設定
- 出力GPIO
- 使用タイマー
- 初期デューティ比
- デューティ比変更
ledc_set_duty()ledc_update_duty()
デューティ比を変更するだけで、LEDの明るさやモーターの出力を自由に制御できます。
PWMでよくあるトラブル
周波数が適切でない
LEDでは数kHz程度が一般的ですが、モーターやブザーでは用途に応じて適切な周波数を選択する必要があります。
例えばDCモーターでは、周波数が低すぎると可聴域のノイズが発生することがあります。一方で、高すぎる周波数ではスイッチング損失の増加やドライバの性能限界を考慮する必要があります。
分解能を高くしすぎる
LEDCでは周波数と分解能はトレードオフの関係にあります。
「高い周波数」と「高い分解能」を同時に設定できるとは限りません。
用途に応じて最適な組み合わせを選ぶことが重要です。
GPIOの選択ミス
ESP32シリーズではGPIOマトリクスにより多くのGPIOへPWM出力を割り当てられます。
ただし、使用するESP32シリーズや基板によっては、ブートストラップピンや他の周辺機能と競合するGPIOがあります。
回路設計時には、データシートや技術資料で対象デバイスのGPIO制約を確認しましょう。
実務での設計ポイント
実際の製品開発では、PWMが動作するだけでは十分ではありません。
例えば、
- LEDはちらつきを感じない周波数を選ぶ
- DCモーターは可聴ノイズを考慮する
- サーボモーターは仕様に合わせたPWM周期を使用する
- 配線を短くしてノイズの影響を抑える
- モーター駆動時は電源ラインやGNDの設計にも配慮する
といった点が重要になります。
また、PWM信号はスイッチング信号であるため、EMI(電磁ノイズ)の原因になることがあります。必要に応じて配線レイアウトやグランド設計を見直すことで、安定した動作につながります。
まとめ
ESP32のLEDCは、LED制御だけでなく、モーターやブザーなど幅広い用途で利用できる柔軟なPWM機能です。
基本的な使い方はシンプルですが、実務では周波数や分解能、GPIOの選択、ノイズ対策まで考慮することで、より品質の高いシステムを構築できます。
まずは今回紹介したサンプルコードを動かし、デューティ比や周波数を変更しながらPWMの動作を体験してみてください。
PWMの仕組みを理解することは、ESP32を活用した組み込み開発の幅を大きく広げる第一歩となるでしょう。