1 of 56

M5Stackハンズオン

2024 10/19

無断転載・外部公開・外部アクセス禁止

2 of 56

何をやる?

目標

  1. IoT開発ボードのM5Stackでの開発を覚える
    1. Displayに描画できる
    2. Core2内蔵のモジュールを使うことができる
    3. I2C通信を用いて拡張センサからデータを取得できる
  2. M5Stackの開発環境であるPlatformIOでの開発を覚える

3 of 56

メンバー紹介

学番: 21FI113

氏名: 山嵜伶馬

趣味: アニメ, 散歩

times: #9_times_b4_reima

#5_cpslab_sensors

技術: C, 組込み周り

ラボ: CPSLab機材管理委員長

4 of 56

機材配布

  • M5Stack Core2
    • 本体
    • USB AtoC
  • M5Stack用温湿度気圧センサユニット ENV Ⅲ

5 of 56

M5Stackとは?

6 of 56

M5Stackとは?

M5Stack社が提供するESP32ベースのモジュール型開発プラットフォーム(MCU)

  • 多くの拡張ボードやモジュールが用意されている
  • 様々なシリーズがある(Core, Stick, Atom, Stamp, …)

WiFiやBluetoothでの通信が可能であり, 様々なセンサ, モジュールと組み合わせることで, 簡単にIoTプロトタイピングができる!

他にもマイコンはあるがM5StackはWiFi接続可+内蔵バッテリー内蔵のものが多い

7 of 56

環境構築

8 of 56

Arduino IDE vs PlatformIO

このハンズオンでは, VSCodeの拡張であるPlatformIOを使用する

  • プロジェクトごとに必要なライブラリのみをインストールすることができる
  • Arduino IDEはコード補完が遅い(コンパイル時に指摘されてブチギレ)

こコ

こン

のパ

スイ

ペル

ル時

がで

違す

いが

9 of 56

実は両方入れておくべきかも

岩井研は最新のESP32が搭載されたM5Stackシリーズも購入する

=>「PlatformIOが対応していない!」となることがあり得るかも!?

10 of 56

USBシリアルドライバインストール

M5Stack Core2ページからUSB認識用のドライバをインストールする

Driver Installationから自分のPCのOSに合わせたドライバをダウンロードする

  • CP210x_VCP_Windows
  • CP210x_VCP_macOS
  • CP210x_VCP_Linux

ダウンロードしたzipを展開

CP210xVCPInstaller_x64_v6.7.0.0を実行

11 of 56

PlatformIO

  1. VSCodeを起動(入ってなかったらインストール)
  2. 画面左のExtensions(拡張機能)を選択
  3. 検索バーで「PlatformIO IDE」と入力
  4. PlatformIO IDE(オレンジのアリ)を選択
  5. Installを選択
  6. 画面左にアリのマークがあればOK

←2

←3

←4

←6

↑5.ここがInstall

12 of 56

とりあえずHello World

13 of 56

プロジェクト作成

  1. 画面左のPlatformIO(アリ)を選択
  2. PIO Home > Openを選択
  3. New Projectを選択

←2

←3

←1

14 of 56

プロジェクト作成

Project Wizard

Name: 任意のプロジェクト名を入力

Board: 開発ボードの選択 => M5Stack Core2を選択する

Framework: 何のフレームワークを使用するかを選択する => Arduino

Location: チェックが入っているとデフォルトの場所におかれる

Finishを押すとプロジェクトが作成される

15 of 56

プロジェクト構成

HandsOn

  • .pio : プロジェクトのビルド時に自動的に生成する一時ディレクトリ
  • build : ビルド後に生成されるファイル(キャッシュなど)
  • libdeps : PlatformIO経由でインストールしたライブラリの格納場所
  • .vscode : VSCodeの設定ファイルが格納されている
    • c_cpp_properties.json : C/C++拡張機能に関連する設定
    • extensions.json : VSCodeの拡張機能の定義
    • launch.json : VSCodeのデバッガ
  • include : ヘッダーファイル(*.h)を格納する
  • lib : プロジェクトで使用するライブラリ(GitHubでダウンロードしてきたものを格納する)
  • src : ソースコードを格納する
    • main.cpp : メインのソースコードを記述する
  • test : テスト用のコードを格納する
  • .gitignore : Git管理の対象外とするファイルの指定(.pioとか管理する必要ないよね)
  • platformio.ini : プロジェクトの設定ファイル

16 of 56

開発に必要なライブラリ

