M5NanoC6の使い方、初期設定、サンプルプログラムで詳しく紹介

M5NanoC6 使い方、初期設定アイキャッチ

「M5NanoC6」の初期設定から使い方をサンプルプログラムを使って詳しく紹介します。
シンプルな構成のデバイスなので専用のライブラリ無しでも入出力からアナログ入力、PWM、I2C通信、Wi-Fi遠隔操作まで動作確認できます。

「コピペ」で動作するサンプルプログラムいくつか準備しましたので、1つづつ動作確認しながら使い方を見ていきましょう。
まだ新しいデバイスのため開発環境の充実はこれからと思います。
今回は「ArduinoIDE」を使った方法をメインに、注意事項も交えて詳しく紹介しています。

ArduinoIDEのインストール方法から使い方は以下のリンクで詳しく紹介しています。

Arduino IDE 2のインストール方法、初期設定、使い方
バージョンアップして使いやすくなったArduino IDE 2のインストールから使い方まで詳しく紹介、便利な機能やM5Stack、ラズパイPicoでの使用方法も紹介します。
スポンサーリンク

1.M5NanoC6とは

「M5NanoC6」とは「M5Stackテクノロジー社」のマイコンボードで、サイズは「23.5×12×9.5mm」と非常に小さいですが、本体ボタン、青色LED、赤外線LED(送信のみ)、NeoPixel(フルカラーLED)がコンパクトに内蔵されています。

他にもシリアル通信はもちろんWi-Fi通信(802.11b /g/n下位互換のWi-Fi6対応)にも対応しており、これらの機能をプログラムで自由に使用することができるため、電子工作やIoTデバイスとして遠隔操作データ監視に利用する等、いろいろなアイデアを形にすることができます。

「USB Type-C」と「GROVEコネクタ」も内蔵していますが、本体があまりにも小さいので、コネクタにコントローラを内蔵したと言った方が正しいのかもしれません^^

現状では開発環境がまだ充実していないため「C言語」ベースの「Arduino IDE」がメインとなりますが、今後「PlatformIO」や「ビジュアルプログラミング(UiFlow)」「Python(MicroPython)」での開発環境も整ってくると思います。

購入に関しては以下のスイッチサイエンスさんがおすすめです。

M5Stack NanoC6
M5Stack NanoC6は、小指サイズの超小型IoT 開発ボードです。ESP32-C6FH4 を搭載、Wi-Fi 6、Matter、Thread、Zigbeeなどの高度な無線通信方式をサポートします。
スポンサーリンク

2.外観

梱包状態は以下のようになります。

M5NanoC6使い方、梱包状態
本体のみで「USB Type-Cケーブル」や「GROVEコネクタケーブル」は付属しないので別途準備する必要があります。

本体の外観は以下のようになります。

M5NanoC6使い方、外観
M5NanoC6使い方、外観
M5NanoC6使い方、外観
M5NanoC6使い方、外観

非常に小さくコンパクトで、「USB」と「GROVE」コネクタをケースで覆っただけのようなもので、小指の第1関節部分とほぼ同寸法です。
ケースは接着ではなく、はめ込みなので外して熱収縮チューブで覆えば、さらに薄く小さくなりますね^^

外部出力端子は2つだけですが、シリアル通信用端子として使用できるので、通信対応デバイスやセンサを使用して無線通信で操作、データ収集するという使い方がメインになりそうです。

「I2C通信」対応センサ等でデータ収集しつつ、外部出力を増設したい時には以下の「4チャンネルリレーユニット」が最適です。

I2C通信リレーの使い方、小型デバイスでも簡単出力増設
2本の信号線で通信できるI2CリレーでI2Cセンサやモータドライバも同時に使用しながら出力不足を解消できます。M5StackのM5NanoC6を使って詳しく紹介
スポンサーリンク

3.仕様一覧表

「M5NanoC6」の仕様は以下表のようになります。

ResourcesParameters
コントローラ(SoC)ESP32-C6FH4@RISC-V 160MHz,4M Flash
Wi-Fi 6,Zigbee 3.0,Thread 1.3, Matter,CDC
Wi-Fi通信2.4GHz Wi-Fi 6 protocol (802.11ax)
下位互換 802.11b /g/n
Bluetooth通信Bluetooth 5(LE)
フルカラーLED(NeoPixel)WS2812
赤外線(IR)※送信のみ赤外線放射距離
0° = 632cm
< 45° = 83cm
< 90° = 29cm
Groveコネクタ電源容量DC 5V @600mA(USB電源に依存します)
待機電流 (Deep Sleep Mode)Type-C 電源 DC 5V@125.5uA
Grove 電源 DC 5V@50uA
待機電流 (ULP Mode)Type-C 電源 DC 5V@252uA
Grove 電源 DC 5V@201.5uA
動作時電流(WIFI mode)IDC 5V @106.2mA
Wi-Fi通信距離約50m(障害物なし)
使用温度範囲0〜40°C
製品サイズ23.5*12*9.5mm
梱包サイズ110*81*11mm
製品重量2.5g
梱包重量11.2g
コントローラの「ESP32-C6」は、まだ新しいもので情報が少なく開発環境も整っていないようなので、しばらく様子を見ながら使っていくことになりそうです。

4.本体機能

本体機能や各機能の配置は以下のようになります。

M5NanoC6使い方、機能

本体裏には各機能の端子番号が書かれていますが、非常に小さいのでイラストで確認してください。

