M5Stack NanoC6でNeoPixelを操作する


アドベントカレンダーの記事ですので、クリスマスに合わせた内容がよいと思い、クリスマスツリーのイルミネーション用にLEDを光らせることにしました。

光らせるのはこちらのNeoPixelタイプのフルカラーLEDです。

https://www.akiba-led.jp/product/1026

コントロールにはM5Stack NanoC6を使おうと思います。

https://www.switch-science.com/products/9570

小さくて1000円くらいで買えるのでとてもいいですね。

## 準備

NanoC6はUIFLowに対応していないので、Arduino IDEを使い開発します。
[このページ](https://docs.m5stack.com/ja/arduino/m5nanoc6/program)の説明通りに設定していきます。


デバッグなどのために `Serial.println()` を使いたい場合、
"ツール" → "USB CDC On Boot" → "Enabled" に設定しないと表示されないので注意です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3166965/b57c945b-618b-9bd9-39a1-1ee8199b19e9.png" width="600px">

# 接続

M5NanoC6とNeoPixelを接続します。
NeoPixelとの接続には、簡単に接続ができるGROVEコネクタを使います。今回はLEDの個数もあまり多くないので、電源もここから取ろうと思います。

NeoPixelには接続向きがあります。矢印などが書いてあるので確認して接続してください。

M5NanoC6への給電はモバイルバッテリーを使います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3166965/5e06ef79-25be-b2df-3d11-72e6ac97f305.jpeg" width="500px">

| 端子 | Pin No |
|:-:|:-:|
| G(GND) | G |
| 5V(VCC) | 5V |
| G2 | GPIO2 |

----

一部のみの紹介になりますので、ソースコードの全体は[こちら](https://gist.github.com/nooooon/a301a7fa539abeb4f4871e5f2cba7811)に上げてあります。


## LED制御
Arduino IDEのライブラリマネージャーからAdafruit NeoPixelをインストールします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3166965/1ca13a29-1956-453c-27e8-dbd404caa212.png" width="500px">


```c
#include <Adafruit_NeoPixel.h>

#define LED_PIN 2 // GPIOのピン番号
#define LED_COUNT 50 // LEDの個数

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// 開始
strip.begin();

// 色を設定
strip.setPixelColor(i, targetColor);

// LEDの状態を更新
strip.show();
```


## web server
サーバーを立てて、ブラウザからLEDの色をコントロールできるようにしようと思います。


Wifiに接続します。
```c
// WiFi station modeで接続
WiFi.mode(WIFI_STA);

// SSIDとパスワードを設定
WiFi.begin(ssid, pass);       

// 接続されるまで繰り返します
while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    if (WiFi.status() == WL_CONNECT_FAILED) {
        Serial.println("Connect Failed");
    }
}
Serial.println("Connected");
```

ブラウザで表示されるHTMLを作成し、設定します。

```c
// ポート番号80でサーバーを定義
WebServer server(80);

// htmlは R"()" 内に記載
char html[] = R"(
  <!DOCTYPE html>
  <html lang="jp">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Color Select</title>
    <script>
      document.addEventListener('DOMContentLoaded', function() {
        const form = document.getElementById("form")
        const submitButton = document.getElementById("submit-button")
        
        submitButton.onclick = () => {
          const formData = new FormData(form)
          const action = form.getAttribute("action")
          const options = {
            method: 'POST',
            body: formData,
          }
          fetch(action, options).then((e) => {
            if(e.status === 200) {
              return
            }
          })
        }
      })
    </script>
    <style>
      // 省略
      // CSSを記載
    </style>
  </head>
  <body>
    <!-- 省略 -->
    <!-- LEDの色を選択するためのフォームを配置 -->
  </body>
  </html>
)";

void handleRoot() {
    // POSTで送られた値を取得
    if (server.method() == HTTP_POST) {
        String val = server.arg("color");

        // 色を変える
        changeColorSequential(val.c_str(), 10); 
    }

    // 値をクライアントに返す
    server.send(200, "text/html", html);
}

void setup() {
    // ルートアクセス時のHTMLを登録
    server.on("/", handleRoot);
    // サーバー開始
    server.begin();
}
```


`WiFi.localIP`で確認できるIPにブラウザからアクセスします。
```c
WiFi.localIP();
```

## 完成

ブラウザで選択した色へと変化するようになりました:christmas_tree:

<iframe width="331" height="588" src="https://www.youtube.com/embed/B7h_Tfj6p1M" title="test M5 dmx Base 2" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>