Arduino

  • ライブラリというよりもフレームワーク
  • PlatformIOはC++ベースなので.inoと同様に開発できるようにするために必要
    • void setup()やvoid loop(), Serialなどを含んでいる
  • インストールする必要はない(フレームワークの選択で含まれるはず?)

M5Unified

  • M5Stackには複数シリーズあるが, 実はそれぞれ開発できるライブラリが異なる
    • M5Stack Basic: M5Stack
    • M5Stack Core2: M5Core2
    • M5StickC Plus: M5StickCPlus
  • M5Unifiedを利用することで全シリーズで共通の操作が可能となっている
  • PlatformIO経由でインストールする必要がある

17 of 56

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

  1. PIO HOMEからLibrariesを選択する
  2. 検索バーで「M5Unified」と入力し, Enterキーを押す
  3. 検索結果からM5Unifiedを探し, クリックする
  4. インストールしたいプロジェクトを選択する
  5. Addを押す(待てばライブラリが追加される)

←1

←2

←3

←4

←5

18 of 56

platformio.ini

env, platform, board, framework

  • 基本変更する必要なし
  • 変更するくらいなら新規プロジェクト作成する方が良い

lib_deps

  • librariesで追加したライブラリが記述される
  • 直接記述することでライブラリの追加もできる(librariesの工程を省くことができる)

upload_port

  • どのデバイスに書き込むか(ESP32系は不要だった気がする)

monitor_speed

  • PCとシリアル通信するためのボーレート
  • 基本的には115200

19 of 56

Hello World

コードのことは考えずにとりあえずHello World(src/main.cppに以下を入力)

20 of 56

書き込み

M5Stack Core2とPCをUSB AtoCでつなぐ

画面右上または左下から

  • (Build)
    • プログラムをビルドする
  • (Upload)
    • ビルドとマイコンへの書き込みをまとめて行う

をクリックする

21 of 56

Hello World

書き込みが完了すればCore2のディスプレイにHello Worldが描画される

Build or Uploadに成功する

Build or Uploadに失敗する

22 of 56

基本的な文法

23 of 56

C, C++由来の文法

#include <XXX.h>

  • 指定されたヘッダーファイルをプログラムに取り込む
  • ヘッダーファイルには, 定数, データ型の定義, マクロ, 構造体などが含まれる
  • インストールやGitHubからダウンロードしたライブラリを使うときに利用する

  • 静的型付けダヨ(でも型付けしてくれるautoはあるよ)
  • ポインタもあるよ(char*など)
  • uint型(符号なし整数)とかもあるよ
  • ただしString型は存在するよ

あとは自分で調べてね(⋈◍>◡<◍)。✧♡

24 of 56

Arduino由来の文法

void setup()

  • マイコンの電源が入れられた時に一度だけ呼び出す
  • 普通は初期設定やセンサの初期化などを行う

void loop()

  • setup()の後に繰り返し実行される(永遠に)
  • 普通はセンサデータの取得や, 送受信などを行う

25 of 56

M5Unifiedで必要な記述

#include <M5Unified.h>

  • M5Unifiedの取り込み(これが無いとM5Unified.hに含まれているものは使えない)

auto cfg = M5.config();

  • 初期化オプションを取得する(M5Unifiedでは必須)

M5.begin(cfg);

  • 初期化. 引数として初期化オプションが必要

26 of 56

M5Stack Core2の内蔵機能を使う

27 of 56

M5Stack Core2

M5Stack Core2で使える機能

  • ディスプレイ(M5.Display): ディスプレイに文字や図形などを描画できる(ILI9342C)
  • タッチスクリーン(M5.Touch): ディスプレイをタッチした場所を取得できる(FT6336U)
  • ボタン(M5.BtnA, M5.BtnB, M5.BtnC): ボタンが押されたかなどを知ることができる
  • I2Sパワーアンプ, スピーカー(M5.Speaker): 音を出せる(NS4168, 1W-0928)
  • バイブレーション(M5.Power.Axp192): 振動させることができる
  • マイクロフォン(M5.Mic): 音声データを取得できる(SPM1423)
  • 6軸IMU(M5.Imu): 3軸加速度, 角速度を取得できる(MPU6886)
  • RTC(M5.Rtc): リアルタイムクロック(BM8563)
  • TFカードスロット(SD): SDカードにデータを保存できる
  • Groveポート(M5.Ex_I2C, Wire): I2C, GPIO, UARTなどで拡張モジュールと通信できる

括弧内(M5.Displayなど)のクラスを使用することで各機能にアクセスできる

基本的にM5.begin()で初期化される

ピンを使って配線もできるがパス(電子工作ハンズオンでやるかも)