フルカラーLEDは本体ボタン中央の隙間から光るのではなく、ほぼケース全体が透けて光ります。本体が青っぽいので白色で点灯させても青っぽく光り、他の色も青と混ざったような色で光ります。

5.端子機能詳細(入出力/ADC/シリアル通信)

「M5NanoC6」の端子機能は以下表のようになります。

M5NanoC6使い方、端子機能
  • 「IR」の赤外線LEDと「LED」の青色LEDは「HIGH」で点灯します。
  • 「BTN」の正面ボタンは内部抵抗10kΩで「プルアップ」されています。
  • 「RGB」のNoePixelを使用するには「RGB_PWR」を出力設定で「HIGH」にして電源を供給する必要があるので忘れないようにしましょう。
GROVEコネクタ端子「G1/G2」は「UART通信(RXD/TXD)」や「I2C通信(SCL/SDA)」の信号用端子として割り付けて使用できます。
「SPI通信」は出力端子が2個しか無いので物理的に不可能です。

6.開発環境設定

開発環境については、新しいデバイスのためまだ充実していません。
「PlatformIO」については今回は情報のみで「ArduinoIDE」を使う方法で紹介します。

公式のチュートリアルに沿って進めますが、今後変更になる可能性があります。

ArduinoIDEのインストール方法は以下のリンクで詳しく紹介しています。

Arduino IDE 2のインストール方法、初期設定、使い方
バージョンアップして使いやすくなったArduino IDE 2のインストールから使い方まで詳しく紹介、便利な機能やM5Stack、ラズパイPicoでの使用方法も紹介します。

また、使用するボードは「ESP32系」で、ボード情報の更新が必要です。まだ開発段階のベータ版ですが、ここで紹介する方法で進めると「安定版」を上書きしてしまうため注意が必要です。
(一旦削除して安定版をインストールすれば元に戻ります。)

これについては以下の「Lang-ship」さんのサイトで詳しく紹介されていて、上書きせずに別名でボード情報を追加する方法も紹介されてますので、以下にリンクを貼らせていただきます。

M5Stack NanoC6購入
概要 ESP32-C6搭載の小型ボードのNanoC6が発売されたので触ってみました。全体的にかなり好印象ですが、まだまだ開発環境が整っていないので真価を発揮するのはまだ先になりそうな予感がします。 製品 今回は中国と日本で同時発売だったので

・Arduino IDE(ESP32ベータ版)

以下、「M5Stack」公式のチュートリアルに沿って進めます。
「ESP32」のボード情報は安定版のバージョン「2.x」からベータ版の「3.0」に上書きされます。

私はもともとESP32のボードを入れていなかったのでベータ版を入れました。
ベータ版でもいいので最新のものを使用したい方はこのまま進めてください。
(削除して2.xをインストールすれば元に戻ります。)

公式のチュートリアルのリンクは以下になります。

m5-docs
The reference docs for M5Stack products. Quick start, get the detailed information or instructions such as IDE,UIFLOW,Arduino. The tutorials for M5Burner, Firmw...

「ESP32」のバージョン「2.x」から「3.0」への移行に関する詳細情報は、以下の「Espressif社」のサイトでご確認ください。

Migration from 2.x to 3.0 - - — Arduino ESP32 latest documentation

ボード情報の更新

まずは「ESP32C6」のボードが選択できるように「ボード情報」の更新を行います。
ボード情報を更新するには下画像のように[ファイル]→[基本設定]をクリックします。

M5NanoC6 ArduinoIDEの設定

下画像のようなウインドウが表示されたら[追加のボードマネージャのURL:]の矢印部のアイコンをクリックします。

M5NanoC6 ArduinoIDEの設定

次に以下のURLをコピーします。

https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json

コピーしたら下画像のようにURLをテキストボックス内に貼り付けて[OK]ボタンをクリックします。

M5NanoC6 ArduinoIDEの設定

次の画面でも以下のように[OK]ボタンをクリックすると「ボード情報」が更新されます。

M5NanoC6 ArduinoIDEの設定

画面左メニューアイコンの[ボードマネージャ]をクリックし、下画像のように検索窓に「esp32」 と入力すると[esp32]が表示されるので[インストール]をクリックします。

M5NanoC6 ArduinoIDEの設定

インストールが完了したら、以下のように[ツール]→[ボード:]→[esp32]→[ESP32C6 Dev Module]をクリックして、ボードの選択は完了です。

M5NanoC6 ArduinoIDEの設定

USBポートの選択

次に「M5NanoC6」をUSBケーブルでパソコンに接続します。

パソコンに接続したら、下画像のように[ツール]→[ポート:]→[COM番号(ESP32が含まれる表示のあるポート)]を選択します。

M5NanoC6 ArduinoIDEの設定

ポートが選択できたら、プログラムを書き込む準備が整いました。

接続したデバイス名は自動で取得されますが、必ずしも同じデバイス名で表示されるわけではないようです。接続した時に追加で認識されたポートがそのデバイスのポートのため、追加表示されたものを選択しましょう。
たまに書き込みを実行してもポートの接続ができないことがありました。この場合は本体ボタンを押しながら接続してポートを切り替え、書き込んでからUSBを抜き差しすると実行できるようになります。

書き込み

プログラムを書き込むには、以下のようにエディタ部にプログラムを作成し、上メニューの[→]アイコンをクリックします。

