M5Stick-CとNeopixelでろうそく風の明かりを作る

M5Stick-CにGROVEでNeoPixel(RGBLED)を繋げ、ろうそく風の揺らぎで点灯させてみました。スマホから色や点灯するLEDの数も制御できます。
作り方を以下に簡単に紹介します。

動いている様子

今回使用するコードは全てgithubで公開しています。

環境

  • Windows10
  • Arduino

必要な物品・ライブラリ

必要なライブラリは以下の通り

  • ESPAsyncWebServer
  • AsyncTCP
  • Adafruit_NeoPixel

これらのライブラリのインストールに関しては、以前ESP32でNeoPixelを操作した時に解説しています。以下の記事を参照ください。
【ESP32】非同期Webサーバー上でNeoPixelの彩度・明度・色相を操作する

また、今回はSPIFFS領域と呼ばれるファイル保存領域を使って、htmlファイルなどを直接ESP32に格納します。
SPIFFSにアップロードするには、「ESP32 Sketch Data Upload」が必要です。これはmgo-techさんの解説ページを参考にインストールしてください。

前準備

書き込む前に、githubからdataフォルダのhtml,js,cssファイルをダウンロードし、SPIFFS uploaderからアップロードします。

  1. プロジェクトフォルダを適当な場所に作り、中にdataという名前のフォルダを作り、その中に先程の3つのファイルを入れます。※このフォルダ内が丸ごとM5Stick-Cにアップロードされます。
  2. mgo-tecさんのSPIFFS uploaderの導入方法に従いSPIFFS uploaderを入れる
  3. ESP32 Sketch Data Uploadを選択してM5Stick-Cにデータをアップロードする。

    これでM5Stick-CのSPIFFS領域に3つのファイルがアップロードされました。

コード(コピペで動く)

#include "WiFi.h"
#include <M5StickC.h>
#include "ESPAsyncWebServer.h"
#include <AsyncTCP.h>
#include "SPIFFS.h"
#include <Adafruit_NeoPixel.h>
#define PIN 33 //INが接続されているピンを指定
#define NUMPIXELS 30 //LEDの数を指定
#define ledPin 26
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); //800kHzでNeoPixelを駆動
int saturation = 100;
int value = 0;
int brightness = 1;
int HUE = 32768;
int lednum = 1;
int prevValue = 64;
const char* ssid = "ESP32_RGB";
const char* pass = "esp32";
const IPAddress ip(192,168,0,1);
const IPAddress subnet(255,255,255,0);
double analogValue;
String ledState;
// ポート80にサーバーを設定
AsyncWebServer server(80);
// 実際のピン出力によってhtmlファイル内のSTATEの文字を変える
String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  return String();
}

void setup(){
  M5.begin();
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT); //GPIO02をアウトプットに
  pixels.begin(); //NeoPixelを開始
  // SPIFFSのセットアップ
  if(!SPIFFS.begin(true)){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  //AP(親機)モードの場合
  digitalWrite(ledPin,HIGH);
  WiFi.softAP("esp32_rgb","password");
  delay(100);
  digitalWrite(ledPin,LOW);
  WiFi.softAPConfig(ip,ip,subnet);
  Serial.println(WiFi.softAPIP());
  delay(1000);
  // サーバーのルートディレクトリにアクセスされた時のレスポンス
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    int paramsNr = request->params();
    digitalWrite(ledPin,HIGH);
    Serial.println(paramsNr);
    for(int i=0;i<paramsNr;i++){
        AsyncWebParameter* p = request->getParam(i);
        if(p->name() =="HUE"){
          HUE = p->value().toInt();
        }else if(p->name() == "Brightness"){
          brightness = p->value().toInt();
        }else if(p->name() == "Saturation"){
          saturation = p->value().toInt();
        }else if(p->name() == "lednum"){
          lednum = p->value().toInt();
        }
        OnPixels(HUE,saturation,brightness,lednum);
    }
    request->send(SPIFFS, "/index.html", String(), false, processor);
    digitalWrite(ledPin,LOW);
  });

  // style.cssにアクセスされた時のレスポンス
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/style.css", "text/css");
  });
    // style.cssにアクセスされた時のレスポンス
  server.on("/jquery.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/jquery.min.js", "text/javascript");
  });
  // サーバースタート
  server.begin();
  OnPixels(HUE,saturation,brightness,lednum);
}

void loop(){
//  FirePixels();
  prevValue = CandlePixels(prevValue);
  delay(10);
//  Serial.println(HUE);
//  delay(100);
}

void OnPixels(int hue,int saturation, int brightness,int lednum){
  for(int i=0; i<NUMPIXELS; i++) { //LEDを1つずつ制御 
    if(i < lednum){
      pixels.setPixelColor(i, pixels.ColorHSV(hue, saturation, brightness)); //LEDの色を設定
    }else{
      pixels.setPixelColor(i, pixels.ColorHSV(hue, saturation, 0)); //LEDの色を設定
    }
      pixels.show();   //LEDに色を反映 
//      delay(1);
  }
}
int CandlePixels(int prevValue){
  int currentValue = prevValue + random(-5,6);
  if(currentValue > 255){
    currentValue = 255;
  }else if(currentValue < 1){
    currentValue = 0;
  }
  OnPixels(HUE,saturation,currentValue,lednum);
  return currentValue;
}
void FirePixels(){
  delay(5000);
  for(int value=0;value<128;value++){
    OnPixels(HUE,saturation,value,lednum);
    delay(5);//フェードの速さを調節
  }
  delay(5000);
  for(value=128;value>0;value--){
    OnPixels(HUE,saturation,value,lednum);
    delay(5);
  }
  pixels.clear(); //NeoPixelの出力をリセット
  pixels.show();
}

実行後は「ESP32_RGB」というWi-Fiが飛ぶので、パスワード「esp32」を入力して接続しましょう。

その後ブラウザで「192.168.0.1」を入力すると、以下のような画面が出てきます。

このスライダーを操作することで、NeoPixelの色相、明度、彩度、そして点灯するLEDの数を制御できます。

プチ解説

今回使用するのはCandlePixelsという関数。

int CandlePixels(int prevValue){
  int currentValue = prevValue + random(-5,6);
  if(currentValue > 255){
    currentValue = 255;
  }else if(currentValue < 1){
    currentValue = 0;
  }
  OnPixels(HUE,saturation,currentValue,lednum);
  return currentValue;
}

やっていることは単純で、前の明るさにランダムで±5の値を足しているだけです。

これで急に暗くなったり、また明るくなったりと揺らぎを表現できます。

コメントする

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

Exit mobile version