背面を取り外して拡張モジュールを取り付けられるが今回はやらない

28 of 56

Display

ディスプレイの描画をする

M5.Display(M5GFX)クラスを利用する(M5.Display.print(“Hello World”);)

主なメソッド(文字描画系)

M5.Display.startWrite() → 描画の開始を宣言(この後に描画系のメソッド, endWrite()を記述することで描画速度が向上する)

M5.Display.setCursor(x座標, y座標) → 描画開始地点の設定(M5Stack Core2のディスプレイのサイズは320x240)

M5.Display.print(“文字列”) → 文字列を描画する

M5.Display.println(“文字列”) → 文字列を描画する. 末尾で改行をする

M5.Display.printf(“文字列”, 変数...) → 文字列を描画する. フォーマット指定子を利用することで, 変数の埋め込みが可能

M5.Display.endWrite() → 描画の終了を宣言(startWrite()とセットで使用する)

M5.Display.clearDisplay() → ディスプレイを何も描画されていない状態にする

29 of 56

Display

M5.Display.println(“Hello”);

M5.Display.print(“World”);

M5.Display.printf(“Temperature: %f\n”, temperature);

M5.Display.printf(“Humidity: %f\n”, humidity);

30 of 56

Display

図形描画系

M5.Display.drawPixel(x, y) → (x, y)にピクセルの描画をする

M5.Display.drawLine(x0, y0, x1, y1[, 色]) → (x0, y0)から(x1, y1)に線を引く

M5.Display.drawCircle(x, y, 半径r[, 色]) → (x, y)を中心とした半径rの指定している色の枠の円を描画する

M5.Display.fillCircle(x, y, 半径r[, 色]) → (x, y)を中心とした半径rの指定している色で塗りつぶした円を描画する

M5.Display.width() → ディスプレイの幅を返す. 描画系で超便利

M5.Display.height() → ディスプレイの高さを返す. 描画系で超便利

drawXXX, fillXXXにはTriangle, Rect, Arcなどもある

[]は省略可. setColorでも指定可能. デフォルトは黒?

31 of 56

Display

M5.Display.drawLine(0, 0, M5.Display.width(),

M5.Display.height(), WHITE);

M5.Display.fillCircle(M5.Display.width()/2, M5.Display.height()/2,

M5.Display.height()/2, WHITE);

32 of 56

Display

色系・文字・フォント系

M5.Display.setColor(色) → 描画色の指定(図形の描画メソッドが対象)

M5.Display.setTextColor(色) → 描画色の指定(print系のメソッドが対象)

M5.Display.fillScreen(色) → 背景を指定した色で塗りつぶす

M5.Display.setTextFont(フォント) → フォントの指定

M5.Display.setTextSize(サイズ) → テキストのサイズの指定

どんな色があるのか調べよう

Color List :: M5Stack Unofficial Guide (lang-ship.com)

使えるフォントを考えよう

Font List :: M5Stack Unofficial Guide (lang-ship.com)

GREEN

RED

YELLOW

BLUE

CYAN

PINK

WHITE

BLACK

ORANGE

PURPLE

33 of 56

Display

M5.Display.setTextFont(6);

M5.Display.setTextSize(2);

M5.setTextColor(RED);

M5.Display.fillScreen(GREEN);

M5.Display.setColor(BLUE);

34 of 56

演習

何か描画してみよう! 何でもOK (10分)

ヒント

  • 描画内容を変化させたければ, void loop()に記述しよう
    • センサの値を取得し継続的に表示したいときは
  • どんなメソッドがあるか調べてみよう

発展

  • M5Canvasを使ってみよう!!!
    • 画面のちらつきを防げる
    • 複数の画面に分割できる
    • m5-docs (m5stack.com)

35 of 56

タッチスクリーン

M5Stack Coreのディスプレイはタッチパネルになっている(M5.Touch)

M5.update() → タッチスクリーン情報の更新

M5.Touch.isEnabled() → タッチされたかどうかを判定する

M5.Touch.getDetail() → タッチされた時の情報を取得する

auto t = M5.Touch.getDetail()としたとき

t.base_x → タッチされた場所のx座標(int16_t型)

t.base_y → タッチされた場所のy座標(int16_t型)

詳細は→m5-docs (m5stack.com)

情報

タッチパネル

36 of 56

演習

タッチした箇所に円やピクセルを描画してみよう(10分)

タッチした場所の座標を取得し, その座標を中心とした円, またはピクセルを描画する

ヒント

  • M5.Touch.getDetail()
  • M5.Display.drawPixel()
  • M5.Display.fillCircle()