M5NanoC6 ArduinoIDEの設定
この後で紹介する「サンプルプログラム」を「コピペ」で貼り付けて、書き込んで動作確認してみましょう。
公式サイトでは、書き込み時には本体ボタンを押しながらUSBを接続してから書き込むように書かれていますが、私の環境ではそのまま接続して書き込むことができました。
もし、書き込みがうまくいかない場合は本体ボタンを押しながらUSBを接続して試してみてください。

・PlatformIO(準備中)

「PlatformIO」については「HOME」画面の「Platforms」から「Espressif 32」をバージョン「6.6.0」にアップデートすることで使用できないことはないようです。

しかし「Board:」は「Espressif ESP32-C6-DebKitM-1」でいいようですが「Framework:」が「Arduino」に対応していません。

今回は深追いせずに対応するのを待ちたいと思います。

7.注意事項

各機能の動作確認をする中でいくつか気になった点があったので以下注意点としてまとめておきます。
今後も気になるものがあれば追加していきます。

・シリアルモニタ出力が表示されない場合

USBシリアルモニタ出力をいつものように「Serial.print()」で指定しましたが、最初は出力できませんでした。

初期設定では出力先が異なるようで、下画像のように[ツール]→[USB CDC On Boot:]→[Enabled]を選択することで出力できるようになります。

M5NanoC6 ArduinoIDEの設定
パソコンと繋いでいる時はいいですが、単体で動作する時は「USB CDC On Boot」が「Enabled」のままだとシリアル出力が実行された時点で動作が停止しました。
単体で動作させる時は「USB CDC On Boot」を「Disabled」にしてから書き込んで使用するようにしましょう。
また、パソコンに接続していても「シリアルモニタ」を起動しておかないと動作が停止して、起動すると動き出しました。

・専用のライブラリは不要

通常はデバイスごとに準備されている専用のライブラリを使用します。

「M5NanoC6」にも専用のライブラリがありますが、現時点では本体ボタンを「ボタンA(BtnA)」として「wasPressed()」や「wasReleased()」が使えるだけなので、特に使用しなくても良いように思います。

使用するには、まだ「GitHub」からダウンロードして「Arduino」の「libraries」フォルダに保存する必要があるので一応以下で紹介しておきます。

まずは、以下の「GitHub」のサイトへアクセスします。

GitHub - m5stack/M5NanoC6
Contribute to m5stack/M5NanoC6 development by creating an account on GitHub.

以下のページが表示されたら[Code]ボタンをクリックして表示される[Download ZIP]をクリックしてダウンロードします。

M5NanoC6ライブラリのダウンロード

次に「ArduinoIDE」のメニューで以下のように[スケッチ]→[ライブラリをインクルード]→[.ZIP形式のライブラリをインストール]をクリックします。

M5NanoC6ライブラリのインストール

以下のようなウインドウが表示されたらダウンロードフォルダにある「M5NanoC6-main.zip」を選択して[開く]ボタンをクリックします。

M5NanoC6ライブラリのインストール

これで「M5NanoC6」のライブラリが使用できるようになりました。

使用方法は以下になります。

/*
  各端子の指定はカッコ内のように指定して使用できます。
  本体青色LED:7(M5NANO_C6_BLUE_LED_PIN)
  本体ボタン:9(M5NANO_C6_BTN_PIN)※Input設定済み
  赤外線(IR)送信:3(M5NANO_C6_IR_TX_PIN)
  フルカラーLED(NeoPixel)電源:19(M5NANO_C6_RGB_LED_PWR_PIN)
  フルカラーLED(NeoPixel)信号:20(M5NANO_C6_RGB_LED_DATA_PIN)
*/

#include "M5NanoC6.h" // ヘッダーファイルを指定

// 初期設定 ---------------------------------------------------
void setup() {
  NanoC6.begin();  // 本体初期化
  // 以下、他の初期設定
}

// メイン -----------------------------------------------------
void loop() {
  NanoC6.update();  // 本体ボタン状態更新
  
 // Arduinoのボタン関数が使用できます。
  if (NanoC6.BtnA.wasPressed()) {   // 本体ボタンが押されたら
    // 処理を記入
  }
  if (NanoC6.BtnA.wasReleased()) {  // 本体ボタンが離されたら
    // 処理を記入
  }
}

ボタン関数が使える以外は特に恩恵は無いように思います・・・

シリアル出力のボーレートは「115200」で初期化されています。
必要に応じて上書きして使用しましょう。

・アナログ入力がおかしい?

アナログ入力値を取得するには以下のように指定しますが、12bitのA/D変換値(0〜4095)ではなく、電圧(mV)で取得されます。

an_val = analogRead(ADC_PIN);

1Vの場合は「1000(mV)」、3.3Vの場合は「3300(mV)」が取得されます。
必要に応じて「0〜4095」になるように換算して使用する必要がありそうです・・・

公式サイトでは「12bitのADC値が取得できる」とあり、電圧(mV)の取得は「analogReadMilliVolts()関数」があるので間違いのように思いますが、今後修正されるのか、本当はこういう仕様なのか・・・不明です。
「サンプルプログラム」では、ひとまず換算して使用するようにしています。

・PWM制御(Ledc関数の変更)

「Ledc関数」はESP32のバージョン3.0になって、使用方法が変わりました。
従来の「ledcSetup()関数」は廃止され「ledcAttach()関数」だけで指定できるようになりました。

