「CORE S3」の使い方を、機能や端子配列、デモ画面を確認しながら、タッチパネル(マルチタッチ)やカメラの使用方法、ポートの増設方法、ACアダプター等、外部電源使用時の注意点と合わせて、サンプルプログラムで詳しく紹介します。
カメラ画像をストリーミングサーバーでスマホやパソコンのブラウザから確認する方法は以下のリンクで詳しく紹介しています。
スポンサーリンク
1.CORE S3とは
・外観、梱包状態、付属品
・入出力コネクタ
・SDカードの入れ方注意点
2.デモ画面の紹介
3.色々な電源供給方法
4.基本仕様
5.端子配列、端子機能一覧表
6.ポートの増設方法
7.開発環境の初期設定
・ArduinoIDE
・PlatformIO
・UIFlow2.0
8.サンプルプログラム
・タッチパネル基本編
・タッチパネル応用編:マルチタッチ
・Lチカ、入出力、アナログ入力、PWM、電源ボタン
・I2C通信
・カメラ画像表示
・カメラ画像のjpegデータ変換
9.まとめ
1.CORE S3とは
「CORE S3」は「M5Stack社」のマイコンボードの上位機種で、タッチパネル対応の液晶画面やカメラ、デュアルマイク、スピーカ、振動センサ(6軸 加速度+ジャイロ)、磁気センサ(3軸)、SDカードスロットを内蔵しており、これらを組み合わせて色々なアイデアを試すことができます。
側面に3つの「Groveコネクタ」があり、スイッチやリレー、サーボ、アナログ入力、シリアル通信機器等を接続できます。
電源スイッチも搭載されており、ACアダプター(9〜24V)での使用も可能です。
バッテリー容量は500mAとマイコンボードとしては大容量です。
通信機能は、有線で「I2C」「UART」「SPI(内部M-BUSより)」に対応しており、無線は「Wi-Fi」と「Bluetooth」に対応しています。
・外観、梱包状態、付属品
購入時のパッケージと本体の外観は下画像のようになります。
付属品は以下のようになります。
本体の固定のための部品と、本体を分解するための工具が付属しています。
本体固定用部品は以下のようになり、本体に取り付けてネジ止めや、制御盤等で使用される「DINレール」への取り付けができるようになります。
・入出力コネクタ
本体側面には3つの「Groveコネクタ(PORT A〜C)」があり、Grove対応ユニットや、スイッチ、リレー、サーボ、シリアル通信機器等を簡単に接続することができます。
下側面にはSDカードスロットやリセットボタン、ACアダプターのDCジャック、電源スイッチがあり、右側面にはスピーカーがあります。
上側面には「Groveコネクタ」が2つ、左側面には「Groveコネクタ」が1つとUSB Type-Cコネクタ、電源ボタンがあります。
・SDカードの入れ方注意点
「SDカード」を入れる時は少し注意が必要です。
そのままだと「SDカード」を表にして入れたくなりますが、裏側にして差し込みましょう
上画像のように表向きだと入らないので無理に押し込まないように注意しましょう。
上画像のように裏側にして差し込むのが正解です。
上画像のところまでは軽く入るので、そこから強めに押し込むと「カチッ」と音がして収まります。
取り出すときは、もう一度押し込むと出てきます。
デモ画面の場合、電源が入った状態でSDカードを入れた時には、上画像の側面右のリセットボタンを押して離すと再起動して認識します。
2.デモ画面の紹介
電源を入れると以下のようなデモ画面で各機能の動作を確認することができます。
内蔵バッテリーで動作させるには、電源スイッチを入れてから、電源ボタンを押します。
電源が入ると上画像のような画面が表示されます。
画面が切り替わり上画像のような画面で主な機能や、使用されているICの型式が確認できます。
画面をタッチすると次の画面に切り替わります。
上画像が「ホーム画面」です。各アイコンをタッチすることで動作確認ができるので、矢印部の「WIFI」から確認していきます。
「WIFI」アイコンをタッチすると周辺のWi-Fi電波のスキャンが開始されます。
「ホーム」画面に戻る場合は左上のアイコンをクリックします。
しばらくすると周辺のWi-Fi接続先(SSID)が電波強度の強い順に上から一覧で表示されます。
確認できたら、次の機能を順番に確認していくので、右上のアイコンをクリックしましょう。
次の画面では、画面下中央にあるカメラの画像が確認できます。
上画像矢印部には「近接センサ(PS)」と「照度センサ(ALS)」があり、センサ部を覆うと上画像のようにレベルメーターでセンサの状態の変化が確認できます。
次の画面では、カメラの両サイドにあるマイクの動作を波形で確認できます。
次の画面では、内部電源の入出力を色々切り替えて使用した時の内部状態が確認できます。
これについては「3.色々な電源供給方法」で詳しく紹介します。
次の画面では「加速度センサ」で傾きや「磁気センサ」で方角の確認ができます。
次の画面でSDカードが挿入されている場合には、上画像のように保存されているデータが確認できます。SDカードを入れ替えた場合は「リセットボタン」を押すことで再認識します。
次の画面では、タッチパネルの動作確認として、画面をなぞることで線を描くことができます。
次の画面では、内部で使用されているI2C通信ICのデバイスアドレス一覧が表示されます。
上画像の矢印部を押すことで、外部コネクタに接続したI2C機器も確認ができます。
上画像ではPortA(赤)に「温湿度センサ」を接続しているので、このデバイスアドレスが確認できます。
さらに矢印部にタッチするとPortBの確認もできます。上画像では何も接続されていないため、デバイスアドレスは表示されていません。
さらにPortCも同様に確認できます。
確認が終わったら「ホーム画面」に戻りましょう。
「ホーム画面」に戻ったら、上画像のように画面右上のアイコンをタッチします。
上画像のような画面が表示されます。
「Shutdoun Now」にタッチすると電源OFFになります。「QUIT」にタッチすると「ホーム画面」に戻ります。
「LCD Backlight」にタッチするごとに、画面が暗くなり、真っ暗になってさらにタッチしていくと元の明るさに戻ります。
「Sleep Now」にタッチすると、画面が消えてスリープ状態になり、もう一度タッチすると復帰します。
「Sleep&Wake In 5sec」にタッチするとスリープ状態になり5秒後に自動で復帰します。
「Sleep&Wake In 1min」にタッチするとスリープ状態になり1分後に自動で復帰します。
3.色々な電源供給方法
「CORE S3」では電源管理IC(AXP2101)によって電源の供給方法を切り替えることができます。
以下からデモ画面を使用して、使用可能な電源供給方法を確認していきます。
(以下画像はCORE S3単体で電源スイッチをONにし、バッテリーで駆動した時の状態です。)
・USB IN / BUS OUT
USBは未接続なので、USBから本体へは0Vとなり、バッテリーで駆動しているのが確認できます
・USB IN / BUS IN
バッテリーで本体は駆動していますが「Grove」からの5V出力は無くなり「Grove」から電源供給して使用できます。
・USB OUT / BUS OUT
USBから5Vが出力されるので、モバイルバッテリーのような使い方ができます。
※500mAhしかないので注意です。
・USB OUT / BUS IN
「Grove」から電源を供給して本体を駆動しつつ、USBから電源を出力できます。
「Grove」から電源を供給しないとUSBへは出力されないので、特に用途が思いつきません・・・
プログラムで各設定を行うには以下のように指定します。
M5.Power.setExtOutput(true); // trueで外部(Grove)電源出力設定、falseで入力設定
M5.Power.setUsbOutput(true); // trueでUSB電源出力設定、falseで入力設定
デモ画面では図の矢印を見れば、なんとなく動作は確認できますが「USB」や「ACアダプター」「内部バッテリーの充放電」等、多くの条件の組み合わせがあります。
それぞれが実際にどのような動作になるのかをイメージするのが難しかったため、思いつく動作パターンを一通り動作確認し、以下表にまとめました。
(以下の赤文字は特に指定しない場合の初期状態です。)
表を見てもわかるように、実際に動作確認してみると微妙に複雑です・・・USBから電源出力できるのでモバイルバッテリーのように使うこともできますが、500mAhしかないので一応できるということだけ覚えておいて、赤文字の標準設定で使うのが良さそうです。
4.基本仕様
「CORE S3」の基本仕様は以下表のようになります。
項目 | 仕様 |
---|---|
MCU | ESP32-S3@Xtensa LX7, 240MHz, WIFI, OTGCDC functions |
フラッシュメモリ | 16MB |
PSRAM | 8MB |
USBポート | Type-C |
液晶画面(マルチタッチ対応) | ILI9342C 2インチ/320×240/強化ガラス |
カメラ | GC0308 30万画素 |
照度+近接センサ | LTR-553ALS-WA |
電源管理IC | AXP2101 |
慣性計測ユニット(IMU) | BMI270 6軸 加速度+ジャイロスコープ |
磁気センサ | BMM150 |
リアルタイムクロック(RTC) | BM8563 |
スピーカー | AW88298 16bits-I2S power amplifier chip 1W |
オーディオADC | ES7210, dual microphone inputs |
TFカードスロット | micro SD 16GBまで対応 |
外部電源入力(電源スイッチ付) | DCジャック DC9V〜24V |
内蔵バッテリー | 3.7V 500mAh |
電源ボタン(左側面) | 押してON、6秒長押しでOFF(プログラムで利用可) |
リセットボタン(下側面) | 押してリセット |
製品寸法 | 54 x 54 x 16mm |
梱包寸法 | 101x64x34mm |
製品重量 | 73.3g |
梱包重量 | 97.8g |
スポンサーリンク
5.端子配列、端子機能一覧表
「CORE S3」の端子配列や機能を以下表にまとめました。
本体側面の3つの「Groveコネクタ(PORT A〜C)」からしか外部への出力はありませんが、内部コネクタ(M-BUS)には使用できる端子が他にもいくつかあります。
表の各記号の意味は以下表のようになります。
記号 | 詳細 |
---|---|
○ | I /O(入出力)または、A/D(アナログ入力)使用可 |
PORT A〜C | 本体側面の「Groveコネクタ」に接続されています。カッコ内は各端子番号 |
pu | プルアップ可 |
ー | 使用不可、または非推奨 |
6.ポートの増設方法
「CORE S3」には「Groveコネクタ」で3つのポート(PORT A,B,C)が使用できますが、本体内部には他にも使用可能な端子がいくつかあります。
本体を下画像のように分解すると「MーBUS」と呼ばれるコネクタがあり、ここから各ポートへつながっているのが確認できます。
せっかく使える端子があるので有効活用する方法を紹介します。
「CORE S3」用ではないですが、以下の「CORE2」用の「ExtPort for Core2」を使用するとポートが2つ(Port D,E)増設できます。
裏面には切り替えスイッチがあって他の端子へ接続を切り換えられますが、初期状態(四角で囲まれた番号の端子)のままで使用します。
「CORE S3」と「CORE2」の端子配列を比較したものは下画像になります。
電源や基本的な配列は同じなので「CORE2」のユニットをそのまま使用することができます。
上画像は「CORE S3」と「ExtPort for Core2」の端子番号の対比表です。
実際に「CORE S3」に「ExtPort for Core2」を取り付けると下画像のようになります。
本体内「MーBUS」の端子が「Groveコネクタ」で使用できるようになりました。
「Port B,C」はもともとありますが、並列で使用できるのでI2C通信デバイスの増設等で便利に使用できます。
7.開発環境の初期設定
開発環境の初期設定について「ArduinoI DE」と「PlatformIO」「UIFlow2.0」を使用した場合で紹介します。
・ArduinoIDE
「ArduinoIDE」の初期設定は以下のようになります。
・ボード
M5CORE S3
・ライブラリ
M5CoreS3(バージョン1.0.0)
M5Unified(バージョン0.1.12)
M5Stackでの「ArduinoIDE」の使い方は、以下のリンクで詳しく紹介しています。
・PlatformIO
「PlatformIO」の初期設定は以下のようになります。
ここでは「バージョン6.5.0」で動作確認しています。
・ボード
M5Stack cores3
・ライブラリ
M5CoreS3(バージョン1.0.0)
M5Unified(バージョン0.1.12)
カメラを使用するには以下のメモリタイプ設定をしておく必要があります。
「platformio.ini」ファイルの内容は以下になります。
[env:m5stack-cores3]
platform = espressif32
board = m5stack-cores3
framework = arduino
board_build.arduino.memory_type = qio_qspi ; フラッシュメモリのタイプを指定
board_build.arduino.partitions = app3M_fat9M_16MB.csv ; フラッシュメモリのパーティション設定
lib_deps =
m5stack/M5CoreS3@^1.0.0
m5stack/M5Unified@^0.1.12
「PlatformIO」のインストールから使い方は、以下のリンクで詳しく紹介しています。
・UIFlow2.0
「CORE S3」でも「ビジュアルプログラミング」でプログラミングを行う「UIFlow」が使用できます。
「ビジュアルプログラミング」とは下画像のようにコマンドの書かれたブロックを組み合わせてプログラムを作成するものです。
プログラム作成エリアにコマンドのブロックを準備します。
コマンドのブロックを組み合わせるようにプログラムを作成します。
「UIFlow」には現在「UIFlow1.0」と「UIFlow2.0」がありますが「CORE S3」は「UIFlow2.0」に対応しています
「UiFlow1.0」のダウンロードから使い方については以下リンクにて詳しく紹介していますが「UIFlow2.0」については、まだ日本語に対応していなかったり「CORE S3」ではカメラのコマンドが無い等、一部の機能が使用できないこともあり、ここでは基本的な使用方法の流れだけ紹介します。
以下「UIFlow2.0」の使い方について、ダイジェスト的になりますが、流れを紹介します。
「UIFlow」を使用するには、まず「M5Burner」をインストールしてファームウェアの書き込みを行う必要があります。
「M5Burner」をインストールするには以下の公式サイトにアクセスします。
上画像のようなページが表示されたら、下へスクロールします。
上画像のように「M5Burner」がダウンロードできるので、お使いの環境に合わせて[ダウンロード]ボタンをクリックします。
「M5Burner」をインストールして起動すると上画像のような画面が表示されます。
左メニューから[CORES3]を選択して「UIFlow2.0」の中の[Download]ボタンをクリックします。
ダウンロードが終了したら「CORE S3」とパソコンを接続して「Burn」ボタンで書き込みますが、Wi-Fiの接続情報の登録が必要となります。
ファームウェアの書き込みが完了すると「CORE S3」の本体には以下のような画面が表示されます。
電源が入ると一瞬上画像のような画面が表示されます。
起動すると上画像のような設定画面になります。
Wi-Fi設定が合っていれば、しばらくすると「USER ACOUNT」の下に登録したメールアドレスが表示されます。
次にクラウド上の「UIFlow」開発環境にアクセスするために以下のサイトへアクセスします。
上画像のようなページが表示されたら「UIFlow2.0」の方を選択して[Confirm]ボタンをクリックします。
上のページが表示されたら[Skip]をクリックします。[Start]でチュートリアルが確認できますが英語です。
以降、新規プロジェクト作成時に「ログイン」して、機種の選択を行います。
上画像が開発画面です。
使い方は「UIFlow1.0」の時とほぼ同じですが、まだ日本語には対応していないようです。
8.サンプルプログラム
「CORE S3」の各機能の使い方を「サンプルプログラム」を使って詳しく紹介します。
・タッチパネル基本編
まずはタッチパネルの基本的な使い方を確認していきましょう。
以下のサンプルプログラムでは、タッチパネルに触れたときに画面を赤色に変更し、タッチ部の座標とタッチステータスを表示します。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include <M5CoreS3.h>
M5Canvas canvas(&M5.Lcd); // メモリ描画領域表示(スプライト)のインスタンスを作成
// 変数宣言
int cnt = 0; // タッチポイント数格納用
int x = 0; // タッチx座標格納用
int y = 0; // タッチy座標格納用
int status = 0; // タッチ状態詳細格納用
static constexpr const char* state_name[16] = {
"none", "touch", "touch_end", "touch_begin",
"___", "hold", "hold_end", "hold_begin",
"___", "flick", "flick_end", "flick_begin",
"___", "drag", "drag_end", "drag_begin"}; // タッチ状態詳細リスト
// 初期設定 -----------------------------------------
void setup() {
auto cfg = M5.config(); // 初期設定
CoreS3.begin(cfg);
// 画面の初期設定
canvas.setTextColor(WHITE); // 文字色
// canvas.setTextDatum(middle_center); // テキストの座標基準指定
canvas.setTextSize(1); // テキストサイズ
canvas.setFont(&fonts::Font4); // フォント
canvas.createSprite(M5.Lcd.width(), M5.Lcd.height()); // canvasサイズ(メモリ描画領域)設定(画面サイズに設定)
}
// メイン -----------------------------------------
void loop() {
CoreS3.update(); // 本体状態更新
canvas.fillScreen(BLACK); // 背景初期化
// タッチ処理
cnt = CoreS3.Touch.getCount(); // タッチポイント数を取得
if (cnt) { // タッチが押されていれば(タッチ数が0以外なら)
canvas.fillScreen(RED); // 背景変更
auto t = CoreS3.Touch.getDetail(0); // タッチ部の状態を格納(ID:0)
x = t.x; // タッチ部のx座標を取得
y = t.y; // タッチ部のy座標を取得
status = t.state; // タッチ状態を格納(番号)
}
canvas.setCursor(0, 0); // 座標設定(x, y)
canvas.printf("cnt : %d , x : %3d , y : %3d\n", cnt, x, y); // タッチ座標情報表示
canvas.printf("state : %d , %s\n", status, state_name[status]); // タッチ状態詳細表示
// メモリ描画領域を座標を指定して一括表示(スプライト)
canvas.pushSprite(&M5.Lcd, 0, 0); // (10, 0)座標に一括表示実行
delay(500); // 遅延時間(ms)※タッチ状態確認のため長めに設定
}
・タッチパネル応用編:マルチタッチ
「CORE S3」のタッチパネルは2つのタッチを認識できるマルチタッチに対応しています。
以下のサンプルプログラムでは、画面をA〜Dの4つのエリアに分け、各エリアに触れるとエリアの色が変化し、最大2点のタッチ部の座標とタッチステータスを確認できます。
実際に動作確認すると下画像のようになります。
「B」にタッチするとタッチ部の色が変わり、画面上部にタッチ部の座標とステータスが表示されます。
「A」「B」2箇所にタッチすると、2箇所の色が変わり、画面上部にそれぞれの情報が表示されます。
「B」「D」はうまく反応せず片方の情報しか表示されませんでした。
「A」「D」のように対角は問題なく反応しますが、近いと不安定になります。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include <M5CoreS3.h>
M5Canvas canvas(&M5.Lcd); // メモリ描画領域表示(スプライト)のインスタンスを作成
// 変数宣言
int lcd_w; // 画面幅格納用
int lcd_h; // 画面高さ格納用
static constexpr const char* state_name[16] = {
"none", "touch", "touch_end", "touch_begin",
"___", "hold", "hold_end", "hold_begin",
"___", "flick", "flick_end", "flick_begin",
"___", "drag", "drag_end", "drag_begin"}; // タッチ状態詳細リスト
// ボタン表示用の関数
void drawButton(const char *label, int x, int y, int w, int h, bool touch, int TouchColor, int notTouchColor) {
canvas.fillRect(x, y, w, h, touch ? TouchColor : notTouchColor); // 条件に応じた色でボタンを塗りつぶす
canvas.drawString(label, x + w / 2, y + h / 2); // ボタンのラベルを中央に描画
}
// 初期設定 -----------------------------------------
void setup() {
auto cfg = M5.config(); // 初期設定
CoreS3.begin(cfg);
// 画面の初期設定
canvas.setTextColor(WHITE); // 文字色
canvas.setTextDatum(middle_center); // テキストの座標基準指定
canvas.setTextSize(1); // テキストサイズ
canvas.setFont(&fonts::Font4); // フォント
lcd_w = M5.Lcd.width(); // 画面幅取得
lcd_h = M5.Lcd.height(); // 画面高さ取得
canvas.createSprite(lcd_w, lcd_h); // canvasサイズ(メモリ描画領域)設定(画面サイズに設定)
}
// メイン -----------------------------------------
void loop() {
CoreS3.update(); // 本体状態更新
// タッチパネルのタッチエリア判定
bool btn_A = false; // タッチボタンA状態格納用
bool btn_B = false; // タッチボタンB状態格納用
bool btn_C = false; // タッチボタンC状態格納用
bool btn_D = false; // タッチボタンC状態格納用
int w = lcd_w / 2; // タッチエリア幅算出用
int h = (lcd_h - 40) / 2; // タッチエリア高さ算出用
auto t = CoreS3.Touch.getDetail(0); // タッチ部の状態を格納(ID:0)
u_int cnt = 0, x = 0, y = 0, id = 0, state = 0; // タッチ部の情報格納用
if (t.isPressed()) { // タッチID0が押されていれば
cnt = CoreS3.Touch.getCount(); // タッチ数を取得
canvas.fillScreen(BLACK); // 背景初期化
canvas.setCursor(0, 8); // 座標設定(x, y)
canvas.setFont(&fonts::Font2); // フォント
for (int i =0; i < cnt; i++) { // タッチ数分繰り返す
auto t = CoreS3.Touch.getDetail(i); // タッチ状態を格納
x = t.x; // タッチ部のx座標を取得
y = t.y; // タッチ部のy座標を取得
id = t.id; // タッチID
state = t.state; // タッチ状態を格納(番号)
canvas.printf("id : %d , x : %3d , y : %3d , state : %d ", id, x, y, state); // タッチ座標情報表示
canvas.printf("%s\n", state_name[state]); // タッチ状態詳細表示
if ((x >= 1 && x < w) && (y >= 40 && y <= 40+w)) { // ボタンAの範囲に触れていたら
btn_A = true;
}
if ((x >= 1 && x <= w) && (y >= 40+h && y <= lcd_h)) { // ボタンBの範囲に触れていたら
btn_B = true;
}
if ((x >= w && x <= lcd_w) && (y >= 40 && y <= 40+w)) { // ボタンCの範囲に触れていたら
btn_C = true;
}
if ((x >= w && x <= lcd_w) && (y >= 40+h && y <= lcd_h)) { // ボタンDの範囲に触れていたら
btn_D = true;
}
}
}
canvas.drawFastHLine (0, 40, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
// ボタン表示(A〜D)
canvas.setFont(&fonts::Font4); // フォント
drawButton("A", 0, 40, w, h, btn_A, DARKGREY, RED);
drawButton("B", 0, 40+h, w, h, btn_B, DARKGREY, BLUE);
drawButton("C", w, 40, w, h, btn_C, DARKGREY, GREEN);
drawButton("D", w, 40+h, w, h, btn_D, DARKGREY, ORANGE);
// メモリ描画領域を座標を指定して一括表示(スプライト)
canvas.pushSprite(&M5.Lcd, 0, 0); // (0, 0)座標に一括表示実行
delay(50); // 遅延時間(ms)
}
・Lチカ、入出力、アナログ入力、PWM、電源ボタン
次に基本的な「Lチカ」や入出力の使い方、アナログ入力(A/D変換)、PWM(LEDの明るさ調整)等の使い方を確認します。
電源ボタンについては、プログラムで「クリック」や「長押し」状態を取得できるため、クリック数をカウントするカウンターでその動作を確認します。長押しでカウント数をリセットします。
「赤ボタン」を押すと「出力1」がONし「LED赤」が点灯します。
「青ボタン」を押すと「出力0」がONし「LED青」が点灯します。
ボリュームを操作すると、アナログ入力値と換算電圧の変化が確認できます。
本体左側面の電源ボタンを「クリック」すると「電源ボタンON回数」が増え「長押し」するとリセットされて「0」になるのが確認できます。
さらにPWMの動作確認を行うには、上の「6.ポートの増設方法」で紹介した増設ユニット「ExtPort for Core2」を使用して、以下のように接続します。
「PORT E」に接続したボタン青を押すごとにPWM0の出力のON/OFFが切換えられます。
「PORT D」に接続したLED青はPWM制御され、ボリュームを操作することで下画像のように明るさの調節ができます。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include <M5CoreS3.h>
#define ADC 1 // アナログ入力 PORT A: 2, 1 (SDA, SCL)
#define IN0 8 // Lチカ入力スイッチ PORT B: 8, 9 (I, O)
#define IN1 9
#define OUT0 18 // Lチカ出力 PORT C: 18, 17 (R, T)
#define OUT1 17
#define IN2 6 // PWM ON/OFFスイッチ PORT E: 6, 7(E1, E2) ※I2C使用不可
#define IN3 7
#define PWM0 10 // PWM出力 PORT D: 14, 10 (D1, D2)
// #define PWM1 14 // ※マイクのデータ入力用端子のため使用は非推奨
M5Canvas canvas(&M5.Lcd); // メモリ描画領域表示(スプライト)のインスタンスを作成
// 変数宣言
float ad_val; // アナログ入力値格納用
float v_in = 0; // アナログ入力電圧換算値
bool in_state0 = false, in_state1 = false, in_state2 = false, in_state3 = false; // 入力状態格納用
bool toggle0 = true, toggle1 = true; // トグル動作状態格納用
int count = 0; // 電源スイッチONカウント数格納用
// 状態に応じて円を描画する関数
void drawStatusCircle(bool condition, int x, int y, int color) {
if (condition) {
canvas.drawCircle(x, y, 12); // 塗り潰し無し円
} else {
canvas.fillCircle(x, y, 12, color); // 塗り潰し円
}
}
// 初期設定 -----------------------------------------
void setup() {
auto cfg = M5.config(); // 初期設定
CoreS3.begin(cfg);
Serial.begin(9600); // シリアル通信初期化
delay(1000); // シリアル通信準備待ち
Serial.print("M5CORE S3 I/O Test"); // シリアルモニタ出力
// 入力端子設定
pinMode(IN0, INPUT_PULLUP); // 入力設定(プルアップ)
pinMode(IN1, INPUT_PULLUP);
pinMode(IN2, INPUT_PULLUP);
pinMode(IN3, INPUT_PULLUP);
// 出力端子設定
pinMode(OUT0, OUTPUT); // 出力設定
pinMode(OUT1, OUTPUT);
digitalWrite(OUT0, LOW); // 出力初期化(LOW)
digitalWrite(OUT1, LOW);
// PWM出力端子設定
pinMode(PWM0, OUTPUT ); // PWM0出力を行う端子を出力端子として設定
ledcSetup (1, 500, 12); // PWM0出力波形の初期設定(チャンネル、周波数、分解能bit)
ledcAttachPin(PWM0 ,1); // チャンネルに対する出力端子を設定
// 以下、端子14でも使用可能ですが非推奨のため無効としています。
// pinMode(PWM1, OUTPUT ); // PWM1出力を行う端子を出力端子として設定
// ledcSetup (2, 500, 12); // PWM1出力波形の初期設定(チャンネル、周波数、分解能bit)
// ledcAttachPin(PWM1 ,2); // チャンネルに対する出力端子を設定
// アナログ入力端子設定
pinMode(ADC, ANALOG); // アナログ入力
// 画面の初期設定
canvas.setTextColor(WHITE); // 文字色
canvas.setTextSize(1); // テキストサイズ
canvas.createSprite(M5.Lcd.width(), M5.Lcd.height()); // canvasサイズ(メモリ描画領域)設定(画面サイズに設定)
}
// メイン -----------------------------------------
void loop() {
CoreS3.update(); // 本体更新
// Lチカ動作(入力ボタンON/OFFでLEDがON/OFF)
bool input0 = digitalRead(IN0); // 入力状態取得
if (input0 != in_state0) { // 入力状態に変化があれば
in_state0 = input0; // 入力状態を更新
digitalWrite(OUT0, !in_state0); // 出力状態更新
}
bool input1 = digitalRead(IN1); // 入力状態取得
if (input1 != in_state1) { // 入力状態に変化があれば
in_state1 = input1; // 入力状態を更新
digitalWrite(OUT1, !in_state1); // 出力状態更新
}
// アナログ入力処理
ad_val = analogRead(ADC); // アナログ入力値を取得
v_in = ad_val * (3.3 / 4095); // 3.3Vへ換算
// PWM動作(入力ボタン押すごとに、出力ON/OFF切り換え)
bool input2 = digitalRead(IN2); // 入力状態取得
if (input2 != in_state2) { // 入力状態に変化があれば
in_state2 = input2; // 入力状態を更新
if (input2 == LOW) { // 入力ボタンが押されていれば
toggle0 = !toggle0; // 出力ON/OFF切り換え
}
}
if (toggle0) { // 出力ON(true)なら
ledcWrite(1, ad_val); // アナログ入力値をDuty比に指定してPWM出力(チャンネル, Duty比)
} else { // 出力OFF(false)なら
ledcWrite(1, 0); // PWM出力OFF
}
bool input3 = digitalRead(IN3); // 入力状態取得
if (input3 != in_state3) { // 入力状態に変化があれば
in_state3 = input3; // 入力状態を更新
if (input3 == LOW) { // 入力ボタンが押されていれば
toggle1 = !toggle1; // 出力ON/OFF切り換え
}
}
// 以下、端子14でも使用可能ですが非推奨のため無効としています。
// if (toggle1) { // 出力ON(true)なら
// ledcWrite(2, ad_val); // アナログ入力値をDuty比に指定してPWM出力(チャンネル, Duty比)
// } else { // 出力OFF(false)なら
// ledcWrite(2, 0); // PWM出力OFF
// }
// 電源ボタンON処理
if (M5.BtnPWR.wasClicked()) { // クリックなら
count++; // カウント+1
} else if (M5.BtnPWR.wasHold()) { // 長押し(1秒以上)※6秒押しで電源OFF
count = 0; // カウントリセット
}
// 液晶表示
canvas.fillScreen(BLACK); // 背景設定
canvas.setFont(&fonts::lgfxJapanGothicP_32); // フォント
canvas.setTextColor(WHITE); // 文字色設定(文字色, 背景)
canvas.drawCentreString("CORE S3 I/O Test", 160, 2); // タイトル表示処理
canvas.drawFastHLine (0, 40, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
// 出力状態(円を描画)表示
canvas.drawString("出力0:", 5, 45); // 項目表示
drawStatusCircle(in_state0, 130, 65, BLUE); // 円描画関数呼び出し
canvas.drawString("出力1:", 5, 80);
drawStatusCircle(in_state1, 130, 100, RED);
canvas.drawString("PWM0:", 165, 45);
drawStatusCircle(!toggle0, 290, 65, BLUE);
canvas.drawString("PWM1:", 165, 80);
drawStatusCircle(!toggle1, 290, 100, RED);
canvas.drawFastHLine (0, 125, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
// アナログ入力値表示
canvas.setCursor(0, 130); // 座標設定(x, y)
canvas.printf("AD= %4.0f, V= %4.2fv\n", ad_val, v_in); // 表示内容
canvas.drawFastHLine (0, 170, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
// 電源ボタンクリックカウント数表示
canvas.setCursor(0, 180); // 座標設定(x, y)
canvas.printf("電源ボタンON回数= %d\n", count); // 表示内容
// バッテリー容量表示
canvas.setFont(&fonts::Font2); // フォント
canvas.setCursor(275, 225); // 座標設定(x, y)
canvas.printf("%4d%%", M5.Power.getBatteryLevel()); // バッテリー容量表示(0〜100%)
// メモリ描画領域を座標を指定して一括表示(スプライト)
canvas.pushSprite(&M5.Lcd, 0, 0); // (0, 0)座標に一括表示実行
delay(50); // 遅延時間(ms)
}
・I2C通信
I2C通信について、温湿度センサ「ENV IV」を使用して、下画像のように温度と湿度を表示させることで動作を確認します。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include <M5CoreS3.h>
#include <Wire.h>
#define SHT3X_ADDR 0x44 // SHT3X(温度、湿度センサ)I2C通信アドレス
M5Canvas canvas(&M5.Lcd); // メモリ描画領域表示(スプライト)のインスタンスを作成
// 変数宣言
unsigned int data[6]; // 温度、湿度受信データ格納用
float t_degC = 0.0; // 温度換算データ格納用
float rh_pRH = 0.0; // 湿度換算データ格納用
// 初期設定 -----------------------------------------
void setup() {
auto cfg = M5.config(); // 初期設定
CoreS3.begin(cfg);
// I2C通信設定
Wire.begin(CoreS3.Ex_I2C.getSDA(), CoreS3.Ex_I2C.getSCL()); // PORT A の場合 SDA=2, SCL=1
// Wire.begin(9, 8); // PORT B の場合 SDA=9(O), SCL=8(I)
// Wire.begin(17, 18); // PORT C の場合 SDA=17(T), SCL=18(R)
// Wire.begin(10, 14); // PORT D の場合 SDA=10(D2), SCL=14(D1) ※端子14は非推奨ですが使えました。
// PORT E ではI2Cは機能しません。
Serial.begin(9600); // シリアル通信初期化
delay(1000); // シリアル通信準備待ち
Serial.print("M5CORE S3 I2C Test"); // シリアルモニタ出力
// 画面の初期設定
canvas.setTextColor(WHITE); // 文字色
canvas.setTextSize(1); // テキストサイズ
canvas.createSprite(M5.Lcd.width(), M5.Lcd.height()); // canvasサイズ(メモリ描画領域)設定(画面サイズに設定)
}
// メイン -----------------------------------------
void loop() {
CoreS3.update(); // 本体更新
// I2Cデータ送信
Wire.beginTransmission(SHT3X_ADDR); // デバイスアドレスを指定して I2C通信開始
Wire.write(0xFD); // 要求コマンド送信(高精度測定を指定)
Wire.endTransmission(true); // 書き込み完了
delay(10); // データ受信待ち(時間はSHT40のデータシートによる: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(); // 受信データ格納
}
// 受信データを温度、湿度に換算(SHT40のデータシートより抜粋)
t_degC = -45 + 175 * (data[0] * 256 + data[1])/65535;
rh_pRH = -6 + 125 * (data[3] * 256 + data[4])/65535;
if (rh_pRH > 100) {
rh_pRH = 100;
}
if (rh_pRH < 0) {
rh_pRH = 0;
}
// 液晶表示処理
canvas.fillScreen(BLACK); // 画面初期化
canvas.setFont(&fonts::lgfxJapanGothicP_32); // フォント
canvas.drawCentreString("CORE S3 I2C Test", 160, 2); // タイトル表示処理
canvas.drawFastHLine (0, 40, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
// I2C通信データ表示
canvas.setCursor(0, 45); // 座標設定(x, y)
canvas.setFont(&fonts::lgfxJapanGothicP_40); // フォント
canvas.printf(" 温度: %.1f℃\n", t_degC); // 温度表示
canvas.printf(" 湿度: %.1f%%\n", rh_pRH); // 湿度表示
// メモリ描画領域を座標を指定して一括表示(スプライト)
canvas.pushSprite(&M5.Lcd, 0, 0); // (0, 0)座標に一括表示実行
delay(500); // 遅延時間(ms)
}
・カメラ画像表示
「CORE S3」の最大の特徴でもあるカメラについて、まずは基本的なリアルタイム画像表示から確認していきます。
サンプルプログラムは画像表示だけのシンプルなプログラムにしています。
以下の「GitHub」のプログラム例を参考にしました。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include "M5CoreS3.h"
int disp_w; // 画面幅格納用
int disp_h; // 画面高さ格納用
// 初期設定 ------------------------------------------------------------------
void setup() {
auto cfg = M5.config(); // 本体初期化
CoreS3.begin(cfg);
disp_w = CoreS3.Display.width(); // 画面幅取得
disp_h = CoreS3.Display.height(); // 画面高さ取得
CoreS3.Camera.begin(); // カメラ初期化
}
// メイン --------------------------------------------------------------------
void loop() {
// カメラからフレームを取得して表示
if (CoreS3.Camera.get()) {
CoreS3.Display.pushImage(0, 0, disp_w, disp_h, (uint16_t *)CoreS3.Camera.fb->buf); // QVGA表示 (x, y, w, h, *data)
CoreS3.Camera.free(); // 取得したフレームを解放
}
}
・カメラ画像のjpegデータ変換
基本的なカメラの使用方法が確認できたので、次はカメラのデータを画像データ(jpeg)として取得する方法を確認します。
サンプルプログラムでは、下画像のように画面にタッチした時の画像をjpegデータとして画面に表示させる自撮りカメラの動作が確認ができます。
画面左にカメラで撮影している画像が表示されます。
画面にタッチする度に、その時のカメラの画像をjpegデータに変換し、画面右に表示していきます。
サンプルプログラムは以下になります。「コピペ」して書き込んでください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。
#include "M5CoreS3.h"
// 変数宣言
int disp_w; // 画面幅格納用
int disp_h; // 画面高さ格納用
// 初期設定 ------------------------------------------------------------------
void setup() {
auto cfg = M5.config(); // 本体初期化
CoreS3.begin(cfg);
CoreS3.Display.setTextColor(CYAN); // 文字色
CoreS3.Display.setFont(&fonts::Orbitron_Light_24); // フォント
CoreS3.Display.setTextSize(1); // テキストサイズ
// 画面サイズを取得
disp_w = CoreS3.Display.width(); // 画面幅
disp_h = CoreS3.Display.height(); // 画面高さ
if (!CoreS3.Camera.begin()) { // カメラの初期化に失敗したら
CoreS3.Display.drawCentreString("Camera Init Fail", disp_w / 2, 185); // エラー表示
}
CoreS3.Display.drawCentreString("Camera", 80, 125); // 文字表示
CoreS3.Display.drawCentreString("jpeg", 240, 125);
CoreS3.Display.drawFastHLine (0, 175, 360, WHITE); // 指定座標から水平線(x, y, 長さ, 色)
CoreS3.Display.drawCentreString("Please touch display!", disp_w / 2, 185);
}
// メイン --------------------------------------------------------------------
void loop() {
CoreS3.update(); // 本体状態更新
// カメラからフレームを取得して処理
if (CoreS3.Camera.get()) {
if (CoreS3.Touch.getDetail(0).wasPressed()) { // 画面のタッチが検出されたら
uint8_t *out_jpg = NULL; // JPEG画像データ用のポインタと長さを初期化
size_t out_jpg_len = 0;
frame2jpg(CoreS3.Camera.fb, 255, &out_jpg, &out_jpg_len); // カメラのフレームバッファをjpegに変換
CoreS3.Display.drawJpg(out_jpg, out_jpg_len, 160, 0, disp_w, disp_h, 0, 0, 0.5, 0.5); // 座標を指定して半分のサイズで表示
free(out_jpg); // メモリ解放
}
// CoreS3.Display.pushImage(0, 0, disp_w, disp_h, (uint16_t *)CoreS3.Camera.fb->buf); // オリジナルサイズ(QVGA)表示
CoreS3.Display.pushImageRotateZoom(0, 0, 0, 0, 0, 0.5, 0.5, disp_w, disp_h, (uint16_t *)CoreS3.Camera.fb->buf); // 半分サイズで表示
CoreS3.Camera.free(); // 取得したフレームを解放
}
}
9.まとめ
「CORE S3」の基本の使い方から、タッチパネル(マルチタッチ)、カメラの使用方法、ポートの増設方法等について詳しく紹介しました。
「CORE S3」はM5Stack社のマイコンボードの上位機種で、「CORE2」と同等の機能を備えていますが、最大の違いはカメラが搭載されたところです。
他にも近接センサーや磁気センサ、ACアダプター(電源スイッチ付)、側面ポート(Groveコネクタ)が追加されました。
多くの機能が追加されたため、価格が高価(ほぼ1万円)なのが難点ですが・・・カメラ搭載で、自由に割り付けて使用できる端子の数も多く、用途の幅がかなり広がったと思います。
今回紹介しきれなかった機能も、まだまだあるので次回ももう少し「CORE S3」について、活用方法を探ってみたいと思います。
コメント