ESP32で電子ホタルをつくる(PWM制御、ledc)【wak-tech Advent Calender2018】

ESP32で電子ホタルをつくる(PWM制御、ledc)【wak-tech Advent Calender2018】

やってみたかったんですよねAdvent Calender!一人だけど!

こんにちは。今月はESP32強化月です。
今回は、ESP32で電子ホタルを作ります。電子ホタルとは、じわじわと明るさが変わっていく光の事です。

以前、PICマイコンで電子ホタルを作るで電子ホタルを作ったことがあります。基本的にはこれと同じ原理です。

電子ホタルの原理

明るさを変えるには、電圧を変えればいいだろうと思うかもしれません。実際、マイコンにはアナログ電圧を出力する機能も付いています。
ですが今回は分かりやすくするためにソフトウェア制御の明るさ変化をさせてみたいと思います。

人間の目を騙せ

人間は30枚の静止画を1秒間の間に続けて見せれば、それが動いているように見えるくらいには目が良くないです。
これを利用して、高速でLEDを点滅させれば実質的に明るさを変えることができます。

簡単に言えば上図のような状態です。LEDをつけた状態を明るさ100とします。
これを短い間にある割合だけオフにして点滅させれば、赤線で表したような平均化した明るさに見えるのです。

明るさ変化させる関数を作ろう

早速ですが、これを実装する関数を作りました。以下コピペでArduinoのエディタに貼り付けましょう。

void pwmLED(int duty,int time){
  int i=0;
  int j=0;
  for(j=1;j<time;j++){
    for(i=0;i<100;i++){
      if(i<duty){
        digitalWrite(LEDpin,HIGH);
      }else{
        digitalWrite(LEDpin,LOW);
      }
      delayMicroseconds(10);
    }
  }
}

LEDを取り付けたピンをLEDpinに設定します。今回は26番に取り付けたので、

const int LEDpin = 26;

と宣言すればこの関数が使えます。

関数の使い方

これだけでは明るさを指定するのみになります。電子ホタルのようにじわじわと明るくするには

for(int i=0;i<100;i++){
    pwmLED(i,100);
}

とすることで、明るさに当たるdutyの値が0→100へとカウントアップされていきます。timeに100を指定しているので、100msごとに少しずつ明るくなるわけです。

回路


GPIOの26ピンから510Ωの抵抗を伸ばし、その先に赤色LEDを接続。そこからはただGNDに繋いだだけのシンプルな回路です。

実際に動いている様子

忙しい人のための完全コピペで動くコード全文

ssidとpasswordは使用するWi-Fiの物に変更して下さい。
いつものごとく、Wi-Fi経由で書き込めるOTAに対応しています。
OTAの記事はこちら

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char* ssid = "*******";
const char* password = "*******";
const int LEDpin = 26;

//LEDのpwm制御関数
void pwmLED(int duty,int time){
  int i=0;
  int j=0;
  for(j=1;j<time;j++){
    for(i=0;i<100;i++){
      if(i<duty){
        digitalWrite(LEDpin,HIGH);
      }else{
        digitalWrite(LEDpin,LOW);
      }
      delayMicroseconds(10);
    }
  }
}
void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  // ArduinoOTA.setHostname("myesp32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.begin();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  pinMode(LEDpin,OUTPUT);
}

void loop() {
  ArduinoOTA.handle();
  //電子ホタル部分
  for(int i=0;i<100;i++){
    pwmLED(i,100);
  }
}

最後に

今回は関数を自作してみましたが、ESP32にはledcなるArduinoでいうところのanalogWrite() に似た関数があります。次回以降それも試してみます(たぶん)。

1件のコメント

返信を残す

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