// 変更前(バージョン2.x)-----------------------------------------------------
pinMode(PWM_PIN, OUTPUT);                   // PWM用ピンを出力設定
ledcSetup(CHANNEL, FREQUENCY, RESOLUTION);  // PWM設定(チャンネル, 周波数, 分解能)
ledcAttachPin(PWM_PIN, CHANNEL);            // PWMチャンネル割り当て(ピン番号, チャンネル)

ledcWrite(CHANNEL, DUTY);                   // DUTY比を指定して、チャンネルに対して実行

// 変更後(バージョン3.0)-----------------------------------------------------
pinMode(PWM_PIN, OUTPUT);                   // PWM用ピンを出力設定
ledcAttach(PWM_PIN, FREQUENCY, RESOLUTION); // PWM設定(ピン番号, 周波数, 分解能)

ledcWrite(PWM_PIN, DUTY);                   // DUTY比を指定して、ピン番号に対して実行
チャンネルごとに指定するのではなく、ピン番号を指定して実行できるので使いやすくなりました。

8.サンプルプログラム(コピペ)

「コピペ」で動作確認できる「サンプルプログラム」をいくつか準備しました。

基本的な入出力から、内蔵NeoPixelの使い方、アナログ入力、PWM、I2C通信、Wi-Fi遠隔操作等の動作を確認することができます。

いずれの「サンプルプログラム」も専用のライブラリは使用していないので「Arduino.h」を必須のヘッダーファイルとして指定しています。

① Lチカ(本体LED)

まずは本体ボタンと本体LED(青)を使用した、基本的な「Lチカ」動作について確認します。
動作は下画像のように「本体ボタン」を押すと「本体LED(青)」が点灯するものです。

M5NanoC6 Lチカ動作確認

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

/*
  M5NanoC6端子番号
  本体青色LED:7
  本体ボタン:9
  赤外線(IR)送信:3
  フルカラーLED(NeoPixel)電源:19
  フルカラーLED(NeoPixel)信号:20
  Groveコネクタ信号(I/O, ADC, Touch):1, 2
*/
#include "Arduino.h"

#define BLUE_LED_PIN 7  // 青色LED端子番号
#define BTN_PIN 9       // 本体ボタン端子番号

bool old_state = true;  // 前回のボタン状態を格納

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600);  // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  // 入力設定
  pinMode(BTN_PIN, INPUT);  // 本体ボタン
  // 出力設定
  pinMode(BLUE_LED_PIN, OUTPUT); // 本体LED青
}

// メイン -----------------------------------------------------
void loop() {
  bool btn_state = digitalRead(BTN_PIN); // 現在のボタン状態を取得
  if (old_state != btn_state) {  // ボタンの状態に変化があれば
    old_state = btn_state;  // 前回のボタン状態を更新
    if (btn_state) {  // ボタンが離された(HIGH)なら
      digitalWrite(BLUE_LED_PIN, LOW);  // 本体LED消灯
      Serial.println("Button A OFF!");  // シリアル出力
    } else {          // ボタンが押された(LOW)なら
      digitalWrite(BLUE_LED_PIN, HIGH); // 本体LED点灯
      Serial.println("Button A ON!");   // シリアル出力
    }
  }
}

② NeoPixel(本体フルカラーLED)

本体内蔵のフルカラーLED(NeoPixel:WS2812)の使用方法を確認します。
サンプルプログラムを書き込んで実行すると「本体ボタン」を押すたびに、下画像のようにLED色が「白→赤→緑→青」のように変化します。

M5NanoC6 NeoPixel動作確認

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include "Arduino.h"
#include <Adafruit_NeoPixel.h>  // NeoPixel(フルカラーLED)制御用

#define BTN_PIN 9           // 本体ボタン端子
#define RGB_LED_PWR_PIN 19  // NeoPixel電源端子
#define RGB_LED_DATA_PIN 20 // NeoPixel信号端子
#define NUM_LEDS 1  // NeoPixel使用数

// NeoPixel初期化
Adafruit_NeoPixel strip(NUM_LEDS, RGB_LED_DATA_PIN, NEO_GRB + NEO_KHZ800);

// 変数宣言
bool old_state = true;  // 前回のボタン状態を格納
int8_t cnt = 0;         // ボタンON回数カウント

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600);  // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  // 入力設定
  pinMode(BTN_PIN, INPUT_PULLUP);  // 本体ボタン
  // 出力設定
  pinMode(RGB_LED_PWR_PIN, OUTPUT);    // NeoPixel電源(19)
  digitalWrite(RGB_LED_PWR_PIN, HIGH); // NeoPixel電源をHigh設定

  // NeoPixel初期設定
  strip.begin();  // NeoPixel初期化
}

// メイン -----------------------------------------------------
void loop() {
  // 本体ボタン押した時だけ実行
  bool btn_state = digitalRead(BTN_PIN);  // 現在のボタン状態を取得
  if (old_state != btn_state) {  // ボタンの状態に変化があれば
    old_state = btn_state;  // 前回のボタン状態を更新
    if (!btn_state) {  // ボタンが押された(LOW)なら
      cnt++;           // ボタンON回数カウント+1
      Serial.println("Collor Change!");  // シリアル出力
    }
  }

  // NeoPixel点灯処理 (R, G, B)
  switch (cnt) {  // ボタンON回数により分岐
  case 0:
    strip.setPixelColor(0, strip.Color(100, 100, 100)); // NeoPixel色指定(白)
    break;
  case 1:
    strip.setPixelColor(0, strip.Color(255, 0, 0)); // NeoPixel色指定(赤)
    break;
  case 2:
    strip.setPixelColor(0, strip.Color(0, 255, 0)); // NeoPixel色指定(緑)
    break;
  case 3:
    strip.setPixelColor(0, strip.Color(0, 0, 255)); // NeoPixel色指定(青)
    break;
  default:
    cnt = 0; // ボタンON回数0リセット
    break;
  }
  strip.show();   // NeoPixel点灯実行
}