37 of 56

Button

M5Stack Core2には3つボタンがついている(BtnA, BtnB, BtnC)

XにはA, B, Cのいずれかが入る. 基本的にtrue/falseを返す

M5.update() → ボタンの状態の更新

M5.BtnX.wasHold() → ボタンを0.5秒以上押したか

M5.BtnX.wasClicked() → ボタンを短時間クリックしたか

M5.BtnX.wasPressed() → ボタンが押したか

M5.BtnX.wasReleased() → ボタンを押して離したか

M5.BtnX.wasDecideClickCount() → ボタンを何度かクリックして0.5秒経過したか

詳細は→M5Unified入門 その4 ボタン操作 | Lang-ship

実はM5.BtnX.wasXXXX()と同じようにM5.BtnX.isXXXX()の関数が存在する

was系はボタンを押してからM5.update()が実行された1回目のみtrueとなる

↑ BtnA

↑ BtnB

↑ BtnC

38 of 56

バイブレーション

M5.Power.Axp192を利用する

電源管理IC(AXP192)はバッテリー残量の取得, 電源のオフなどの処理を行う

M5Stack Core2には振動モータを搭載しているため, バイブレーションをすることができる(他のデバイスではできない)

M5.Power.Axp192.setLDO3(数値) → 数値が1800~3300なら振動する. 値が大きい方が振動も大きくなる. それ以下は振動

  を止める(止める時は0で良いかも)

M5.Power.Axp192.getBatteryLevel() → バッテリー残量を返す(0~100)

M5.Power.Axp192.isCharging() → 今, 充電されているかどうかを返す(bool値)

詳細は→M5Stack Core2のAXP192周り解析 | Lang-ship

39 of 56

演習

ボタンを押したらバイブレーションしてみよう(10分)

  • ボタンごとにバイブレーションの強さを変えてみよう
  • 押している間だけバイブレーションさせてみよう
  • どのボタンを押しているかわかるようにディスプレイに何か描画してみよう

ヒント

  • M5.BtnX.isPressed()
  • M5.Power.Axp192.setLDO3()
  • delay()

40 of 56

6軸IMU

6軸IMU: 3軸(x, y, z方向)の加速度, 角速度を取得できるセンサのこと

M5.Imu.update() → IMUの更新

M5.Imu.getAccel(&ax, &ay, &az) → 加速度を取得する

M5.Imu.getGyro(&gx, &gy, &gy) → 角速度を取得する

加速度や角速度を取得する時はfloat型の変数のアドレスを引数にする必要がある

詳細は→M5Stack 6軸IMUユニット(U095) MPU6886 | Lang-ship

+x

+y

+z

41 of 56

演習

IMUが取る値を見てみよう! (5分)

サンプルコードを動かしてみよう! (スライド下をコピペ)

書き込めたらCore2を様々な方向・速度・角度で動かしてみよう

何か気になることが見つかるかも?

42 of 56

スピーカー

M5.Speakerを使用する(サンプルはスライド下)

M5.Speaker.tone(音の周波数, 音の長さミリ秒, 仮想チャンネル番号, 今鳴っている音を止めるかtrue/false) → beep音を鳴らす

周波数参考→音階の周波数データ (plala.or.jp)

詳しくは→M5Stack用のM5Unifiedを使用したスピーカー制御 | KeiYouのソフト館 (progkeiyou.com)

SDカードと組み合わせて音声データを鳴らすならESP32-audioI2Sライブラリはおすすめ

この機械音も出せるかも!?

43 of 56

マイク

M5.Mic

音を電気信号に変換する電子部品 (多分一番難しいので全然覚えなくてよいです)

サンプルコードを動かしてみよう

M5Unified/examples/Basic/Microphone/Microphone.ino at master · m5stack/M5Unified (github.com)

44 of 56

RTC

Real-Time Clock (リアルタイムクロック) M5.Rtc

電源がオフ(スリープ)の状態でも時間を正確に保持するための専用回路やチップのこと(NTPサーバと通信して, 時刻の同期が必要)

構造体tm, NTPサーバへの通信, WiFi通信について知っている必要があるためスライド下にサンプル掲載

M5.Rtc.setDateTime(tm型の変数) → RTCに時刻をセットする

M5.Rtc.getDate() → 日付情報を取得する.

year(年), month(月), date(日)などのプロパティを持つ

M5.Rtc.getTime() → 時刻情報を取得する

hours(時), minutes(分), seconds(秒)などのプロパティを持つ

R

T

C

電源落ちた

