ESP32でledcWrite()を使ってPWM出力をする【wak-tech Advent Calender2018】

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で新着記事が自動通知されるようになっているのでフォローの方をお勧めします。よろしくお願いします。

3件のコメント

  1. いつもとても参考になるコードをありがとうございます。
    コードを見ていたところ、ミスタイプと思わしき部分を発見いたしましたのでご報告いたします。
    ledcWrite()を使う流れのすぐ下のコードの部分の
    const int が const in になっています。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です