③ 外部入出力

「GROVEコネクタ」の端子を使用して、入出力動作の確認を行います。

端子「G1」にLED(抵抗510Ω接続)を、端子「G2」にスイッチを、下画像のようにブレッドボードで接続して「サンプルプログラム」を書き込むと、スイッチを押すとLEDが点灯する動作が確認できます。

M5NanoC6 入出力動作確認
M5NanoC6 入出力動作確認

スイッチやLEDの使い方は以下のリンクで詳しく紹介しています。

スイッチ(操作用)の使い方。便利なスイッチユニットについても詳しく紹介
スイッチとは「開閉器」とも呼ばれ電気の通り道をつないだり開いたりするものです。 スイッチには人が操作して動作する「操作スイッチ」と、状況によって動作する「検知スイッチ(センサー)」があります。 ここでは「操作スイッチ」について紹介します。
LED(発光ダイオード)の使い方。Lチカでの動作確認方法
LEDが登場するまで光源としては白熱電球が主流でした。白熱電球は電気を熱に変えて光りますがLEDは+と-の電気が結合する時のエネルギーで光り、電気を直接光に変換するため発光効率が非常に良いです。

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include "Arduino.h"

#define BLUE_LED_PIN 7 // 青色LED端子番号
#define BTN_PIN 9      // 本体ボタン端子番号
#define LED_PIN 1      // Grove出力端子(LED)
#define SW_PIN  2      // Grove入力端子(スイッチ)

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600);  // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  // 入力設定
  pinMode(SW_PIN, INPUT_PULLUP);  // スイッチ
  // 出力設定
  pinMode(BLUE_LED_PIN, OUTPUT);    // 本体LED青
  digitalWrite(BLUE_LED_PIN, HIGH); // 本体LED点灯
  pinMode(LED_PIN, OUTPUT);         // 外部LED
}

// メイン -----------------------------------------------------
void loop() {
  if (digitalRead(SW_PIN)) {  // 外部スイッチがOFFなら
    digitalWrite(LED_PIN, LOW);    // 外部LED消灯
    Serial.println("Switch OFF!"); // シリアル出力
  } else {                    // 外部スイッチがONなら
    digitalWrite(LED_PIN, HIGH);   // 外部LED点灯
    Serial.println("Switch ON!");  // シリアル出力
  }
}

④ アナログ入力

アナログ入力動作について、下画像のように「GROVEコネクタ」に接続できる「M5Stack」社製の「ANGLE UNIT(ボリューム)」を使用して接続して動作確認を行います。

「サンプルプログラム」を書き込んでボリュームを操作すると、フルカラーLED(NeoPixel)の点灯色がボリュームから取得したアナログ値に応じて変化するのが確認できます。

M5NanoC6 NeoPixel動作確認

ボリューム(可変抵抗器)やアナログ入力については以下のリンクで詳しく紹介しています。

ボリューム(可変抵抗器)の使い方、つなぎ方、抵抗値計算等を回路図も使って詳しく解説
ボリュームというと音量調節のイメージですが、明るさや回転数等を調整するのにも使用されます。「抵抗(固定抵抗器)」が固定の抵抗値を持つのに対して「可変抵抗器」は抵抗値を調整することができます。このボリューム(可変抵抗器)について紹介します。
ボリュームで7色変化!フルカラーLEDコントローラーを作ろう「ATOM LITE」
ATOM LITE本体のフルカラーLEDの色をボリューム操作で可変させるプログラムの作り方を詳しく紹介。NeoPixel(WS2812B)をFastLEDで制御

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include "Arduino.h"
#include <Adafruit_NeoPixel.h>  // NeoPixel制御用

#define BTN_PIN 9  // 本体ボタン端子
#define ADC_PIN 1  // アナログ入力端子番号
#define RGB_LED_PWR_PIN 19  // NeoPixel電源端子
#define RGB_LED_DATA_PIN 20 // NeoPixel信号端子
#define NUM_LEDS 1          // NeoPixel使用数

// NeoPixel初期化
Adafruit_NeoPixel strip(NUM_LEDS, RGB_LED_DATA_PIN, NEO_GRB + NEO_KHZ800);

// 変数宣言
float an_val;  // アナログ値(0~4095)格納用 ※なぜかmV(0〜3300)で取得されるので換算して使用します・・・
float new_val; // 正しいアナログ値(0~4095)に換算用
float r,g,b;   // LED明るさ指定用(赤、緑、青)
int cnt;       // シリアル出力タイミングカウント用

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600);  // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  // 出力設定
  pinMode(RGB_LED_PWR_PIN, OUTPUT);    // NeoPixel電源(19)
  digitalWrite(RGB_LED_PWR_PIN, HIGH); // NeoPixel電源をHigh設定

  // アナログ入力設定
  pinMode(ADC_PIN, ANALOG); //アナログ入力

  // NeoPixel初期設定
  strip.begin();  // NeoPixel初期化
}

