Merge branch 'develop'

This commit is contained in:
GOB
2024-10-28 16:13:53 +09:00
24 changed files with 1011 additions and 747 deletions
-118
View File
@@ -1,118 +0,0 @@
name: ArduinoBuild(platform-version 2.x)
env:
SKETCH_NAMES_FIND_START: ./examples/UnitUnified
REQUIRED_LIBRARIES: M5Unified
# M5UNITUNIFIED_BRANCH: main
M5UNITUNIFIED_BRANCH: develop
on:
push:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**ArduinoBuild_2.yml'
pull_request:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**ArduinoBuild_2.yml'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
platform-url:
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
sketch:
- PlotToSerial
board:
- m5stack-core-esp32
- m5stack-core2
- m5stack-atoms3
- m5stack-cores3
platform-version:
#- 2.0.15
#- 2.0.16
- 2.0.17
platform:
- esp32
archi:
- esp32
steps:
- name: Running on GitHub Actions
if: env.ACT != 'true'
run: echo "This is running on GitHub Actions."
- name: Running locally with act
if: env.ACT == 'true'
run: echo "This is running locally with act."
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Checkout library from specific URL and branch
# Note that dependent libraries are not automatically installed.
# - name: Configure git for authentication (Until each repository is published)
# run: |
# git config --global url."https://${{ secrets.TOKEN_M5UNITUNIFIED }}@github.com/".insteadOf "https://github.com/"
- name: Checkout M5Utility
uses: actions/checkout@v3
with:
repository: m5stack/M5Utility
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5Utility # must contain string "Custom"
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
- name: Checkout M5HAL
uses: actions/checkout@v3
with:
repository: m5stack/M5HAL
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5HAL # must contain string "Custom"
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
- name: Checkout M5UnitUnified
uses: actions/checkout@v3
with:
repository: m5stack/M5UnitUnified
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5UnitUnified
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
# Build
- name: Compile examples
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
extra-arduino-cli-args: ${{ matrix.cli-args }}
#build-properties: ${{ toJson(matrix.build-properties) }}
sketch-names: ${{ matrix.sketch }}.ino
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}
#sketches-exclude: ${{ matrix.sketches-exclude }}
-124
View File
@@ -1,124 +0,0 @@
name: ArduinoBuild(platform-version 3.x)
env:
SKETCH_NAMES_FIND_START: ./examples/UnitUnified
REQUIRED_LIBRARIES: M5Unified
# M5UNITUNIFIED_BRANCH: main
M5UNITUNIFIED_BRANCH: develop
on:
push:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**ArduinoBuild_3.yml'
pull_request:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**ArduinoBuild_3.yml'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
platform-url:
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
sketch:
- PlotToSerial
board:
- m5stack_core
- m5stack_core2
- m5stack_atoms3
- m5stack_cores3
- m5stack_dial
- m5stack_nanoc6
- m5stack_paper
- m5stack_stickc_plus
platform-version:
#- 3.0.0
#- 3.0.1
#- 3.0.2
#- 3.0.3
- 3.0.4
platform:
- esp32
archi:
- esp32
steps:
- name: Running on GitHub Actions
if: env.ACT != 'true'
run: echo "This is running on GitHub Actions."
- name: Running locally with act
if: env.ACT == 'true'
run: echo "This is running locally with act."
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Checkout library from specific URL and branch
# Note that dependent libraries are not automatically installed.
# - name: Configure git for authentication (Until each repository is published)
# run: |
# git config --global url."https://${{ secrets.TOKEN_M5UNITUNIFIED }}@github.com/".insteadOf "https://github.com/"
- name: Checkout M5Utility
uses: actions/checkout@v3
with:
repository: m5stack/M5Utility
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5Utility # must contain string "Custom"
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
- name: Checkout M5HAL
uses: actions/checkout@v3
with:
repository: m5stack/M5HAL
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5HAL # must contain string "Custom"
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
- name: Checkout M5UnitUnified
uses: actions/checkout@v3
with:
repository: m5stack/M5UnitUnified
ref: ${{ env.M5UNITUNIFIED_BRANCH }}
path: CustomLibrary_M5UnitUnified
token: ${{ secrets.TOKEN_M5UNITUNIFIED }} # Only required during development in private repo
# Build
- name: Compile examples
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
extra-arduino-cli-args: ${{ matrix.cli-args }}
#build-properties: ${{ toJson(matrix.build-properties) }}
sketch-names: ${{ matrix.sketch }}.ino
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}
#sketches-exclude: ${{ matrix.sketches-exclude }}
-108
View File
@@ -1,108 +0,0 @@
name: PlatformIOBuild
on:
push:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**PlatformioBuild.yml'
- '**platformio.ini'
pull_request:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
- '**.h'
- '**.c'
- '**PlatformioBuild.yml'
- '**platformio.ini'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.example }}@${{ matrix.board }}:${{ matrix.framework }}:${{ matrix.espressif32 }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
example:
- PlotToSerial
board:
- Core
- Core2
- CoreS3
- StampS3
- AtomS3
- Dial
- NanoC6
- StickCPlus
- Paper
- Fire
framework:
- Arduino
espressif32:
- latest
- '5_4_0'
- '4_4_0'
exclude:
- board: CoreS3
espressif32: '5_4_0'
- board: CoreS3
espressif32: '4_4_0'
- board: StampS3
espressif32: '5_4_0'
- board: StampS3
espressif32: '4_4_0'
- board: AtomS3
espressif32: '5_4_0'
- board: AtomS3
espressif32: '4_4_0'
- board: Dial
espressif32: '5_4_0'
- board: Dial
espressif32: '4_4_0'
- board: NanoC6
espressif32: '5_4_0'
- board: NanoC6
espressif32: '4_4_0'
- board: StickCPlus
espressif32: '5_4_0'
- board: StickCPlus
espressif32: '4_4_0'
- board: Paper
espressif32: '5_4_0'
- board: Paper
espressif32: '4_4_0'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Configure git for authentication (Until each repository is published)
run: |
git config --global url."https://${{ secrets.TOKEN_M5UNITUNIFIED }}@github.com/".insteadOf "https://github.com/"
- name: Build examples
uses: karniv00l/platformio-run-action@v1
with:
environments: ${{ matrix.example }}_${{ matrix.board }}_${{ matrix.framework }}_${{ matrix.espressif32 }}
#targets:
project-dir: "./"
project-conf: "./platformio.ini"
#jobs: 6
#silent: false
#verbose: truee
#disable-auto-clean: false
@@ -0,0 +1,101 @@
name: Build(arduino-esp32:2.x)
env:
SKETCH_NAMES_FIND_START: ./examples/UnitUnified
REQUIRED_LIBRARIES: M5Unified,M5UnitUnified
on:
push:
tags-ignore:
- '*.*.*'
- 'v*.*.*'
branches:
- '*'
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-esp-v2-build-check.yml'
pull_request:
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-esp-v2-build-check.yml'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
platform-url:
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
sketch:
- PlotToSerial
unit:
- ''
board:
- m5stack-atom
- m5stack-atoms3
- m5stack-core-esp32
- m5stack-core2
- m5stack-coreink
- m5stack-cores3
- m5stack-fire
platform-version:
- 2.0.17
platform:
- esp32
archi:
- esp32
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Build
- name: Compile examples
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
extra-arduino-cli-args: ${{ matrix.cli-args }}
#build-properties: ${{ toJson(matrix.build-properties) }}
sketch-names: ${{ matrix.sketch }}.ino
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
#sketches-exclude: ${{ matrix.sketches-exclude }}
@@ -0,0 +1,118 @@
name: Build(arduino-esp32:3.x)
env:
SKETCH_NAMES_FIND_START: ./examples/UnitUnified
REQUIRED_LIBRARIES: M5Unified,M5UnitUnified
on:
push:
tags-ignore:
- '*.*.*'
- 'v*.*.*'
branches:
- '*'
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-esp-v3-build-check.yml'
pull_request:
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-esp-v3-build-check.yml'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
platform-url:
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
sketch:
- PlotToSerial
unit:
- ''
board:
- m5stack_atom
- m5stack_atoms3
- m5stack_capsule
# - m5stack_cardputer
- m5stack_core
- m5stack_core2
- m5stack_coreink
- m5stack_cores3
- m5stack_dial
- m5stack_fire
- m5stack_nanoc6
- m5stack_paper
# - m5stack_poe_cam
# - m5stack_stamp_c3
# - m5stack_stamp_pico
- m5stack_stamp_s3
# - m5stack_station
# - m5stack_stickc
- m5stack_stickc_plus
- m5stack_stickc_plus2
# - m5stack_timer_cam
# - m5stack_tough
# - m5stack_unit_cam
# - m5stack_unit_cams3
platform-version:
- 3.0.4
platform:
- esp32
archi:
- esp32
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Build
- name: Compile examples
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
extra-arduino-cli-args: ${{ matrix.cli-args }}
#build-properties: ${{ toJson(matrix.build-properties) }}
sketch-names: ${{ matrix.sketch }}.ino
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
#sketches-exclude: ${{ matrix.sketches-exclude }}
@@ -0,0 +1,120 @@
name: Build(arduino-m5stack)
env:
SKETCH_NAMES_FIND_START: ./examples/UnitUnified
REQUIRED_LIBRARIES: M5Unified,M5UnitUnified
on:
push:
tags-ignore:
- '*.*.*'
- 'v*.*.*'
branches:
- '*'
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-m5-build-check.yml'
pull_request:
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**arduino-m5-build-check.yml'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
# max-parallel: 1
matrix:
platform-url:
- https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
sketch:
- PlotToSerial
unit:
- ''
board:
- m5stack_atom
- m5stack_atoms3
- m5stack_atoms3r
- m5stack_capsule
# - m5stack_cardputer
- m5stack_core
- m5stack_core2
- m5stack_coreink
- m5stack_cores3
- m5stack_dial
- m5stack_dinmeter
- m5stack_fire
- m5stack_paper
# - m5stack_poe_cam
# - m5stack_stamp_c3
# - m5stack_stamp_pico
- m5stack_stamp_s3
# - m5stack_station
# - m5stack_stickc
- m5stack_stickc_plus
- m5stack_stickc_plus2
# - m5stack_timer_cam
# - m5stack_tough
# - m5stack_unit_cam
# - m5stack_unit_cams3
platform-version:
- 2.1.2
platform:
- m5stack
archi:
- esp32
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Build
- name: Compile examples
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
extra-arduino-cli-args: ${{ matrix.cli-args }}
#build-properties: ${{ toJson(matrix.build-properties) }}
sketch-names: ${{ matrix.sketch }}.ino
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
#sketches-exclude: ${{ matrix.sketches-exclude }}
+11 -2
View File
@@ -5,6 +5,11 @@ env:
on:
push:
tags-ignore:
- '*.*.*'
- 'v*.*.*'
branches:
- '*'
paths:
- '**.ino'
- '**.cpp'
@@ -13,7 +18,9 @@ on:
- '**.c'
- '**.inl'
- '**clang-format-check.yml'
pull_request:
- '**.clang-format'
pull_request:
paths:
- '**.ino'
- '**.cpp'
- '**.hpp'
@@ -21,6 +28,8 @@ on:
- '**.c'
- '**.inl'
- '**clang-format-check.yml'
- '**.clang-format'
workflow_dispatch:
jobs:
formatting-check:
@@ -36,7 +45,7 @@ jobs:
- check: 'examples'
exclude: ''
steps:
- name: Checkout # When pull_request is used, include it in the checkout https://zenn.dev/hkusu/articles/c731862051438b
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -0,0 +1,131 @@
name: Build(platformio)
on:
push:
tags-ignore:
- '*.*.*'
- 'v*.*.*'
branches:
- '*'
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '/platformio-build-check.yml'
- '**platformio.ini'
pull_request:
paths:
- 'src/unit/**.cpp'
- 'src/unit/**.hpp'
- 'src/unit/**.h'
- 'src/unit/**.c'
- 'test/**.cpp'
- 'test/**.hpp'
- 'test/**.h'
- 'test/**.c'
- 'examples/UnitUnified/**.ino'
- 'examples/UnitUnified/**.cpp'
- 'examples/UnitUnified/**.hpp'
- 'examples/UnitUnified/**.h'
- 'examples/UnitUnified/**.c'
- '**/platformio-build-check.yml'
- '**platformio.ini'
workflow_dispatch:
jobs:
build:
name: ${{ matrix.unit }}:${{ matrix.example }}@${{ matrix.board }}:${{ matrix.framework }}:${{ matrix.espressif32 }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
#max-parallel: 1
matrix:
example:
- PlotToSerial
unit:
- ''
board:
- Core
- Core2
- CoreS3
- Fire
- StampS3
- Dial
- AtomMatrix
- AtomS3
- AtomS3R
- NanoC6
- StickCPlus
- StickCPlus2
- Paper
- CoreInk
framework:
- Arduino
espressif32:
- latest
# - '5_4_0'
# - '4_4_0'
# exclude:
# - board: CoreS3
# espressif32: '5_4_0'
# - board: CoreS3
# espressif32: '4_4_0'
# - board: StampS3
# espressif32: '5_4_0'
# - board: StampS3
# espressif32: '4_4_0'
# - board: AtomS3
# espressif32: '5_4_0'
# - board: AtomS3
# espressif32: '4_4_0'
# - board: Dial
# espressif32: '5_4_0'
# - board: Dial
# espressif32: '4_4_0'
# - board: NanoC6
# espressif32: '5_4_0'
# - board: NanoC6
# espressif32: '4_4_0'
# - board: StickCPlus
# espressif32: '5_4_0'
# - board: StickCPlus
# espressif32: '4_4_0'
# - board: Paper
# espressif32: '5_4_0'
# - board: Paper
# espressif32: '4_4_0'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Build examples
uses: karniv00l/platformio-run-action@v1
with:
environments: ${{ matrix.unit != '' && format('{0}_{1}_{2}_{3}_{4}', matrix.unit, matrix.example, matrix.board, matrix.framework, matrix.espressif32) || format('{0}_{1}_{2}_{3}', matrix.example, matrix.board, matrix.framework, matrix.espressif32) }}
# targets:
project-dir: "./"
project-conf: "./platformio.ini"
# jobs: 6
# silent: false
# verbose: true
# disable-auto-clean: false
+2
View File
@@ -34,6 +34,8 @@ See also examples using conventional methods here.
See also [examples/UnitUnified](examples/UnitUnified)
## Doxygen document
[GitHub Pages](https://m5stack.github.io/M5Unit-HEART/)
If you want to generate documents on your local machine, execute the following command
```
+41
View File
@@ -0,0 +1,41 @@
{
"build": {
"arduino": {
"memory_type": "qio_opi",
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DARDUINO_M5STACK_ATOMS3R",
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "dio",
"mcu": "esp32s3",
"variant": "m5stack_atoms3"
},
"connectivity": [
"bluetooth",
"wifi"
],
"frameworks": [
"arduino",
"espidf"
],
"name": "M5Stack AtomS3R",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"require_upload_port": true,
"speed": 460800
},
"url": "https://docs.m5stack.com/en/core/AtomS3R",
"vendor": "M5Stack"
}
+1 -1
View File
@@ -2,7 +2,7 @@
"build": {
"core": "esp32",
"extra_flags": [
"-DARDUINO_M5Stack_NanoC6"
"-DARDUINO_M5STACK_NANOC6"
],
"f_cpu": "160000000L",
"f_flash": "80000000L",
+40
View File
@@ -0,0 +1,40 @@
{
"build": {
"arduino":{
"ldscript": "esp32_out.ld",
"partitions": "default_8MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DM5STACK_M5STICK_CPLUS2",
"-DBOARD_HAS_PSRAM",
"-mfix-esp32-psram-cache-issue",
"-mfix-esp32-psram-cache-strategy=memw",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "dio",
"mcu": "esp32",
"variant": "m5stick_c"
},
"connectivity": [
"wifi",
"bluetooth"
],
"frameworks": [
"arduino",
"espidf"
],
"name": "M5Stick-CPlus2",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"require_upload_port": true,
"speed": 1500000
},
"url": "https://docs.m5stack.com/en/core/M5StickC%20PLUS2",
"vendor": "M5Stack"
}
@@ -11,7 +11,6 @@
#include <M5Unified.h>
#include <M5UnitUnified.h>
#include <M5UnitUnifiedHEART.h>
#include <utility/heart_rate.hpp>
#if !defined(USING_M5HAL)
#include <Wire.h>
#endif
@@ -19,27 +18,25 @@
namespace {
auto& lcd = M5.Display;
m5::unit::UnitUnified Units;
m5::unit::UnitHEART unitHeart;
m5::max30100::HeartRate heartRate(100 /*sample rate*/);
m5::unit::UnitHEART unit;
m5::heart::PulseMonitor monitor(100.f);
} // namespace
void setup()
{
m5::utility::delay(1500);
M5.begin();
// Another settings
if (0) {
auto cfg = unitHeart.config();
cfg.sample_rate = m5::unit::max30100::Sample::Rate400;
cfg.pulse_width = m5::unit::max30100::LedPulseWidth::PW400;
cfg.ir_current = m5::unit::max30100::CurrentControl::mA7_6;
cfg.red_current = m5::unit::max30100::CurrentControl::mA7_6;
heartRate.setSampleRate(m5::max30100::HeartRate::getSampleRate(cfg.sample_rate));
// heartRate.setThreshold(25.0f); // depends on ir/redCurrent
// cfg.mode = m5::unit::max30100::Mode::HROnly;
unitHeart.config(cfg);
auto cfg = unit.config();
cfg.sampling_rate = m5::unit::max30100::Sampling::Rate200;
cfg.pulse_width = m5::unit::max30100::LedPulseWidth::PW200;
cfg.ir_current = m5::unit::max30100::CurrentControl::mA7_6;
cfg.red_current = m5::unit::max30100::CurrentControl::mA7_6;
auto sr = m5::unit::max30100::getSamplingRate(cfg.sampling_rate);
monitor.setSamplingRate(sr);
unit.config(cfg);
}
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
@@ -54,7 +51,7 @@ void setup()
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
M5_LOGI("Bus:%d", i2c_bus.has_value());
if (!Units.add(unitHeart, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
if (!Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
M5_LOGE("Failed to begin");
lcd.clear(TFT_RED);
while (true) {
@@ -65,7 +62,7 @@ void setup()
#pragma message "Using Wire"
// Using TwoWire
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
if (!Units.add(unitHeart, Wire) || !Units.begin()) {
if (!Units.add(unit, Wire) || !Units.begin()) {
M5_LOGE("Failed to begin");
lcd.clear(TFT_RED);
while (true) {
@@ -84,25 +81,29 @@ void loop()
{
M5.update();
Units.update();
if (unitHeart.updated()) {
while (unitHeart.available()) {
M5_LOGI("\n>IR:%u\n>RED:%u", unitHeart.ir(), unitHeart.red());
bool beat = heartRate.push_back((float)unitHeart.ir(), (float)unitHeart.red());
if (beat) {
M5_LOGI("Beat!");
}
unitHeart.discard();
if (unit.updated()) {
// WARNING
// If overflow is occurring, the sampling rate should be reduced because the processing is not up to par
if (unit.overflow()) {
M5_LOGW("\n>OVERFLOW:%u", unit.overflow());
}
auto bpm = heartRate.calculate();
M5_LOGW("\n>HRR:%f\n>SpO2:%f", bpm, heartRate.SpO2());
bool beat{};
// MAX30100 is equipped with a FIFO, so multiple data may be stored
while (unit.available()) {
monitor.push_back(unit.ir(), unit.red()); // Push back the oldest data
// M5_LOGI("\n>MIR:%f\n>MRED:%f", monitor.latestIR(), monitor.latestRED());
monitor.update();
beat = monitor.isBeat();
unit.discard(); // Discard the oldest data
}
M5_LOGI("\n>BPM:%f\n>SpO2:%f\n>BEAT:%u", monitor.bpm(), monitor.SpO2(), beat);
}
// buffer clear and measure tempeature
// Measure tempeature
if (M5.BtnA.wasClicked()) {
heartRate.clear();
m5::unit::max30100::TemperatureData td{};
if (unitHeart.measureTemperatureSingleshot(td)) {
if (unit.measureTemperatureSingleshot(td)) {
M5_LOGI("\n>Temp:%f", td.celsius());
}
}
+4 -7
View File
@@ -11,11 +11,9 @@
"url": "https://github.com/m5stack/M5Unit-HEART.git"
},
"dependencies": {
"M5UnitUnified": "https://github.com/m5stack/M5UnitUnified.git",
"M5Utility": "https://github.com/m5stack/M5Utility.git",
"M5HAL": "https://github.com/m5stack/M5HAL.git"
"M5UnitUnified": "https://github.com/m5stack/M5UnitUnified.git"
},
"version": "0.0.1",
"version": "0.0.2",
"frameworks": [
"arduino"
],
@@ -25,9 +23,8 @@
"headers": "M5UnitUnifiedHEART.h",
"license": "MIT",
"export": {
"exclude":
[
"exclude": [
"docs/html"
]
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
name=M5Unit-HEART
version=0.0.1
version=0.0.2
author=M5Stack
maintainer=M5Stack
sentence=Library for M5Stack UNIT HEART using M5UnitUnified
+64 -5
View File
@@ -3,8 +3,6 @@
; For UnitTest and examples (Using M5UnitUnified)
;-----------------------------------------------------------------------
[platformio]
;default_envs = test_UnitHEART_Core, test_UnitHEART_Core2, test_UnitHEART_CoreS3, test_UnitHEART_Fire, test_UnitHEART_StampS3, test_UnitHEART_Dial, test_UnitHEART_AtomS3, test_UnitHEART_NanoC6, test_UnitHEART_StickCPlus, test_UnitHEART_Paper
;default_envs = PlotToSerial_Core_Arduino_latest, PlotToSerial_Core_Arduino_5_4_0, PlotToSerial_Core_Arduino_4_4_0, PlotToSerial_Core2_Arduino_latest, PlotToSerial_Core2_Arduino_5_4_0, PlotToSerial_Core2_Arduino_4_4_0, PlotToSerial_CoreS3_Arduino_latest, PlotToSerial_StampS3_Arduino_latest, PlotToSerial_AtomS3_Arduino_latest, PlotToSerial_Dial_Arduino_latest, PlotToSerial_NanoC6_Arduino_latest, PlotToSerial_StickCPlus_Arduino_latest, PlotToSerial_Paper_Arduino_latest, PlotToSerial_Fire_Arduino_latest, PlotToSerial_Fire_Arduino_5_4_0, PlotToSerial_Fire_Arduino_4_4_0
[env]
build_flags =-Wall -Wextra -Wreturn-local-addr -Werror=format -Werror=return-local-addr
@@ -45,7 +43,7 @@ board = m5stack-fire
lib_deps = ${env.lib_deps}
[StampS3]
;include M5Capsule
;include M5Capsule, DinMeter
extends = m5base
board = m5stack-stamps3
lib_deps = ${env.lib_deps}
@@ -56,11 +54,22 @@ board = m5stack-stamps3
lib_deps = ${env.lib_deps}
m5stack/M5Dial
[AtomMatrix]
extends = m5base
board = m5stack-atom
lib_deps = ${env.lib_deps}
[AtomS3]
extends = m5base
board = m5stack-atoms3
lib_deps = ${env.lib_deps}
; Using ./boards/m5stack-atoms3r.json
[AtomS3R]
extends = m5base
board = m5stack-atoms3r
lib_deps = ${env.lib_deps}
; Using ./boards/m5stack-nanoc6.json
[NanoC6]
extends = m5base
@@ -77,10 +86,20 @@ extends = m5base
board = m5stick-c
lib_deps = ${env.lib_deps}
; Using ./boards/m5stick-cplus2.json
[StickCPlus2]
extends = m5base
board = m5stick-cplus2
lib_deps = ${env.lib_deps}
[Paper]
extends = m5base
board = m5stack-fire
; Using M5Fire instead of the M5Paper(Noting...)
lib_deps = ${env.lib_deps}
[CoreInk]
extends = m5base
board = m5stack-coreink
lib_deps = ${env.lib_deps}
[sdl]
@@ -202,12 +221,24 @@ lib_deps = ${Dial.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_AtomMatrix]
extends=AtomMatrix, option_release, arduino_latest
lib_deps = ${AtomMatrix.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_AtomS3]
extends=AtomS3, option_release, arduino_latest
lib_deps = ${AtomS3.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_AtomS3R]
extends=AtomS3R, option_release, arduino_latest
lib_deps = ${AtomS3R.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_NanoC6]
extends=NanoC6, option_release, arduino_latest
lib_deps = ${NanoC6.lib_deps}
@@ -220,12 +251,24 @@ lib_deps = ${StickCPlus.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_StickCPlus2]
extends=StickCPlus2, option_release, arduino_latest
lib_deps = ${StickCPlus2.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_Paper]
extends=Paper, option_release, arduino_latest
lib_deps = ${Paper.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
[env:test_UnitHEART_CoreInk]
extends=CoreInk, option_release, arduino_latest
lib_deps = ${CoreInk.lib_deps}
${test_fw.lib_deps}
test_filter= embedded/test_max30100
; --------------------------------
;Examples by M5UnitUnified
; --------------------------------
@@ -239,7 +282,7 @@ extends=Core, option_release, arduino_5_4_0
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_Core_Arduino_4_4_0]
extends=Core, option_release, arduino_5_4_0
extends=Core, option_release, arduino_4_4_0
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_Core2_Arduino_latest]
@@ -262,10 +305,18 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial
extends=StampS3, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_AtomMatrix_Arduino_latest]
extends=AtomMatrix, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_AtomS3_Arduino_latest]
extends=AtomS3, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_AtomS3R_Arduino_latest]
extends=AtomS3R, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_Dial_Arduino_latest]
extends=Dial, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
@@ -278,10 +329,18 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial
extends=StickCPlus, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_StickCPlus2_Arduino_latest]
extends=StickCPlus2, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_Paper_Arduino_latest]
extends=Paper, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_CoreInk_Arduino_latest]
extends=CoreInk, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
[env:PlotToSerial_Fire_Arduino_latest]
extends=Fire, option_release, arduino_latest
build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/PlotToSerial>
+1 -1
View File
@@ -14,7 +14,7 @@
#define M5_UNIT_HEART_HPP
#include "unit/unit_MAX30100.hpp"
#include "utility/heart_rate.hpp"
#include "utility/pulse_monitor.hpp"
/*!
@namespace m5
+20 -9
View File
@@ -24,6 +24,8 @@ constexpr elapsed_time_t interval_table[] = {
1000 / 50, 1000 / 100, 1000 / 167, 1000 / 200, 1000 / 400, 1000 / 600, 1000 / 800, 1000 / 1000,
};
constexpr uint32_t sr_table[] = {50, 100, 167, 200, 400, 600, 800, 1000};
constexpr uint32_t MEASURE_TEMPERATURE_DURATION{29}; // 29ms
constexpr uint8_t allowed_spo2_table[] = {
@@ -34,7 +36,7 @@ constexpr uint8_t allowed_hr_table[] = {
// LSB:200 MSB:1600
0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03,
};
bool is_allowed_settings(const Mode mode, const Sample rate, const LedPulseWidth pw)
bool is_allowed_settings(const Mode mode, const Sampling rate, const LedPulseWidth pw)
{
return (mode != Mode::None)
? (mode == Mode::SPO2 ? allowed_spo2_table : allowed_hr_table)[m5::stl::to_underlying(rate)] &
@@ -48,6 +50,11 @@ namespace m5 {
namespace unit {
namespace max30100 {
uint32_t getSamplingRate(Sampling rate)
{
return sr_table[m5::stl::to_underlying(rate)];
}
uint16_t Data::ir() const
{
return m5::types::big_uint16_t(raw[0], raw[1]).get();
@@ -100,7 +107,7 @@ bool UnitMAX30100::begin()
return false;
}
return _cfg.start_periodic ? startPeriodicMeasurement(_cfg.mode, _cfg.sample_rate, _cfg.pulse_width,
return _cfg.start_periodic ? startPeriodicMeasurement(_cfg.mode, _cfg.sampling_rate, _cfg.pulse_width,
_cfg.ir_current, _cfg.high_resolution, _cfg.red_current)
: true;
}
@@ -111,7 +118,11 @@ void UnitMAX30100::update(const bool force)
if (inPeriodic()) {
auto at = m5::utility::millis();
if (force || !_latest || at >= _latest + _interval) {
// Reduce interval if overflow
_updated = read_FIFO();
if (_interval && overflow()) {
--_interval;
}
if (_updated) {
_latest = at;
}
@@ -141,7 +152,7 @@ bool UnitMAX30100::start_periodic_measurement()
return false;
}
bool UnitMAX30100::start_periodic_measurement(const max30100::Mode mode, const max30100::Sample sample_rate,
bool UnitMAX30100::start_periodic_measurement(const max30100::Mode mode, const max30100::Sampling sampling_rate,
const max30100::LedPulseWidth pulse_width,
const max30100::CurrentControl ir_current, const bool high_resolution,
const max30100::CurrentControl red_current)
@@ -151,7 +162,7 @@ bool UnitMAX30100::start_periodic_measurement(const max30100::Mode mode, const m
}
SpO2Configuration sc{};
sc.sampleRate(sample_rate);
sc.samplingRate(sampling_rate);
sc.ledPulseWidth(pulse_width);
sc.highResolution(high_resolution);
@@ -220,11 +231,11 @@ bool UnitMAX30100::writeSpO2Configuration(const max30100::SpO2Configuration sc)
return write_spo2_configration(sc.value);
}
bool UnitMAX30100::writeSampleRate(const max30100::Sample rate)
bool UnitMAX30100::writeSamplingRate(const max30100::Sampling rate)
{
max30100::SpO2Configuration sc{};
if (read_spo2_configration(sc.value)) {
sc.sampleRate(rate);
sc.samplingRate(rate);
return write_spo2_configration(sc.value);
}
return false;
@@ -363,13 +374,13 @@ bool UnitMAX30100::write_spo2_configration(const uint8_t c)
max30100::SpO2Configuration sc;
sc.value = c;
if (!is_allowed_settings(_mode, sc.sampleRate(), sc.ledPulseWidth())) {
M5_LIB_LOGW("Invalid combination %u:%u:%u", _mode, sc.sampleRate(), sc.ledPulseWidth());
if (!is_allowed_settings(_mode, sc.samplingRate(), sc.ledPulseWidth())) {
M5_LIB_LOGW("Invalid combination %u:%u:%u", _mode, sc.samplingRate(), sc.ledPulseWidth());
return false;
}
if (writeRegister8(SPO2_CONFIGURATION, c) && read_spo2_configration(chk) && (chk == c)) {
_interval = interval_table[m5::stl::to_underlying(sc.sampleRate())];
_interval = interval_table[m5::stl::to_underlying(sc.samplingRate())];
return true;
}
return false;
+24 -17
View File
@@ -81,11 +81,11 @@ struct ModeConfiguration {
};
/*!
@enum Sample
@brief Sample rate for pulse
@enum Sampling
@brief Sampling rate for pulse
@details Unit is the number of sample per second
*/
enum class Sample : uint8_t {
enum class Sampling : uint8_t {
Rate50, //!< 50 sps
Rate100, //!< 100 sps
Rate167, //!< 167 sps
@@ -96,6 +96,13 @@ enum class Sample : uint8_t {
Rate1000, //!< 1000 sps
};
/*!
@brief Enum to sampling rate value
@param rate Enum value
@return sampling rate
*/
uint32_t getSamplingRate(const Sampling rate);
/*!
@enum LedPulseWidth
@brief LED pulse width (the IR and RED have the same pulse width)
@@ -114,7 +121,7 @@ enum class LedPulseWidth {
on the mode
- Mode:SPO2
|Sample\PulseWidth|200 |400 |800 |1600|
|Sampling\PulseWidth|200 |400 |800 |1600|
|---|---|---|---|---|
| 50|o|o|o|o|
| 100|o|o|o|o|
@@ -125,7 +132,7 @@ enum class LedPulseWidth {
| 800|o|x|x|x|
|1000|o|x|x|x|
- Mode:HROnly
|Sample\PulseWidth|200 |400 |800 |1600|
|Sampling\PulseWidth|200 |400 |800 |1600|
|---|---|---|---|---|
| 50|o|o|o|o|
| 100|o|o|o|o|
@@ -143,9 +150,9 @@ struct SpO2Configuration {
{ // for SpO2
return value & (1U << 6);
}
Sample sampleRate() const
Sampling samplingRate() const
{
return static_cast<Sample>((value >> 2) & 0x07);
return static_cast<Sampling>((value >> 2) & 0x07);
}
LedPulseWidth ledPulseWidth() const
{
@@ -159,7 +166,7 @@ struct SpO2Configuration {
{ // for SpO2
value = (value & ~(1U << 6)) | ((b ? 1 : 0) << 6);
}
void sampleRate(const Sample rate)
void samplingRate(const Sampling rate)
{
value = (value & ~(0x07 << 2)) | ((m5::stl::to_underlying(rate) & 0x07) << 2);
}
@@ -268,15 +275,15 @@ public:
/*!
@struct config_t
@brief Settings for begin
@warning Note that some combinations of sample_rate and pulse_width are invalid. See also datasheet
@warning Note that some combinations of sampling_rate and pulse_width are invalid. See also datasheet
*/
struct config_t {
//! Start periodic measurement on begin?
bool start_periodic{true};
//! Operating mode if start on begin
max30100::Mode mode{max30100::Mode::SPO2};
//! Sample rate if start on begin
max30100::Sample sample_rate{m5::unit::max30100::Sample::Rate100};
//! Sampling rate if start on begin
max30100::Sampling sampling_rate{m5::unit::max30100::Sampling::Rate100};
//! Led pulse width if start on begin
max30100::LedPulseWidth pulse_width{m5::unit::max30100::LedPulseWidth::PW1600};
//! Led current for IR if start on begin
@@ -361,7 +368,7 @@ public:
/*!
@brief Start periodic measurement
@param mode Operation mode
@param sample_rate Sample rate
@param sample_rate Sampling rate
@param pulse_width Pulse width
@param ir_current IR Led control
@param high_resolution (only SpO2)
@@ -369,7 +376,7 @@ public:
@return True if successful
@warning Note that some combinations of sample_rate and pulse_width are invalid. See also datasheet
*/
inline bool startPeriodicMeasurement(const max30100::Mode mode, const max30100::Sample sample_rate,
inline bool startPeriodicMeasurement(const max30100::Mode mode, const max30100::Sampling sample_rate,
const max30100::LedPulseWidth pulse_width,
const max30100::CurrentControl ir_current, const bool high_resolution = false,
const max30100::CurrentControl red_current = max30100::CurrentControl::mA0_0)
@@ -387,7 +394,7 @@ public:
}
///@warning Note that there are different combinations that can be set
/// depending on the mode See also SpO2Configuration
/// depending on the mode See also m5::unit::max30100::SpO2Configuration
///@name Mode Configuration
///@{
/*!
@@ -417,7 +424,7 @@ public:
///@}
///@warning Note that there are different combinations that can be set depending on the mode See also
/// SpO2Configuration
/// m5::unit::max30100::SpO2Configuration
///@name SpO2 Configuration
///@{
/*!
@@ -433,7 +440,7 @@ public:
*/
bool writeSpO2Configuration(const max30100::SpO2Configuration sc);
//! @brief Write sample rate
bool writeSampleRate(const max30100::Sample rate);
bool writeSamplingRate(const max30100::Sampling rate);
//! @brief Write LED pulse width
bool writeLedPulseWidth(const max30100::LedPulseWidth width);
//! @brief Writee SpO2 high resolution mode to enable
@@ -496,7 +503,7 @@ public:
protected:
bool start_periodic_measurement();
bool start_periodic_measurement(const max30100::Mode mode, const max30100::Sample sample_rate,
bool start_periodic_measurement(const max30100::Mode mode, const max30100::Sampling sample_rate,
const max30100::LedPulseWidth pulse_width,
const max30100::CurrentControl ir_current, const bool high_resolution,
const max30100::CurrentControl red_current);
-187
View File
@@ -1,187 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*!
@file heart_rate.cpp
@brief Calculate heart rate and SpO2
*/
#include "heart_rate.hpp"
#include <M5Unified.hpp>
#include <M5Utility.hpp>
#include <cmath>
#include <numeric>
using namespace m5::max30100;
namespace {
constexpr float ALPHA{0.95f}; // for removeDC
void calculateButterworthCoefficients(float Fs, float Fc, float& a0, float& a1, float& b1)
{
float tanWc = std::tan(M_PI * Fc / Fs);
float sqrt2 = std::sqrt(2.0f);
a0 = tanWc / (tanWc + sqrt2);
a1 = a0;
b1 = (tanWc - sqrt2) / (tanWc + sqrt2);
}
inline dcFilter_t removeDC(const float x, const float prev_w, const float alpha)
{
dcFilter_t filtered;
filtered.w = x + alpha * prev_w;
filtered.result = filtered.w - prev_w;
return filtered;
}
float meanDiff(const float M, meanDiffFilter_t& filterValues)
{
float avg{};
filterValues.sum -= filterValues.values[filterValues.index];
filterValues.values[filterValues.index] = M;
filterValues.sum += filterValues.values[filterValues.index];
filterValues.index++;
filterValues.index = filterValues.index % meanDiffFilter_t::MEAN_FILTER_SIZE;
if (filterValues.count < meanDiffFilter_t::MEAN_FILTER_SIZE) {
filterValues.count++;
}
avg = filterValues.sum / filterValues.count;
return avg - M;
}
void lowPassButterworthFilter(const float x, butterworthFilter_t& fr)
{
fr.v[0] = fr.v[1];
fr.v[1] = (fr.a0 * x) + (fr.a1 * fr.v[0]) - (fr.b1 * fr.v[1]);
fr.result = fr.v[0] + fr.v[1];
}
#if 0
std::pair<float /*AC*/, float /*DC*/> calculateACDC(
const std::deque<float>& data) {
float maxVal = *std::max_element(data.begin(), data.end());
float minVal = *std::min_element(data.begin(), data.end());
return {maxVal - minVal,
std::accumulate(data.begin(), data.end(), 0.0f) / data.size()};
}
#endif
} // namespace
namespace m5 {
namespace max30100 {
HeartRate::HeartRate(const uint32_t srate, const float threshold, const size_t max_data_size)
: _sampleRate{(float)srate}, _threshold(threshold), _maxDataSize{max_data_size}
{
assert(srate && "SampleRate must not be zero");
if (!max_data_size) {
_maxDataSize = (size_t)srate * 30U;
}
calculateButterworthCoefficients(_sampleRate, 10.0f, _bwfIR.a0, _bwfIR.a1, _bwfIR.b1);
}
void HeartRate::setSampleRate(const uint32_t sr)
{
_sampleRate = sr;
calculateButterworthCoefficients(_sampleRate, 10.0f, _bwfIR.a0, _bwfIR.a1, _bwfIR.b1);
clear();
}
void HeartRate::clear()
{
_dataIR.clear();
_peakDowns.clear();
_incrasing = false;
_dcIR = dcFilter_t{};
_mdIR = meanDiffFilter_t{};
_bwfIR = butterworthFilter_t{};
calculateButterworthCoefficients(_sampleRate, 10.0f, _bwfIR.a0, _bwfIR.a1, _bwfIR.b1);
}
bool HeartRate::push_back(const float ir, const float red)
{
// Filtering (IR)
_dcIR = removeDC(ir, _dcIR.w, ALPHA);
// M5_LIB_LOGI("\n>ACIR:%f", _dcIR.result);
auto md = meanDiff(_dcIR.result, _mdIR);
// M5_LIB_LOGI("\n>MD:%f", md);
lowPassButterworthFilter(md, _bwfIR);
// M5_LIB_LOGI("\n>LP:%f", _bwfIR.result);
// Filtering (RED)
_dcRED = removeDC(red, _dcRED.w, ALPHA);
// M5_LIB_LOGI("\n>ACRED:%f", _dcRED.result);
// Store
_dataIR.push_back(_bwfIR.result);
if (_dataIR.size() > _maxDataSize) {
_dataIR.pop_front();
}
// Heart beat
_beat = detect_beat();
// SpO2
_acSqIR += _dcIR.result * _dcIR.result;
//_acSqRED += _dcRED.result * _dcRED.result;
_acSqRED = _dcRED.result * _dcRED.result;
++_count;
if (_beat) {
float rr = std::log(std::sqrt(_acSqRED / _count)) / std::log(std::sqrt(_acSqIR / _count));
auto s = 110.0f - _coeffSpO2 * rr;
_SpO2 = std::fmin(std::fmax(s, 80.f), 100.f);
_acSqIR = _acSqRED = 0.0f;
_count = 0;
}
return _beat;
}
float HeartRate::calculate() const
{
if (_peakDowns.size() < 2) {
return 0.0f;
}
float total{};
for (size_t i = 1; i < _peakDowns.size(); ++i) {
total += _peakDowns[i] - _peakDowns[i - 1];
}
float avg = total / (_peakDowns.size() - 1);
return 1.0f / avg * 60000.0f;
}
bool HeartRate::detect_beat()
{
auto now = m5::utility::millis();
bool beat{};
if (_dataIR.size() >= 4) {
auto d3 = _dataIR.back();
auto d2 = _dataIR[_dataIR.size() - 2];
auto d1 = _dataIR[_dataIR.size() - 3];
auto d0 = _dataIR[_dataIR.size() - 4];
if (!_incrasing && (d0 > _threshold) && (d1 > d0) && (d2 > d1) && (d3 > d2)) {
_incrasing = true;
} else if (_incrasing && (d1 < d0) && (d2 < d1) && (d3 < d2)) {
_incrasing = false;
beat = true;
_peakDowns.push_back(now);
}
}
// Remove old peaks from the window
while (!_peakDowns.empty() && now - _peakDowns.front() > 1000 * 10) {
_peakDowns.pop_front();
}
return beat;
}
} // namespace max30100
} // namespace m5

Some files were not shown because too many files have changed in this diff Show More