目次
ESP32でledcWrite()を使ってPWM出力をする【wak-tech Advent Calender2018】
wak-tech Advent Calender2018 3日目です。一人です。
参考にさせていただいたページ
ピン配置
先人が居るというのはどれだけありがたいことか。お借りいたします。
動いている様子
回路
GPIOの26ピンから510Ωの抵抗を伸ばし、その先に赤色LEDを接続。そこからはただGNDに繋いだだけのシンプルな回路です。
PWMとは
PWMとは、(Pulse Width Modulation) の略で、細かくオンオフを繰り返すことで平均としてアナログの出力を出す仕組みの事です。
マイコンは基本オンオフしかできません。オンにしたときのLEDの明るさを100とすると、例えば1msごとにオンオフを交互にするだけで明るさを50にすることができます。
この時のオンになっている割合のことをduty(デューティ―)比と言います。
このPWM関数を実際に作ってみて実装した「ESP32で電子ホタルをつくる(PWM制御、ledc)【wak-tech Advent Calender2018】」を書きましたのでもしよければご覧ください。
Arduino core for ESP32に備わっているPWM関数
もちろん、自作しなくても公式に関数が用意されています。
ただ注意したいのが、普通のArduinoで使えていたanalogWrite()がないということです。
Arduino 日本語リファレンス analogWrite()を見ればわかる通り、
analogWrite(3,128);
とするだけで明るさが50%の出力をピン3に出すことができました。これができません。その代わりにledcWrite() という関数があります。
ledcWrite()の使い方
ledcWrite(channel,brightness);
…なんだ、channelって。これはLED_PWMの実験(ESP-WROOM-32)に詳しく書かれています。というかこの記事はほぼこの方のおかげで書かれています。ありがとうございますm(__)m
このページによれば、ESP32ではchannelが0~15までがあり、同じチャンネルに接続されたピンたちは1つの関数で動かすことができるようです。
ledcWrite()に使えるピンたち
GPIO | アナログピン番号 |
---|---|
32 | A4 |
33 | A5 |
26 | A19 |
25 | A18 |
27 | A17 |
14 | A16 |
12 | A15 |
13 | A14 |
15 | A13 |
4 | A10 |
2 | A12 |
0 | A11 |
この表にあるピンであれば使用することができます。
今回の回路ではGPIO26にLEDをつないでいるので、A19を指定することになります。
const int ledPin = A19;
ledcWrite()を使う流れ
//使用するピンのアナログピン番号を指定
const int ledPin = A19;
//pwmの設定。最初の引数がchannel,次が周波数,最後が解像度(ここでは8bit = 256段階)
ledcSetup(0,12800,8);
//ピンをチャンネルに接続
ledcAttachPin(ledPin,0)
以上の手順で、0というチャンネルにA19番が登録されました。これで準備完了です。あとは
ledcWrite(0,128);
とでもすれば、0チェンネルに接続されたピンが128/256 = 50%の電力相当で駆動されます。LEDをつなげば明るさを半分にできるわけです。
電子ホタルのソースコード
これを使ってLEDの明るさをじわじわ変えてみましょう。いわゆる電子ホタルです。以下のコードはLED_PWMの実験(ESP-WROOM-32)様のサンプルコードに少し注釈を加えたものになっています。
const int ledPin = A19;
void setup() {
// 使用するタイマーのチャネルと周波数を設定
ledcSetup(0, 12800, 8);
// ledPinをチャネル0へ接続
ledcAttachPin(ledPin, 0);
}
void loop() {
// 初期の明るさを指定
static uint8_t brightness = 0;
// 明るさの変動具合を設定(高いほど急に変わる)
static int diff = 1;
// チャネル0に明るさを設定
ledcWrite(0, brightness);
// 明るさが0を下回る、若しくは255を超えた時に反転
if (brightness == 0) {
diff = 1;
} else if (brightness == 255) {
diff = -1;
}
brightness += diff;
//遅延を遅くすればゆっくり明るさが変わるようになる
delay(10);
}
最後のdelay(10);の値を大きくすれば、ゆっくりな動きになります。
最後に
この関数を使えばフルカラーLEDやモーターも駆動できそうですね!
いずれやりますのでブックマークお願いします。
twitterで新着記事が自動通知されるようになっているのでフォローの方をお勧めします。よろしくお願いします。
ピンバック: ESP32で始めるIoT電子工作入門【20個のチュートリアル】 | Wak-tech
いつもとても参考になるコードをありがとうございます。
コードを見ていたところ、ミスタイプと思わしき部分を発見いたしましたのでご報告いたします。
ledcWrite()を使う流れのすぐ下のコードの部分の
const int が const in になっています。
ご指摘誠にありがとうございます!すぐに訂正いたします。
ピンバック: 3Dプリンタでメカナムホイールを堪能 - 電子工作 - HomeMadeGarbage
ピンバック: esp32同士でシリアル無線通信をして,無線Lチカ・光量制御をしてみる(Arduino IDE使用) | Remma's Laboratory
ledcWrite()に使えるピンたち の根拠を教えていただけないでしょうか。
リファレンス見てもそのような記載は無いようなので,ぜひお願いします。
私が見つけたのは下記だけです。
GPIO5など問題ないように思うのですが・・・。
(これからGPIO5も使ってLED光らせる予定なので,少々心配しています)
ESP32-WROOM-32D & ESP32-WROOM-32U Datasheet V1.9 8ページ
Note:
External connections can be made to any GPIO except for GPIOs in the range 6-11. These six GPIOs are connected to the module’s integrated SPI flash. For details, please see Section 6 Schematics.
ESP32 Technical Reference Manual V4.1 44ページ
Note that the I/O GPIO pads are 0-19, 21-23, 25-27, 32-39, while the output GPIOs are 0-19, 21-23, 25-27, 32-33. GPIO pads 34-39 are input-only.
コメントありがとうございます。
ledcが使用可能なのはPWM機能が付いているピンです。こちらのサイト(https://circuits4you.com/2018/12/31/esp32-devkit-esp32-wroom-gpio-pinout/)のピンアサインを見ていただければ分かるかと思います。Espressif公式のデータシート(https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)の32ページによれば「Any GPIO Pin」とありますので、基本全てのピンで使用可能です。ただしGPIO6-11は内部フラッシュに接続されているので、これ以外を使うべきかと思います。
早速に返信いただきありがとうございます。
結局,まだよくわからないので追加で確認させてください。
本文にある表のIO以外でもLEDPWMに使える,と言うことでよろしいでしょうか?
(具体的にはGPIOの5,16,17,18,19,21,22,23)
データシート上はそうです。他のピンは使用したことがないため保証出来かねますが、恐らく動くと思います。
試しに5番ピン等でpwm設定してもらえるとありがたいです。
ledcSetupでコンパイルがエラー停止します。