// メイン -----------------------------------------------------
void loop() {
  r = 0;  //LED赤色0リセット
  g = 0;  //LED緑色0リセット
  b = 0;  //LED青色0リセット

  // アナログ入力処理
  an_val = analogRead(ADC_PIN);     //アナログ換算値(0~4095)取得

  // なぜかmVで取得される?ため12bit値へ換算・・・
  new_val = an_val * (4095.0 / 3300.0);        // Max4095になるよう換算
  new_val = (new_val > 4095) ? 4095 : new_val; // 4095を超えるなら4095固定

  //LED色可変
  if(new_val < 1365) {   //アナログ値が1365より小さいなら赤、緑指定
    g = (new_val / 5.353);             //緑を指定(0~255へ換算)
    r = 255 - g;                      //緑が明るくなったら赤を暗く
  } else if(new_val >= 1365 && new_val < 2730) {
                //アナログ値が1365以上2730より小さいなら赤、緑指定
    b = ((new_val - 1365) / 5.353);    //青を指定(0~255へ換算)
    g = 255 - b;                      //青が明るくなったら緑を暗く
  } else if(new_val >= 2730) { //アナログ値が1365以上なら青、赤指定
    r = ((new_val -2730) / 5.353);     //赤を指定(0~255へ換算)
    b = 255 - r;                      //赤が明るくなったら青を暗く
  }
  strip.setPixelColor(0, strip.Color((int)r, (int)g, (int)b));  // NeoPixel色指定(R,G,B)
  strip.show();                                                 // NeoPixel点灯実行

  // シリアル出力表示
  if (cnt == 10) {
    Serial.printf("an_val:%4.0f, new_val:%4.0f\n", an_val, new_val);
    cnt = 0;  // カウント0リセット
  }
  cnt++;      // カウント+1
  delay(100); // 待機時間
}

⑤ PWM

本体LEDの明るさを変化させることで、PWM制御の動作確認を行います。

下画像のように「ANGLE UNIT(ボリューム)」を使用して、アナログ入力値を取得し、アナログ値をPWM制御のDUTY比に設定することでLEDの明るさを変化させます。

M5NanoC6 PWM動作確認

PWM制御については以下のリンクで詳しく紹介しています。(Ledc関数の使い方は少し変更されています。)

PWM制御とは?Arduino(ESP32)コマンドで使い方を詳しく紹介
PWM制御の基本動作からArduinoコマンドを使ったプログラミング方法、サンプルプログラムを使用して音(ブザー)と光(LED)で動作確認しながら使い方を詳しく紹介します。

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include "Arduino.h"

#define BLUE_LED_PIN 7  // 青色LED端子番号
#define BTN_PIN 9       // 本体ボタン端子番号
#define ADC_PIN 1       // アナログ入力端子番号

// 変数宣言
float an_val;  // アナログ値(0~4095)格納用 ※なぜかmV(0〜3300)で取得されるので換算して使用します・・・
float new_val; // 正しいアナログ値(0~4095)に換算用
int cnt;       // シリアル出力タイミングカウント用

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600);  // シリアル通信初期化(ArduinoIDEの「USB CDC on Boot:」設定は"Enable"にしておく)
  // 入力設定
  pinMode(BTN_PIN, INPUT);  // 本体ボタン
  // PWM出力設定(チャンネル自動割付)※ESP32バージョン2.xとは指定方法が異なる
  pinMode(BLUE_LED_PIN, OUTPUT);      // 本体LED青を出力設定
  ledcAttach(BLUE_LED_PIN, 1000, 12); // PWM設定(ピン番号, 周波数, 分解能)
  // アナログ入力設定
  pinMode(ADC_PIN, ANALOG); //アナログ入力
}

// メイン -----------------------------------------------------
void loop() {
  // アナログ入力処理
  an_val = analogRead(ADC_PIN);  //アナログ換算値(0~4095)取得

  // なぜかmVで取得される?ため12bit値へ換算・・・
  new_val = an_val * (4095.0 / 3300.0);        // Max4095になるよう換算
  new_val = (new_val > 4095) ? 4095 : new_val; // 4095を超えるなら4095固定

  // シリアル出力表示
  if (cnt == 10) {
    Serial.printf("an_val:%4.0f, new_val:%4.0f\n", an_val, new_val);
    cnt = 0;  // カウント0リセット
  }
  cnt++;  // カウント+1

  // PWM出力実行(ピン番号を指定)※ESP32バージョン2.xとは指定方法が異なる
  ledcWrite(BLUE_LED_PIN, (int)new_val);  // 青色LEDの明るさをアナログ値で調整

  delay(100);  // 待機時間
}

⑥ I2C通信

「I2C通信」デバイスの使用方法を確認します。

下画像のように「I2C通信」で使用できる「OLED表示器:miniOLED」と「温湿度センサ:ENV IV」を「GROVEコネクタ」で接続して、測定した温度と湿度を表示させて確認します。

M5NanoC6 I2C温度センサOLED動作確認

「miniOLED」と「ENV IV」の使い方については、以下のリンクで詳しく紹介しています。

I2Cデバイスの情報表示に最適MiniOLEDの使い方
超小型0.42インチ(72x40)のOLED有機ELディスプレイ、I2Cデバイスの情報表示に最適MiniOLED(M5Stack社製)の使い方について詳しく紹介します。
M5StickC Plus2 I2C通信で温度、湿度測定ENV IVセンサの使い方
M5StickC Plus2でI2C通信の温湿度気圧センサENV IVをライブラリ使用とライブラリを使用せずI2C通信で直接データ受信する方法で詳しく紹介します。

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include "Arduino.h"
#include <U8g2lib.h>  // miniOLED制御用
#include <Wire.h>     // I2C通信制御用

