mirror of
https://github.com/m5stack/M5UnitUnified.git
synced 2026-05-20 11:24:51 -07:00
324 lines
9.0 KiB
Markdown
324 lines
9.0 KiB
Markdown
# M5UnitUnified
|
|
|
|
[日本語](README.ja.md)
|
|
|
|
**A new approach to connect and handle various M5 units in the M5Stack**
|
|
Library for M5Stack Series and M5Unit Series
|
|
|
|
## Overview
|
|
M5UnitUnified is a library for unified handling of various M5 units products.
|
|
|
|
### Unified APIs
|
|
Each unit's external library has its own API design.
|
|
Unify basic APIs so that all units can be handled in the same way.
|
|
|
|
### Unified connections and communications
|
|
Each unit's external library requires its own communication functions and assumptions.
|
|
Unify prerequisites and communication methods.
|
|
In the future, we plan to work with [M5HAL (Hardware Abstraction Layer)](https://github.com/m5stack/M5HAL) to unified communication with each unit.
|
|
|
|
### Unified Licensing
|
|
External library licenses for each unit are mixed.
|
|
All M5UnitUnified and related libraries are under the [MIT license](LICENSE).
|
|
|
|
|
|
## How to install
|
|
The library is registered with the library manager.
|
|
|
|
### Arduino IDE
|
|
|
|
1. Using library manager and select the library of the unit you want to use (e.g. M5Unit-GESTURE)
|
|
|
|
Dependent M5UnitUnified related libraries will be downloaded automatically.
|
|
|
|
### PlatformIO
|
|
1. Write lib\_deps settings to platformio.ini
|
|
```ini
|
|
lib_deps= m5stack/M5Unit-foo ; Unit to be used
|
|
```
|
|
Dependent M5UnitUnified related libraries will be downloaded automatically.
|
|
|
|
|
|
## How to use
|
|
|
|
See also examples for each unit repository too.
|
|
|
|
### UnitComponent with UnitUnified (Standard usage)
|
|
|
|
#### Unit using Wire
|
|
```cpp
|
|
// If you use other units, change include files(*1), instances(*2), and get values(*3)
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedENV.h> // *1 Include the header of the unit to be used
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitCO2 unit; // *2 Instance of the unit
|
|
|
|
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) // 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 Obtaining unit-specific measurements
|
|
M5.Log.printf("CO2:%u Temp:%f Hum:%f\n", unit.co2(), unit.temperature(), unit.humidity());
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Unit using I2C_Class (M5Unified internal I2C)
|
|
```cpp
|
|
// Example: Reading the SHT30 sensor built into M5Paper via M5Unified's In_I2C
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedENV.h> // *1 Include the header of the unit to be used
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitSHT30 unit; // *2 Instance of the unit
|
|
|
|
void setup() {
|
|
M5.begin();
|
|
|
|
// Use M5Unified's In_I2C (internal I2C bus)
|
|
// No manual pin/frequency configuration needed
|
|
if (!Units.add(unit, M5.In_I2C) // Add unit using I2C_Class
|
|
|| !Units.begin()) {
|
|
M5_LOGE("Failed to add/begin");
|
|
}
|
|
}
|
|
|
|
void loop() {
|
|
M5.update();
|
|
Units.update();
|
|
if (unit.updated()) {
|
|
// *3 Obtaining unit-specific measurements
|
|
M5.Log.printf("Temp:%f Hum:%f\n", unit.temperature(), unit.humidity());
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Unit using M5HAL Bus (SoftwareI2C)
|
|
```cpp
|
|
// If you use other units, change include files(*1), instances(*2), and get values(*3)
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedENV.h> // *1 Include the header of the unit to be used
|
|
#include <M5HAL.hpp>
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitCO2 unit; // *2 Instance of the unit
|
|
|
|
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) // Add unit using M5HAL Bus
|
|
|| !Units.begin()) {
|
|
M5_LOGE("Failed to add/begin");
|
|
}
|
|
}
|
|
|
|
void loop() {
|
|
M5.update();
|
|
Units.update();
|
|
if (unit.updated()) {
|
|
// *3 Obtaining unit-specific measurements
|
|
M5.Log.printf("CO2:%u Temp:%f Hum:%f\n", unit.co2(), unit.temperature(), unit.humidity());
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Unit using GPIO
|
|
|
|
```cpp
|
|
// If you use other units, change include files(*1), instances(*2), and get values(*3)
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedTUBE.h> // *1 Include the header of the unit to be used
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitTubePressure unit; // *2 Instance of the unit
|
|
|
|
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 Obtaining unit-specific measurements
|
|
M5.Log.printf("Pressure:%.2f\n", unit.pressure());
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Unit using UART(Serial)
|
|
|
|
```cpp
|
|
// If you use other units, change include files(*1), instances(*2), and call any API(*3)
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedFINGER.h> // *1 Include the header of the unit to be used
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitFinger unit; // *2 Instance of the unit
|
|
|
|
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();
|
|
// Note that the argument varies depending on the target unit
|
|
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 Arbitrary API calls to the unit...
|
|
}
|
|
|
|
```
|
|
|
|
#### Unit using SPI
|
|
|
|
```cpp
|
|
// If you use other units, change include files(*1), instances(*2), and call any API(*3)
|
|
#include <M5Unified.h>
|
|
#include <M5UnitUnified.h>
|
|
#include <M5UnitUnifiedFoo.h> // *1 Include the header of the unit to be used
|
|
|
|
m5::unit::UnitUnified Units;
|
|
m5::unit::UnitFoo unit; // *2 Instance of the unit
|
|
|
|
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);
|
|
}
|
|
|
|
// Note that the depending on the target unit
|
|
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 Arbitrary API calls to the unit...
|
|
}
|
|
```
|
|
|
|
|
|
## Supported things
|
|
### Supported frameworks
|
|
- Arduino
|
|
|
|
In the future, all connections will be made through M5HAL, eliminating the need to use Wire class etc. directly.
|
|
|
|
### Supported connection
|
|
- I2C with TwoWire class
|
|
- I2C with I2C_Class (M5Unified In_I2C/Ex_I2C)
|
|
- I2C with M5HAL Bus (including SoftwareI2C)
|
|
- GPIO (Currently only functions required for the units are included)
|
|
- UART with HardwareSerial class
|
|
- SPI with SPI class
|
|
|
|
### Supported devices, units
|
|
See also [Wiki](https://github.com/m5stack/M5UnitUnified/wiki/)
|
|
|
|
## Examples
|
|
For examples, please refer to each unit's repository (e.g. M5Unit-ENV, M5Unit-HEART, etc.).
|
|
|
|
## Doxygen document
|
|
|
|
[GitHub Pages](https://m5stack.github.io/M5UnitUnified/)
|
|
|
|
If you want to generate documents on your local machine, execute the following command
|
|
|
|
```
|
|
bash docs/doxy.sh
|
|
```
|
|
|
|
It will output it under docs/html
|
|
If you want to output Git commit hashes to html, do it for the git cloned folder.
|
|
|
|
### Required
|
|
- [Doxygen](https://www.doxygen.nl/)
|
|
- [pcregrep](https://formulae.brew.sh/formula/pcre2)
|
|
- [Git](https://git-scm.com/) (Output commit hash to html)
|
|
|