M5Stack に色々な M5 ユニットをつないで扱う為の新たなアプローチ
M5Stack シリーズ、 M5Unitシリーズの為のライブラリです。
M5UnitUnified は、様々な M5 ユニット製品を統一的に扱うためのライブラリです。
各ユニットの外部ライブラリは、それぞれ独自の API デザインがされています。
基本的なAPIを統一し、すべてのユニットが同じように扱えるようにします。
各ユニットの外部ライブラリは独自の通信機能と前提条件が必要です。
前提条件や通信方法を統一化します。
将来的にはM5HAL(Hardware Abstraction Layer)と連携し、各ユニットとの通信を統一する予定です。
各ユニットの外部ライブラリのライセンスは様々な物が混在しています。
すべてのM5UnitUnifiedおよび関連ライブラリは、MITライセンス下にあります。
Arduino/PlatformIO のライブラリマネージャーに登録されています
- ライブラリマネージャから使用したいユニットのライブラリ (M5Unit-Foo) を選択してください
依存する M5UnitUnified 関連のライブラリは自動で DL されます
- platformio.ini の lib_deps に記述してください
lib_deps=m5stack/M5Unit-foo ;使用したいユニットのライブラリ依存する M5UnitUnified 関連のライブラリは自動で DL されます
各ユニットのリポジトリの例も参照のこと。
// 他のユニットを使用する場合、インクルードファイル (*1)、インスタンス (*2)、値の取得 (*3) を変更する
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedENV.h> // *1 使用するユニットのヘッダ
m5::unit::UnitUnified Units;
m5::unit::UnitCO2 unit; // *2 使用するユニットのインスタンス
void setup() {
M5.begin();
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
Wire.end();
Wire.begin(pin_num_sda, pin_num_scl, 400 * 1000U);
if (!Units.add(unit, Wire) // unit を UnitUnified マネージャへ追加
|| !Units.begin()) { // ユニットの始動
M5_LOGE("Failed to add/begin");
}
}
void loop() {
M5.update();
Units.update();
if (unit.updated()) {
// *3 ユニット固有の計測値の取得
M5.Log.printf("CO2:%u Temp:%f Hum:%f\n", unit.co2(), unit.temperature(), unit.humidity());
}
}// M5Paper 内蔵 SHT30 センサを M5Unified の In_I2C 経由で読み取る例
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedENV.h> // *1 使用するユニットのヘッダ
m5::unit::UnitUnified Units;
m5::unit::UnitSHT30 unit; // *2 使用するユニットのインスタンス
void setup() {
M5.begin();
// M5Unified の In_I2C(内部 I2C バス)を使用
// ピンや周波数の手動設定は不要
if (!Units.add(unit, M5.In_I2C) // I2C_Class を使用してユニットを追加
|| !Units.begin()) {
M5_LOGE("Failed to add/begin");
}
}
void loop() {
M5.update();
Units.update();
if (unit.updated()) {
// *3 ユニット固有の計測値の取得
M5.Log.printf("Temp:%f Hum:%f\n", unit.temperature(), unit.humidity());
}
}// 他のユニットを使用する場合、インクルードファイル (*1)、インスタンス (*2)、値の取得 (*3) を変更する
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedENV.h> // *1 使用するユニットのヘッダ
#include <M5HAL.hpp>
m5::unit::UnitUnified Units;
m5::unit::UnitCO2 unit; // *2 使用するユニットのインスタンス
void setup() {
M5.begin();
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
m5::hal::bus::I2CBusConfig i2c_cfg;
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
if (!Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) // M5HAL Bus を使用してユニットを追加
|| !Units.begin()) {
M5_LOGE("Failed to add/begin");
}
}
void loop() {
M5.update();
Units.update();
if (unit.updated()) {
// *3 ユニット固有の計測値の取得
M5.Log.printf("CO2:%u Temp:%f Hum:%f\n", unit.co2(), unit.temperature(), unit.humidity());
}
}// 他のユニットを使用する場合、インクルードファイル (*1)、インスタンス (*2)、値の取得 (*3) を変更する
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedTUBE.h> // *1 使用するユニットのヘッダ
m5::unit::UnitUnified Units;
m5::unit::UnitTubePressure unit; // *2 使用するユニットのインスタンス
void setup()
{
M5.begin();
// PortB if available, PortA if not
auto pin_num_gpio_in = M5.getPin(m5::pin_name_t::port_b_in);
auto pin_num_gpio_out = M5.getPin(m5::pin_name_t::port_b_out);
if (pin_num_gpio_in < 0 || pin_num_gpio_out < 0) {
M5_LOGW("PortB is not available");
Wire.end();
pin_num_gpio_in = M5.getPin(m5::pin_name_t::port_a_pin1);
pin_num_gpio_out = M5.getPin(m5::pin_name_t::port_a_pin2);
}
if (!Units.add(unit, pin_num_gpio_in, pin_num_gpio_out) // Add unit to UnitUnified manager
|| !Units.begin()) { // Begin each unit
M5_LOGE("Failed to add/begin");
}
}
void loop()
{
M5.update();
Units.update();
if (unit.updated()) {
// *3 ユニット固有の計測値の取得
M5.Log.printf("Pressure:%.2f\n", unit.pressure());
}
}// 他のユニットを使用する場合、インクルードファイル (*1)、インスタンス (*2)、API呼び出し (*3) を変更する
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedFINGER.h> // *1 使用するユニットのヘッダ
m5::unit::UnitUnified Units;
m5::unit::UnitFinger unit; // *2 使用するユニットのインスタンス
void setup()
{
M5.begin();
// PortC if available, PortA if not
auto pin_num_in = M5.getPin(m5::pin_name_t::port_c_rxd);
auto pin_num_out = M5.getPin(m5::pin_name_t::port_c_txd);
if (pin_num_in < 0 || pin_num_out < 0) {
M5_LOGW("PortC is not available");
Wire.end();
pin_num_in = M5.getPin(m5::pin_name_t::port_a_pin1);
pin_num_out = M5.getPin(m5::pin_name_t::port_a_pin2);
}
#if SOC_UART_NUM > 2
auto& s = Serial2;
#elif SOC_UART_NUM > 1
auto& s = Serial1;
#else
#error "Not enough Serial"
#endif
s.end();
// 備考: ユニットによって初期化パラメータは異なる
s.begin(19200, SERIAL_8N1, pin_num_in, pin_num_out);
if (!Units.add(unit, s) // Add unit to UnitUnified manager
|| !Units.begin()) { // Begin each unit
M5_LOGE("Failed to begin");
}
}
void loop() {
M5.update();
Units.update();
// *3 任意の API 呼び出し...
}
// 他のユニットを使用する場合、インクルードファイル (*1)、インスタンス (*2)、API呼び出し (*3) を変更する
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedFoo.h> // *1 使用するユニットのヘッダ
m5::unit::UnitUnified Units;
m5::unit::UnitFoo unit; // *2 使用するユニットのインスタンス
void setup()
{
M5.begin();
if (!SPI.bus()) {
auto spi_sclk = M5.getPin(m5::pin_name_t::sd_spi_sclk);
auto spi_mosi = M5.getPin(m5::pin_name_t::sd_spi_mosi);
auto spi_miso = M5.getPin(m5::pin_name_t::sd_spi_miso);
M5_LOGI("getPin: %d,%d,%d", spi_sclk, spi_mosi, spi_miso);
SPI.begin(spi_sclk, spi_miso, spi_mosi);
}
// 備考: ユニットによって初期化パラメータは異なる
SPISettings settings = {10000000, MSBFIRST, SPI_MODE1};
if (!Units.add(cap, SPI, settings) || !Units.begin()) {
M5_LOGE("Failed to begin");
lcd.fillScreen(TFT_RED);
while (true) {
m5::utility::delay(10000);
}
}
}
void loop() {
M5.update();
Units.update();
// *3 任意の API 呼び出し...
}- Arduino
将来的には Wire クラス等を直接使わず、全て M5HAL 経由で接続を行えるようになる予定です。
- I2C TwoWire class による
- I2C I2C_Class (M5Unified In_I2C/Ex_I2C) による
- I2C M5HAL Bus (SoftwareI2C を含む) による
- GPIO (現在は各ユニットに必要な機能のみ搭載)
- UART HardwareSerial class による
- SPI SPI class による
Wikiを参照
使用例は各ユニットのリポジトリ (M5Unit-ENV, M5Unit-HEART 等) を参照してください。
あなたのローカルマシンでドキュメントを生成したい場合は、以下のコマンドを実行してください。
bash docs/doxy.sh
docs/html の下に出力されます。
Git コミットのハッシュを html に出力したい場合は、 git クローンしたフォルダに対して実行してください。