「M5NanoC6」の初期設定から使い方をサンプルプログラムを使って詳しく紹介します。
シンプルな構成のデバイスなので専用のライブラリ無しでも入出力からアナログ入力、PWM、I2C通信、Wi-Fi遠隔操作まで動作確認できます。
ArduinoIDEのインストール方法から使い方は以下のリンクで詳しく紹介しています。
1.M5NanoC6とは
2.外観
3.仕様一覧表
4.本体機能
5.端子機能詳細(入出力/ADC/シリアル通信)
6.開発環境設定
・Arduino IDE(ESP32ベータ版)
・PlatformIO(準備中)
7.注意事項
・シリアルモニタ出力が表示されない場合
・専用のライブラリは不要
・アナログ入力がおかしい?
・PWM制御(Ledc関数の変更)
8.サンプルプログラム(コピペ)
① Lチカ(本体LED)
② NeoPixel(本体フルカラーLED)
③ 外部入出力
④ アナログ入力
⑤ PWM
⑥ I2C通信
⑦ Wi-Fi通信
9.まとめ
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コネクタ」も内蔵していますが、本体があまりにも小さいので、コネクタにコントローラを内蔵したと言った方が正しいのかもしれません^^
購入に関しては以下のスイッチサイエンスさんがおすすめです。
2.外観
梱包状態は以下のようになります。
本体の外観は以下のようになります。
非常に小さくコンパクトで、「USB」と「GROVE」コネクタをケースで覆っただけのようなもので、小指の第1関節部分とほぼ同寸法です。
ケースは接着ではなく、はめ込みなので外して熱収縮チューブで覆えば、さらに薄く小さくなりますね^^
「I2C通信」対応センサ等でデータ収集しつつ、外部出力を増設したい時には以下の「4チャンネルリレーユニット」が最適です。
3.仕様一覧表
「M5NanoC6」の仕様は以下表のようになります。
Resources | Parameters |
---|---|
コントローラ(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 |
4.本体機能
本体機能や各機能の配置は以下のようになります。
本体裏には各機能の端子番号が書かれていますが、非常に小さいのでイラストで確認してください。
5.端子機能詳細(入出力/ADC/シリアル通信)
「M5NanoC6」の端子機能は以下表のようになります。
- 「IR」の赤外線LEDと「LED」の青色LEDは「HIGH」で点灯します。
- 「BTN」の正面ボタンは内部抵抗10kΩで「プルアップ」されています。
- 「RGB」のNoePixelを使用するには「RGB_PWR」を出力設定で「HIGH」にして電源を供給する必要があるので忘れないようにしましょう。
6.開発環境設定
開発環境については、新しいデバイスのためまだ充実していません。
「PlatformIO」については今回は情報のみで「ArduinoIDE」を使う方法で紹介します。
ArduinoIDEのインストール方法は以下のリンクで詳しく紹介しています。
また、使用するボードは「ESP32系」で、ボード情報の更新が必要です。まだ開発段階のベータ版ですが、ここで紹介する方法で進めると「安定版」を上書きしてしまうため注意が必要です。
(一旦削除して安定版をインストールすれば元に戻ります。)
これについては以下の「Lang-ship」さんのサイトで詳しく紹介されていて、上書きせずに別名でボード情報を追加する方法も紹介されてますので、以下にリンクを貼らせていただきます。
・Arduino IDE(ESP32ベータ版)
以下、「M5Stack」公式のチュートリアルに沿って進めます。
「ESP32」のボード情報は安定版のバージョン「2.x」からベータ版の「3.0」に上書きされます。
公式のチュートリアルのリンクは以下になります。
「ESP32」のバージョン「2.x」から「3.0」への移行に関する詳細情報は、以下の「Espressif社」のサイトでご確認ください。
ボード情報の更新
まずは「ESP32C6」のボードが選択できるように「ボード情報」の更新を行います。
ボード情報を更新するには下画像のように[ファイル]→[基本設定]をクリックします。
下画像のようなウインドウが表示されたら[追加のボードマネージャのURL:]の矢印部のアイコンをクリックします。
次に以下のURLをコピーします。
コピーしたら下画像のようにURLをテキストボックス内に貼り付けて[OK]ボタンをクリックします。
次の画面でも以下のように[OK]ボタンをクリックすると「ボード情報」が更新されます。
画面左メニューアイコンの[ボードマネージャ]をクリックし、下画像のように検索窓に「esp32」 と入力すると[esp32]が表示されるので[インストール]をクリックします。
インストールが完了したら、以下のように[ツール]→[ボード:]→[esp32]→[ESP32C6 Dev Module]をクリックして、ボードの選択は完了です。
USBポートの選択
次に「M5NanoC6」をUSBケーブルでパソコンに接続します。
パソコンに接続したら、下画像のように[ツール]→[ポート:]→[COM番号(ESP32が含まれる表示のあるポート)]を選択します。
ポートが選択できたら、プログラムを書き込む準備が整いました。
書き込み
プログラムを書き込むには、以下のようにエディタ部にプログラムを作成し、上メニューの[→]アイコンをクリックします。
・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」にも専用のライブラリがありますが、現時点では本体ボタンを「ボタンA(BtnA)」として「wasPressed()」や「wasReleased()」が使えるだけなので、特に使用しなくても良いように思います。
まずは、以下の「GitHub」のサイトへアクセスします。
以下のページが表示されたら[Code]ボタンをクリックして表示される[Download ZIP]をクリックしてダウンロードします。
次に「ArduinoIDE」のメニューで以下のように[スケッチ]→[ライブラリをインクルード]→[.ZIP形式のライブラリをインストール]をクリックします。
以下のようなウインドウが表示されたらダウンロードフォルダにある「M5NanoC6-main.zip」を選択して[開く]ボタンをクリックします。
これで「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()) { // 本体ボタンが離されたら
// 処理を記入
}
}
ボタン関数が使える以外は特に恩恵は無いように思います・・・
・アナログ入力がおかしい?
アナログ入力値を取得するには以下のように指定しますが、12bitのA/D変換値(0〜4095)ではなく、電圧(mV)で取得されます。
an_val = analogRead(ADC_PIN);
1Vの場合は「1000(mV)」、3.3Vの場合は「3300(mV)」が取得されます。
必要に応じて「0〜4095」になるように換算して使用する必要がありそうです・・・
・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遠隔操作等の動作を確認することができます。
① Lチカ(本体LED)
まずは本体ボタンと本体LED(青)を使用した、基本的な「Lチカ」動作について確認します。
動作は下画像のように「本体ボタン」を押すと「本体LED(青)」が点灯するものです。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
/*
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色が「白→赤→緑→青」のように変化します。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#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が点灯する動作が確認できます。
スイッチや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)の点灯色がボリュームから取得したアナログ値に応じて変化するのが確認できます。
ボリューム(可変抵抗器)やアナログ入力については以下のリンクで詳しく紹介しています。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#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の明るさを変化させます。
PWM制御については以下のリンクで詳しく紹介しています。(Ledc関数の使い方は少し変更されています。)
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#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コネクタ」で接続して、測定した温度と湿度を表示させて確認します。
「miniOLED」と「ENV IV」の使い方については、以下のリンクで詳しく紹介しています。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#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」にアクセスするには「IPアドレス(下画像では192.168.0.30)」でもできますが、今回は「マルチキャストDNS」を使用して「mDNS名」として「nano1」を設定しています。
これにより、ブラウザのアドレスバーに「nano1.local(「mDNS名」に「.local」をつける)」のように入力してアクセスすることで「IPアドレス」が取得されて接続することができ、表示器の無い「M5NanoC6」でも「IPアドレス」を確認する必要もなく、接続することができます。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
「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」を利用した独自のセンサネットワークの構築等を、色々試しながら確認していきたいと思います。
コメント
caa45040です。
M5NanoC6のPWMの記事やインストールの記事が
とても参考になりました。
qiitaでリンクを張らせていただきました。
すばらしい記事をありがとうございました。
caa45040さん、いらっしゃいませ^^
記事を読んでいただきありがとうございます。
リンクも感謝です!
最近更新が滞っていますが^^;ぼちぼち更新していきますので
また見に来てください。