#define BLUE_LED_PIN 7  // 青色LED端子番号
#define SHT3X_ADDR 0x44 // SHT3X(温度、湿度センサ)I2C通信アドレス

// OLED表示用のインスタンスを作成
U8G2_SSD1306_72X40_ER_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE); // MiniOLED 0.42" 72x40

// 変数宣言
float data[6]; // 温度、湿度受信データ格納用
float t_degC = 0.0;   // 温度換算データ格納用
float rh_pRH = 0.0;   // 湿度換算データ格納用
char t_str[20];       // 温度表示文字列格納用
char rh_str[20];      // 湿度表示文字列格納用

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600); // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  Wire.begin(2, 1);   // I2C通信初期化(SDA, SCL)、グローブコネクタの端子番号を指定
  u8g2.begin();       // OLED初期化

  // 出力設定
  pinMode(BLUE_LED_PIN, OUTPUT);    // 本体LED青
  digitalWrite(BLUE_LED_PIN, HIGH); // 本体LED点灯
}

// メイン -----------------------------------------------------
void loop() {
  // I2Cデータ送信
  Wire.beginTransmission(SHT3X_ADDR); // デバイスアドレスを指定して I2C通信開始
  Wire.write(0xFD);           // 要求コマンド送信(高精度測定を指定)
  Wire.endTransmission(true); // 書き込み完了
  delay(10);                  // データ受信待ち(時間はデータシートによる:0.01s)

  // I2Cデータ受信(温度、湿度それぞれ 測定データ:8bit ×2 + CRC:8bit で合計6byte)
  Wire.requestFrom(SHT3X_ADDR, 6); // 受信データリクエスト(6byte)
  for (int i = 0; i < 6; i++) {    // 6byte分繰り返し
    data[i] = Wire.read();         // 受信データ格納
  }
  // I2C受信データを温度、湿度に換算(計算方法はデータシート確認)
  t_degC = -45 + 175 * (data[0] * 256 + data[1])/65535; // 温度データ換算
  rh_pRH = -6 + 125 * (data[3] * 256 + data[4])/65535;  // 湿度データ換算

  // データをOLEDに表示するために文字列として結合
  sprintf(t_str, "T:%.1f'c", t_degC);  // 温度データ表示用文字列結合
  sprintf(rh_str, "H:%.1f%%", rh_pRH); // 湿度データ表示用文字列結合
  
  // 各データシリアル出力
  Serial.printf("%.1f, %.1f\n", t_degC, rh_pRH);

  // OLED表示
  u8g2.clearBuffer();           // OLED表示初期化
  u8g2.setFont(u8g2_font_helvR14_tr); // フォント設定
  u8g2.drawStr(2, 18, t_str);   // 温度文字列表示
  u8g2.drawStr(2, 38, rh_str);  // 湿度文字列表示
  u8g2.sendBuffer();            // OLED表示出力
  delay(1000);  // 遅延時間
}

⑦ Wi-Fi通信

Wi-Fi通信を使用して、パソコンやスマホのブラウザから遠隔操作する方法を確認します。

下画像のように「M5NanoC6」に「リレーユニット」を接続して遠隔操作します。
本体をサーバーに設定することで、スマホやパソコンのブラウザからアクセスして表示される画面からリレーをON/OFFできます。

操作画面の[ON]ボタンを押すとリレーがONし、本体の青色LEDが点灯します。
[OFF]ボタンを押すとリレーがOFFし、本体の青色LEDも消灯します。

M5NanoC6 Wi-Fi遠隔操作動作確認
M5NanoC6 Wi-Fi遠隔操作動作確認

サーバーに設定した「M5NanoC6」にアクセスするには「IPアドレス(下画像では192.168.0.30)」でもできますが、今回は「マルチキャストDNS」を使用して「mDNS名」として「nano1」を設定しています。

これにより、ブラウザのアドレスバーに「nano1.local(「mDNS名」に「.local」をつける)」のように入力してアクセスすることで「IPアドレス」が取得されて接続することができ、表示器の無い「M5NanoC6」でも「IPアドレス」を確認する必要もなく、接続することができます。

M5NanoC6 Wi-Fi遠隔操作動作確認
M5NanoC6 Wi-Fi遠隔操作動作確認
M5NanoC6 Wi-Fi遠隔操作動作確認
上画像では確認のために「IPアドレス」と「mDNS名」を「miniOLED」に表示させて確認していますが、これは別プログラムで実行したものです。
以下の「サンプルプログラム」にはこの「OLED」表示のプログラムはありません。

サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

「14,15行目」にはお使いのWi-Fiルーターの「SSID」と「接続パスワード」を設定してから書き込んでください。同じ「SSID」に接続しているパソコンや、スマホでアクセスしてください。

#include "Arduino.h"
#include <WiFi.h>       // Wi-Fi接続用
#include <WebServer.h>  // サーバー設定用
#include <ESPmDNS.h>    // ドメインネームでIPアドレス取得用

#define BLUE_LED_PIN 7  // 青色LED端子番号
#define BTN_PIN 9       // 本体ボタン端子番号
#define OUT_PIN 2       // 外部出力端子番号

// 変数宣言
bool state = false; // ボタン状態保持用

