ESP32のPWMとDACを使ってみる ~ おまけ:LCDのバックライトを調光
サクサクと動かす事が出来た1.3インチLCDですが、今回はバックライトを調光しようと思います。
小さい画面ですからたいして眩しく無いんですけれど、ESP32はArduinoの様なAnalogWrite関数が無いらしいですね。
代わりにLED制御用の関数 ledc というのがあるらしく、これがESP32ではPWM出力用として使われる様です。
はて、確かESP32はDACも持ってなかったっけ・・・?
というわけで調べたら25、26番ピンがアナログ波形を出力できるみたいですね。
dacWriteというメソッドで実行できる様子。
ひとまずいきなりLCDのバックライトを操作するのは怖いですので、LEDで試みてみます。
ESP32 PWM(ledc)によるLEDの調光制御
EspressifのArduino core for the ESP32ライブラリを使ってみます。
検索をかけてみると、それらしきものがありました。
毎度の事ながらヘッダーしか見ませんが・・・
一部抜粋
//channel 0-15 resolution 1-16bits freq limits depend on resolution
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-ledc.h
double ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);
void ledcWrite(uint8_t channel, uint32_t duty);
double ledcWriteTone(uint8_t channel, double freq);
double ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);
uint32_t ledcRead(uint8_t channel);
double ledcReadFreq(uint8_t channel);
void ledcAttachPin(uint8_t pin, uint8_t channel);
void ledcDetachPin(uint8_t pin);
これを見ると0~15の合計16チャンネルを持つ事が出来て、各チャンネルに登録されたGPIOに対して制御できる様な造りになっている様子。
PWM的なものって出すだけかと思ってましたが、なかledcRead系のものもある様で。
PWMを読み取れるって事なんでしょうか。
モールス信号的な?
よく判らないのでRead系はとりあえずスルーしておいて、、
ledcの使い方
1.ledcSetup でチャンネルと周波数、ビット幅を決める
2.ledcAttachPin でPWMを出力するGPIOピンとチャンネルを関連づける
3.ledcWrite でチャンネルに対してデューティー比を指定して出力する
こんな感じかな。
わりと簡潔に出来ている様です。
コードはこんな感じでしょうか。
#include <Arduino.h>
// PWM出力 ledc変数
uint8_t ledcGPIO = 27; // PWM GPIO
uint8_t ledcCH = 0; // ledcチャンネル
double ledcFreq = 5000; // PWM周波数
uint8_t ledcBitWidth = 8; // 8bit 0-255(13bit default)
uint32_t ledcDuty = ( pow(2, ledcBitWidth) / 2 ) - 1; // デューティ比初期値設定 1/2 (127)
uint16_t timeWait = 2; // 調光ウェイト ms
void setup() {
Serial.begin(115200);
// 1.ledc設定
ledcSetup(ledcCH, ledcFreq, ledcBitWidth);
// 2.GPIOピンをチャンネルに所属させる
ledcAttachPin(ledcGPIO, ledcCH);
// 3.対象チャンネルに対してデューティ値(ビット幅分の値)でPWM開始
ledcWrite(ledcCH, ledcDuty);
// 比較用LED 常灯
pinMode(14, OUTPUT);
digitalWrite(14, HIGH);
}
// デューティー比増減
void volumeDuty(void *param) {
Serial.println("volumeDuty Start.");
for(uint8_t cnt = 0; cnt < 5; cnt++) {
for(long i=0; i <= pow(2, ledcBitWidth)-1; i++) {
ledcWrite(ledcCH, i);
delay(timeWait);
Serial.print("LEDC Duty : ");
Serial.println(i);
}
for(long i=pow(2, ledcBitWidth)-1; i >= 0; i--) {
ledcWrite(ledcCH, i);
delay(timeWait);
Serial.print("LEDC Duty : ");
Serial.println(i);
}
}
Serial.println("volumeDuty End.");
ledcWrite(ledcCH, 0);
}
void loop() {
volumeDuty(NULL);
}8bitの分解能は0-255の256値ですから、とりあえず初期値は適当に半分にして点灯させてみます。
その後メインループで0-255の間を繰り返し増減させています。
大体リニアに明るさが変化している感じですね。
pwm周波数が5000との事で、要するに1秒間に5000回更新されています。
これのデューティ比1/2という事は、1秒間の間に2500回OFFし2500回ONしているという計算。
全くチラつきは感じません。
実際チラつくとどうなるのかが気になりましたので、周波数を落としてみました。
人間の目は30Hz~50Hzくらいまでは感知できるらしいのですが、肉眼ではキッチリと50Hzでチラつきは見えなくなりました。
私の目は人並みという事か
しかし動画では多少はチラついて見える事から、実際にはちゃんと点滅しているのでしょう。
また、チラついている様な低周波数の時でもDuty比が1:1に近ければほぼ常灯している事から、ちゃんとPWMで出力されているんだなという事が想像できます。
オシロスコープでも持ってれば見る事が出来るのでしょうけれど・・・
さて次にDACによるコントロールを見ていきます。
ESP32 DAC(dacWrite)によるLEDの調光制御
ヘッダを見るとこちらは至極簡単で、そのまま0-255のレベルの範囲で出力できる様です。
DACに使えるGPIOピンが25,26と限られている様ですが、お手軽で良いですね。
簡単にコードに追加してみます。

https://github.com/espressif/arduino-esp32/blob/master/cores...
https://github.com/espressif/arduino-esp32/blob/master/cores...
















ディスカッション
コメント一覧
まだ、コメントがありません