M5Stackハンズオン
2024 10/19
無断転載・外部公開・外部アクセス禁止
何をやる?
目標
メンバー紹介
学番: 21FI113
氏名: 山嵜伶馬
趣味: アニメ, 散歩
times: #9_times_b4_reima
#5_cpslab_sensors
技術: C, 組込み周り
ラボ: CPSLab機材管理委員長
機材配布
M5Stackとは?
M5Stack社が提供するESP32ベースのモジュール型開発プラットフォーム(MCU)
WiFiやBluetoothでの通信が可能であり, 様々なセンサ, モジュールと組み合わせることで, 簡単にIoTプロトタイピングができる!
他にもマイコンはあるがM5StackはWiFi接続可+内蔵バッテリー内蔵のものが多い
環境構築
Arduino IDE vs PlatformIO
このハンズオンでは, VSCodeの拡張であるPlatformIOを使用する
こコ
こン
のパ
スイ
ペル
ル時
がで
違す
いが
ま
す
!
実は両方入れておくべきかも
岩井研は最新のESP32が搭載されたM5Stackシリーズも購入する
=>「PlatformIOが対応していない!」となることがあり得るかも!?
USBシリアルドライバインストール
M5Stack Core2ページからUSB認識用のドライバをインストールする
Driver Installationから自分のPCのOSに合わせたドライバをダウンロードする
ダウンロードしたzipを展開
CP210xVCPInstaller_x64_v6.7.0.0を実行
PlatformIO
←2
←3
←4
←6
↑5.ここがInstall
とりあえずHello World
プロジェクト作成
←2
←3
←1
プロジェクト作成
Project Wizard
Name: 任意のプロジェクト名を入力
Board: 開発ボードの選択 => M5Stack Core2を選択する
Framework: 何のフレームワークを使用するかを選択する => Arduino
Location: チェックが入っているとデフォルトの場所におかれる
Finishを押すとプロジェクトが作成される
プロジェクト構成
HandsOn
開発に必要なライブラリ
Arduino
M5Unified
ライブラリのインストール
←1
←2
←3
←4
←5
platformio.ini
env, platform, board, framework
lib_deps
upload_port
monitor_speed
Hello World
コードのことは考えずにとりあえずHello World(src/main.cppに以下を入力)
ワ
|
ル
ド
書き込み
M5Stack Core2とPCをUSB AtoCでつなぐ
画面右上または左下から
をクリックする
↓
→
→
→
↓
Hello World
書き込みが完了すればCore2のディスプレイにHello Worldが描画される
Build or Uploadに成功する
Build or Uploadに失敗する
基本的な文法
C, C++由来の文法
#include <XXX.h>
型
あとは自分で調べてね(⋈◍>◡<◍)。✧♡
Arduino由来の文法
void setup()
void loop()
ア
ル
デ
ィ
|
ノ
M5Unifiedで必要な記述
#include <M5Unified.h>
auto cfg = M5.config();
M5.begin(cfg);
M5Stack Core2の内蔵機能を使う
M5Stack Core2
M5Stack Core2で使える機能
括弧内(M5.Displayなど)のクラスを使用することで各機能にアクセスできる
基本的にM5.begin()で初期化される
ピンを使って配線もできるがパス(電子工作ハンズオンでやるかも)
背面を取り外して拡張モジュールを取り付けられるが今回はやらない
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() → ディスプレイを何も描画されていない状態にする
Display
M5.Display.println(“Hello”);
M5.Display.print(“World”);
M5.Display.printf(“Temperature: %f\n”, temperature);
M5.Display.printf(“Humidity: %f\n”, humidity);
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でも指定可能. デフォルトは黒?
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);
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)
使えるフォントを考えよう
GREEN
RED
YELLOW
BLUE
CYAN
PINK
WHITE
BLACK
ORANGE
PURPLE
Display
M5.Display.setTextFont(6);
M5.Display.setTextSize(2);
M5.setTextColor(RED);
M5.Display.fillScreen(GREEN);
M5.Display.setColor(BLUE);
演習
何か描画してみよう! 何でもOK (10分)
ヒント
発展
タッチスクリーン
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型)
正
確
な
座
標
の
情報
タッチパネル
演習
タッチした箇所に円やピクセルを描画してみよう(10分)
タッチした場所の座標を取得し, その座標を中心とした円, またはピクセルを描画する
ヒント
例
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
バイブレーション
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値)
演習
ボタンを押したらバイブレーションしてみよう(10分)
ヒント
例
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型の変数のアドレスを引数にする必要がある
+x
+y
+z
演習
IMUが取る値を見てみよう! (5分)
サンプルコードを動かしてみよう! (スライド下をコピペ)
書き込めたらCore2を様々な方向・速度・角度で動かしてみよう
何か気になることが見つかるかも?
スピーカー
M5.Speakerを使用する(サンプルはスライド下)
M5.Speaker.tone(音の周波数, 音の長さミリ秒, 仮想チャンネル番号, 今鳴っている音を止めるかtrue/false) → beep音を鳴らす
周波数参考→音階の周波数データ (plala.or.jp)
詳しくは→M5Stack用のM5Unifiedを使用したスピーカー制御 | KeiYouのソフト館 (progkeiyou.com)
SDカードと組み合わせて音声データを鳴らすならESP32-audioI2Sライブラリはおすすめ
この機械音も出せるかも!?
マイク
M5.Mic
音を電気信号に変換する電子部品 (多分一番難しいので全然覚えなくてよいです)
サンプルコードを動かしてみよう
M5Unified/examples/Basic/Microphone/Microphone.ino at master · m5stack/M5Unified (github.com)
マ
イ
ク
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
搭
載
な
電源落ちた
SDカード
TFカードスロットにマイクロSDを差し込む
マイクロSDにデータを保存, 入っているデータ(音声データなど)をの読み出しができる
SDを使ってデータを書き込み, 読み出しを行う
↑ TFカードスロット
に
保
存
S
D
I2C, GPIO, UART
M5StackシリーズがGrove拡張ユニットと通信するための通信方式
商品画像の右下or左下, コネクタの色で判断する
今回のハンズオンではI2Cのみを取り扱う
Groveとは
センサやスイッチを簡単に扱えるスターターキットでハンダ付けが不要
M5Stackならコネクタに挿すだけでセンサを動かすことができる
I2C
I2C(Inter-Integrated Circuit)
同期式のシリアルバスで, 各種センサなどの接続用として使われる
同期式の通信なので, データ信号線(SDA)とクロック信号線(SCL)を使う
I2Cバスを制御するデバイスをコントローラ(主にM5Stack側), コントローラにより制御されるデバイスをターゲット(主にGrove拡張ユニット側)と呼ぶ
複数のデバイスを接続することができ, ターゲットの識別はアドレス(基本は7ビット)を用いる
SHT30: 0x44
QMP6988: 0x70
0x48
0x3C
I2C
Wire.h: I2C通信を簡単に行うライブラリ
Wire.begin() → コントローラとして初期化する
Wire.beginTransmission(ターゲットのアドレス)
→ ターゲットデバイスにデータを送信する
Wire.write(送信するバイト列)
→ データを送信する. ※データシートを読むことが超大事
Wire.endTransmission()
→ データ送信を終了する(返り値が0でないなら通信に失敗)
今みんなが思っていること→
セ
ン
サ
の
制
御
デ
|
タ
の
書
き
込
み
I2C
何のバイト列を送れば制御できるのか分からん!!!
解決案は2つ
1.ライブラリを使え
→PlatformIOで検索 or GitHubを探せば見つかる
2.とにかくデータシートを読め!!!
→センサ名 データシートで検索すれば見つかる
→基本的には英語なので頑張って読む
デ
|
タ
シ
|
ト
ENVⅢ
M5Stack用温湿度気圧センサユニット ENVⅢ
温湿度センサSHT30と気圧センサQMP6988を搭載した温湿度気圧が測定できるユニット
M5Stack用温湿度気圧センサユニット Ver.3(ENV Ⅲ) — スイッチサイエンス (switch-science.com)
温度: 150℃
湿度: 100%
気圧: 100kPa
ENVⅢ
ライブラリをインストールしよう: M5Unit_ENV (Libraries or GitHub)
このライブラリはUnit_ENVシリーズについてまとめたもの(ENV, ENVⅡ, ENVⅢ, ENVⅣ)
ENVⅢにはSHT30とQMP6988が搭載されているので, 使うクラスに注意
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 → 湿度を取得する
制
御
QMP6988
QMP6988 qmp6988;と定義する
qmp6988.begin(&Wire, 0x70, M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL())
→ 初期化. 引数は順にWireのアドレス, ターゲットのアドレス,
コントローラのSDA, コントローラのSCL
qmp6988.update() → センサ情報を更新する
qmp6988.pressure → 気圧を取得する
演習 前半戦ラスト!
ENVⅢ+M5Stack Core2の内蔵機能を組み合わせてみよう(10分)
ヒント
様々な組み合わせを考えてみよう
まとめ
前半戦終了 お疲れさまでした!
後半戦はNode-RED, 無線通信を取り扱います!
早く終わってしまったら