// Wi-Fiローカル接続先設定
const char ssid[] = "自宅のWi-FiルーターのSSIDを設定";  // 接続先SSID
const char pass[] = "自宅のWi-Fiルーターのパスワードを設定"; // 接続先パスワード
const char mdnsName[] = "nano1";  // mDNS Name(mdnsName.localで接続可能)

// サーバー設定ポート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>REMOTE-SWITCH</title>
    <style>
      body { display: flex; justify-content: center; height: 100vh; }
      .container { margin-top: 20px;text-align: center; }
      button { height:50px }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>REMOTE-SWITCH</h1>
      <div>
        <button onclick="location.href='/get/btn_on'"> ON </button>
        <button onclick="location.href='/get/btn_off'"> OFF </button>
      </div>
    </div>
  </body>
  </html>
)";

/******************サーバーリクエスト時処理関数 ******************/
// ルートアクセス時の応答関数
void handleRoot() {
  server.send(200, "text/html", html);  //レスポンス200を返しhtml送信
}
// エラー(Webページが見つからない)時の応答関数
void handleNotFound() {
  server.send(404, "text/plain", "404 Not Found!");  //text送信
}
// ブラウザONボタン処理
void btnOn() {
  digitalWrite(BLUE_LED_PIN, HIGH); // 本体LED点灯
  digitalWrite(OUT_PIN, HIGH);      // 外部出力ON
  Serial.println("get:/get/btn_on");
  server.send(200, "text/html", html);  //レスポンス200を返しhtml送信
}
// ブラウザOFFボタン処理
void btnOff() {
  digitalWrite(BLUE_LED_PIN, LOW);  // 本体LED消灯
  digitalWrite(OUT_PIN, LOW);       // 外部出力OFF
  Serial.println("get:/get/btn_off");
  server.send(200, "text/html", html);  //レスポンス200を返しhtml送信
}

// 初期設定 ---------------------------------------------------
void setup() {
  Serial.begin(9600); // シリアル通信初期化(ArduinoIDEの「USB CDC On Boot:」設定は"Enable"にしておく)
  // Wi-Fi接続開始
  while (WiFi.localIP()[0] == 0) { // IPアドレスが取得されるまで繰り返し
    WiFi.begin(ssid, pass);        //ローカル Wi-Fi接続実行
    delay(3000); // 再接続待ち
  }

  // mDNS設定(mdnsName.localでアクセス)
  MDNS.begin(mdnsName);

  // 接続情報シリアル出力表示
  Serial.print("IP:");
  Serial.println(WiFi.localIP());       // IPアドレス(配列)表示
  Serial.printf("mDNS:%S\n", mdnsName); // mDNS名表示

  // サーバー設定
  server.on("/", handleRoot);         //ルートアクセス時の応答関数を設定
  server.onNotFound(handleNotFound);  //Webページが見つからない時の応答関数を設定
  server.on("/get/btn_on", btnOn);    //ボタンオン受信処理
  server.on("/get/btn_off", btnOff);  //ボタンオフ受信処理
  server.begin();                     //Webサーバー開始

  // 入力設定
  pinMode(BTN_PIN, INPUT_PULLUP);  // 本体ボタン

  // 出力設定
  pinMode(BLUE_LED_PIN, OUTPUT); // 本体LED青
  pinMode(OUT_PIN, OUTPUT);      // 外部出力
}

// メイン -----------------------------------------------------
void loop() {
  if (digitalRead(BTN_PIN) == LOW && state == false) { // 本体ボタンがON で stateがfalseなら
    digitalWrite(BLUE_LED_PIN, HIGH); // 本体LED点灯
    digitalWrite(OUT_PIN, HIGH);      // 外部出力ON
    state = true;   // stateをtrueへ
  }
  if (digitalRead(BTN_PIN) == HIGH && state == true) {  // 本体ボタンがOFFなら
    digitalWrite(BLUE_LED_PIN, LOW);  // 本体LED消灯
    digitalWrite(OUT_PIN, LOW);       // 外部出力OFF
    state = false;  // stateをfalseへ
  }
  server.handleClient();  //クライアントからのアクセス確認
  delay(100);             //遅延時間(ms)
}

9.まとめ

超小型で安価なIoTデバイス「M5NanoC6」の基本的な使い方から、NeoPixelやアナログ入力、PWM、I2C通信、Wi-Fi遠隔操作等の使用方法を詳しく紹介しました。

あまりにも小さすぎて、コネクタにコントローラが内蔵されたかのようですが、入出力端子やI2C通信も使用できるため、Wi-Fi経由で遠隔操作やデータ監視を行うには最適のデバイスと思います。

使用しているコントローラがまだ新しいため、開発環境はしばらく「ArduinoIDE」がメインになりそうですが、今後は「PlatformIO」や「UIFlow」でも使用できるようになってくると思います。

本体の機能は必要最低限ですが、通信については「Wi-Fi6」や近距離データ通信の「ZigBee」にも対応しているため、安価で手軽にIoTによる遠隔操作やデータ監視が実現できそうです。

今回で基本的な動作が一通り確認できたので、今後はより具体的なIoTデバイスとしての遠隔操作、データ監視の方法や、Wi-Fi通信環境に依存しない「ZigBee」を利用した独自のセンサネットワークの構築等を、色々試しながら確認していきたいと思います。

I2C通信リレーの使い方、小型デバイスでも簡単出力増設
2本の信号線で通信できるI2CリレーでI2Cセンサやモータドライバも同時に使用しながら出力不足を解消できます。M5StackのM5NanoC6を使って詳しく紹介

コメント

タイトルとURLをコピーしました