45 of 56

SDカード

TFカードスロットマイクロSDを差し込む

マイクロSDにデータを保存, 入っているデータ(音声データなど)をの読み出しができる

SDを使ってデータを書き込み, 読み出しを行う

↑ TFカードスロット

S

D

46 of 56

I2C, GPIO, UART

M5StackシリーズがGrove拡張ユニットと通信するための通信方式

商品画像の右下or左下, コネクタの色で判断する

  • コネクタが赤→I2C
  • コネクタが黒→GPIO
  • コネクタが青→UART

今回のハンズオンではI2Cのみを取り扱う

47 of 56

Groveとは

センサやスイッチを簡単に扱えるスターターキットでハンダ付けが不要

M5Stackならコネクタに挿すだけでセンサを動かすことができる

48 of 56

I2C

I2C(Inter-Integrated Circuit)

同期式のシリアルバスで, 各種センサなどの接続用として使われる

同期式の通信なので, データ信号線(SDA)クロック信号線(SCL)を使う

I2Cバスを制御するデバイスをコントローラ(主にM5Stack側), コントローラにより制御されるデバイスをターゲット(主にGrove拡張ユニット側)と呼ぶ

複数のデバイスを接続することができ, ターゲットの識別はアドレス(基本は7ビット)を用いる

SHT30: 0x44

QMP6988: 0x70

0x48

0x3C

49 of 56

I2C

Wire.h: I2C通信を簡単に行うライブラリ

Wire.begin() → コントローラとして初期化する

Wire.beginTransmission(ターゲットのアドレス)

→ ターゲットデバイスにデータを送信する

Wire.write(送信するバイト列)

→ データを送信する. ※データシートを読むことが超大事

Wire.endTransmission()

→ データ送信を終了する(返り値が0でないなら通信に失敗)

今みんなが思っていること→

50 of 56

I2C

何のバイト列を送れば制御できるのか分からん!!!

解決案は2つ

1.ライブラリを使え

→PlatformIOで検索 or GitHubを探せば見つかる

2.とにかくデータシートを読め!!!

→センサ名 データシートで検索すれば見つかる

→基本的には英語なので頑張って読む

51 of 56

ENVⅢ

M5Stack用温湿度気圧センサユニット ENVⅢ

温湿度センサSHT30と気圧センサQMP6988を搭載した温湿度気圧が測定できるユニット

M5Stack用温湿度気圧センサユニット Ver.3(ENV Ⅲ) — スイッチサイエンス (switch-science.com)

温度: 150℃

湿度: 100%

気圧: 100kPa

52 of 56

ENVⅢ

ライブラリをインストールしよう: M5Unit_ENV (Libraries or GitHub)

このライブラリはUnit_ENVシリーズについてまとめたもの(ENV, ENVⅡ, ENVⅢ, ENVⅣ)

ENVⅢにはSHT30とQMP6988が搭載されているので, 使うクラスに注意

  • SHT3X
  • QMP6988

53 of 56

SHT30

SHT3X sht30;と定義する

sht30.begin(&Wire, 0x44, M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL())

→ 初期化. 引数は順にWireのアドレス, ターゲットのアドレス,

  コントローラのSDA, コントローラのSCL

sht30.update() → センサ情報を更新する

sht30.cTemp → Celsius温度を取得する

sht30.humidity → 湿度を取得する

54 of 56

QMP6988

QMP6988 qmp6988;と定義する

qmp6988.begin(&Wire, 0x70, M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL())

→ 初期化. 引数は順にWireのアドレス, ターゲットのアドレス,

  コントローラのSDA, コントローラのSCL

qmp6988.update() → センサ情報を更新する

qmp6988.pressure → 気圧を取得する

55 of 56

演習 前半戦ラスト!

ENVⅢ+M5Stack Core2の内蔵機能を組み合わせてみよう(10分)

ヒント

様々な組み合わせを考えてみよう

  • × ディスプレイ
  • × ボタン
  • × スピーカー

56 of 56

まとめ

前半戦終了 お疲れさまでした!

後半戦はNode-RED, 無線通信を取り扱います!

  • 難しくなるので分からなかったら早めに聞くこと大事
  • どんどんプロトタイピングしよう!
  • M5Unifiedを使いこなそう

早く終わってしまったら

  • 他のM5シリーズを使ってみよう
    • M5Unified使ってれば, 殆ど変えずに開発できる
  • 他のGrove拡張ユニットを触ってみよう
    • 岩井研にはたくさんある
  • 面白いセンサ, アクチュエータの組み合わせを探そう