initial commit

This commit is contained in:
Moirtz Wagner 2025-03-21 09:59:09 +01:00
parent 59637f4fa8
commit f690d03c57
355 changed files with 297020 additions and 0 deletions

7522
Raumtempregler v10.step Normal file

File diff suppressed because it is too large Load Diff

5
Raumtermostat/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
Raumtermostat/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View File

@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
Raumtermostat/lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@ -0,0 +1,3 @@
*.hpp linguist-language=C++

View File

@ -0,0 +1,127 @@
name: Build with Arduino
on:
workflow_dispatch:
pull_request:
push:
paths:
- "src/**"
- "examples/**"
- ".github/workflows/arduino_ci.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ArduinoLint:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
board:
- fqbn: esp32:esp32:esp32s3
platform: esp32:esp32
url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
- fqbn: rp2040:rp2040:rpipico
platform: rp2040:rp2040
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
- fqbn: adafruit:nrf52:pca10056
platform: adafruit:nrf52
url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
- fqbn: STMicroelectronics:stm32:GenF4
platform: stmicroelectronics:stm32
url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
- fqbn: arduino:mbed_rp2040:pico
platform: arduino:mbed_rp2040
include:
- example_file: examples.txt
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Arduino CLI
run: |
echo "Installing Arduino CLI..."
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
if [ $? -ne 0 ]; then
echo "Failed to install Arduino CLI."
exit 1
fi
echo "./bin" >> $GITHUB_PATH
echo "Arduino CLI installed successfully."
- name: Install board
run: |
echo "Initializing Arduino CLI configuration..."
arduino-cli config init
arduino-cli config set library.enable_unsafe_install true
if [ -n "${{ matrix.board.url }}" ]; then
echo "Adding additional board manager URL: ${{ matrix.board.url }}"
arduino-cli config add board_manager.additional_urls ${{ matrix.board.url }}
fi
echo "Updating board index..."
arduino-cli core update-index
if [ $? -ne 0 ]; then
echo "Failed to update board index."
exit 1
fi
echo "Installing board platform: ${{ matrix.board.platform }}"
arduino-cli core install ${{ matrix.board.platform }}
if [ $? -ne 0 ]; then
echo "Failed to install board platform."
exit 1
fi
echo "Board platform installed successfully."
- name: Install libraries
run: |
echo "Installing required libraries..."
arduino-cli lib install --git-url https://github.com/ThingPulse/esp8266-oled-ssd1306.git
arduino-cli lib install --git-url https://github.com/arduino-libraries/MadgwickAHRS.git
arduino-cli lib install --git-url https://github.com/CreativeRobotics/Commander.git
arduino-cli lib install --git-url https://github.com/adafruit/SdFat.git
if [ $? -ne 0 ]; then
echo "Failed to install libraries."
exit 1
fi
echo "Libraries installed successfully."
- name: Install adafruit-nrfutil
if: matrix.board.platform == 'adafruit:nrf52'
run: |
pip install adafruit-nrfutil
if [ $? -ne 0 ]; then
echo "Failed to install adafruit-nrfutil."
exit 1
fi
echo "adafruit-nrfutil installed successfully."
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Find .ino files in examples directory
id: find-examples
run: |
echo "Current working directory: $(pwd)"
if [ -d "./examples" ]; then
examples=$(find ./examples -name "*.ino" -print0 | tr '\0' ' ')
echo "Found examples: $examples"
echo "examples=$examples" >> $GITHUB_OUTPUT
else
echo "The './examples' directory does not exist."
exit 1
fi
- name: Run test
run: |
for example in ${{ steps.find-examples.outputs.examples }}; do
echo "Compiling example: $example"
arduino-cli compile --library . -b ${{ matrix.board.fqbn }} $example
if [ $? -ne 0 ]; then
echo "Compilation failed for example: $example"
exit 1
fi
echo "Compilation succeeded for example: $example"
done

View File

@ -0,0 +1,38 @@
name: Build with ESP-IDF
on:
workflow_dispatch:
pull_request:
push:
paths:
- "src/**"
- "examples/ESP_IDF_TouchDrvExample/**"
- "examples/ESP_IDF_SensorExamples/**"
- ".github/workflows/esp-idf.yml"
jobs:
esp-idf-build:
strategy:
matrix:
idf_ver: ["latest"]
runs-on: ubuntu-latest
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Build ESP_IDF_TouchDrvExample
shell: bash
run: |
pwd
. ${IDF_PATH}/export.sh
cd examples/ESP_IDF_TouchDrvExample
idf.py build
- name: Build ESP_IDF_SensorExamples
shell: bash
run: |
pwd
. ${IDF_PATH}/export.sh
cd examples/ESP_IDF_SensorExamples
idf.py build

View File

@ -0,0 +1,80 @@
name: Build with PlatformIO
on:
workflow_dispatch:
pull_request:
push:
paths:
- "src/**"
- "examples/**"
- ".github/workflows/platformio.yml"
- "platformio.ini"
jobs:
platformio-build:
runs-on: ubuntu-latest
strategy:
matrix:
example: ${{ fromJSON(needs.find-examples.outputs.examples) }}
needs: [find-examples]
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install MadgwickAHRS library
run: pio pkg install --library "arduino-libraries/Madgwick@^1.2.0" -g
- name: Install esp8266-oled-ssd1306 library
run: pio pkg install --library "thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays @ ^4.4.0" -g
- name: Install Commander library
run: pio pkg install --library "creativerobotics/Commander @ ^4.3.0" -g
- name: Install SdFat
run: pio pkg install --library "adafruit/SdFat - Adafruit Fork @ ^2.2.3" -g
- name: Run PlatformIO
run: pio ci --lib="." --board=esp32-s3-devkitm-1 --board=nrf52840_dk_adafruit
env:
PLATFORMIO_CI_SRC: ${{ matrix.example }}
find-examples:
runs-on: ubuntu-latest
outputs:
examples: ${{ steps.find.outputs.examples }}
steps:
- uses: actions/checkout@v3
- name: Create Python script
run: |
cat << 'EOF' > find_examples.py
import os
import json
examples_dir = 'examples'
ino_folders = []
for root, dirs, files in os.walk(examples_dir):
for file in files:
if file.endswith('.ino'):
ino_folders.append(root)
break
unique_folders = sorted(set(ino_folders))
print(json.dumps(unique_folders))
EOF
- name: Run Python script
id: find
run: |
result=$(python find_examples.py)
echo "::set-output name=examples::$result"

View File

@ -0,0 +1,11 @@
.pio
.vscode
test
.travis.yml
test
assets
*.bk
*.test
build
*.old
sdkconfig

View File

@ -0,0 +1,19 @@
set(src_dirs ./src
./src/touch
./src/platform
./src/bosch
./src/bosch/BMM150
./src/bosch/common
)
set(include_dirs ./src
./src/REG
./src/touch
./src/platform
./src/bosch
./src/bosch/firmware
./src/bosch/BMM150
./src/bosch/common)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs}
REQUIRES esp_timer esp_driver_gpio driver)

View File

@ -0,0 +1,16 @@
menu "SensorLib Configuration"
choice SensorLib_ESP_IDF_API
prompt "SensorLib library esp-idf api version"
default SENSORLIB_ESP_IDF_NEW_API
help
Define API version
config SENSORLIB_ESP_IDF_NEW_API
bool "Use esp-idf higher version (>= 5.0) API"
config SENSORLIB_ESP_IDF_OLD_API
bool "Use esp-idf lower version ( < 5.0) API , Compatible with lower versions of esp-idf"
endchoice
endmenu

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,44 @@
<center><img src="extras/images/SensroLib.jpg" width="80%" height="30%"></center>
[![Build with ESP-IDF](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml)
[![Build with Arduino](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml)
[![Build with PlatformIO](https://github.com/lewisxhe/SensorLib/actions/workflows/platformio.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/platformio.yml)
[![arduino-library-badge](https://www.ardu-badge.com/badge/SensorLib.svg?)](https://www.ardu-badge.com/SensorLib)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/lewisxhe/library/SensorLib.svg)](https://registry.platformio.org/libraries/lewisxhe/SensorLib)
[![LICENSE](https://img.shields.io/github/license/lewisxhe/SensorLib)](https://github.com/lewisxhe/SensorLib/blob/master/LICENSE)
[![ISSUES](https://img.shields.io/github/issues/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/issues)
[![FORK](https://img.shields.io/github/forks/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/graphs/contributors)
[![STAR](https://img.shields.io/github/stars/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/stargazers)
[![releases](https://img.shields.io/github/release/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorLib/releases)
Support list:
| Sensor | Description | I2C | SPI |
| --------------- | ------------------------ | --- | --- |
| PCF8563/HYM8563 | Real-time clock | ✔️ | ❌ |
| PCF85063 | Real-time clock | ✔️ | ❌ |
| QMI8658 | IMU | ✔️ | ✔️ |
| BHI260AP | IMU | ✔️ | ✔️ |
| QMC6310 | Magnetic Sensor | ✔️ | ❌ |
| BMM150 | Magnetic Sensor | ✔️ | ❌ |
| XL9555 | I/O expander | ✔️ | ❌ |
| BMA423 | Accelerometer | ✔️ | ❌ |
| DRV2605 | Haptic Driver | ✔️ | ❌ |
| CM32181 | Ambient Light Sensor | ✔️ | ❌ |
| LTR553 | Light & Proximity Sensor | ✔️ | ❌ |
| FT3267 | Capacitive touch | ✔️ | ❌ |
| FT5206 | Capacitive touch | ✔️ | ❌ |
| FT6206 | Capacitive touch | ✔️ | ❌ |
| FT6236 | Capacitive touch | ✔️ | ❌ |
| CST820 | Capacitive touch | ✔️ | ❌ |
| CST816S/T/D | Capacitive touch | ✔️ | ❌ |
| CST226SE | Capacitive touch | ✔️ | ❌ |
| CHSC5816 | Capacitive touch | ✔️ | ❌ |
| GT911 | Capacitive touch | ✔️ | ❌ |
| CST9217 | Capacitive touch | ✔️ | ❌ |
| CST9220 | Capacitive touch | ✔️ | ❌ |
| GT9895 | Capacitive touch | ✔️ | ❌ |
| AW9364 | Led Driver (GPIO) | ❌ | ❌ |

View File

@ -0,0 +1,70 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file AW9364_LedDriver.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-11-22
*/
#include <Arduino.h>
#include "AW9364LedDriver.hpp"
#ifdef ENABLE_TFT
#include "TFT_eSPI.h"
TFT_eSPI tft;
#endif
// Drive LED pin
#define BACKLIGHT_PIN 2
AW9364LedDriver ledDriver;
uint8_t level = 0;
void setup()
{
Serial.begin(115200);
#ifdef ENABLE_TFT
tft.begin();
tft.setRotation(1);
tft.fillScreen(TFT_GREEN);
#endif
// Initialize LED driver
ledDriver.begin(BACKLIGHT_PIN);
}
void loop()
{
// 16 dimming levels
Serial.print("level:");
Serial.println(level);
ledDriver.setBrightness(level);
level++;
level %= MAX_BRIGHTNESS_STEPS;
delay(1000);
}

View File

@ -0,0 +1,293 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_6DoF.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-06
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorXYZ accel(SensorBHI260AP::ACCEL_PASSTHROUGH, bhy);
SensorXYZ gyro(SensorBHI260AP::GYRO_PASSTHROUGH, bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void xyz_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_xyz data;
float scaling_factor = bhy.getScaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(" ");
Serial.print("x: ");
Serial.print(data.x * scaling_factor);
Serial.print(", y: ");
Serial.print(data.y * scaling_factor);
Serial.print(", z: ");
Serial.print(data.z * scaling_factor);
Serial.println(";");
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
float sample_rate = 100.0; /* Read out data measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
#ifdef USING_DATA_HELPER
// Enable acceleration
accel.enable(sample_rate, report_latency_ms);
// Enable gyroscope
gyro.enable(sample_rate, report_latency_ms);
#else
// Enable acceleration
bhy.configure(SensorBHI260AP::ACCEL_PASSTHROUGH, sample_rate, report_latency_ms);
// Enable gyroscope
bhy.configure(SensorBHI260AP::GYRO_PASSTHROUGH, sample_rate, report_latency_ms);
// Set the acceleration sensor result callback function
bhy.onResultEvent(SensorBHI260AP::ACCEL_PASSTHROUGH, xyz_process_callback);
// Set the gyroscope sensor result callback function
bhy.onResultEvent(SensorBHI260AP::GYRO_PASSTHROUGH, xyz_process_callback);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (accel.hasUpdated() && gyro.hasUpdated()) {
uint32_t s;
uint32_t ns;
accel.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] AX:%+7.2f AY:%+7.2f AZ:%+7.2f GX:%+7.2f GY:%+7.2f GZ:%+7.2f \n",
s, ns, accel.getX(), accel.getY(), accel.getZ(),
gyro.getX(), gyro.getY(), gyro.getZ());
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("] AX:");
Serial.print(accel.getX(), 2);
Serial.print(" AY:");
Serial.print(accel.getY(), 2);
Serial.print(" AZ:");
Serial.print(accel.getZ(), 2);
Serial.print(" GX:");
Serial.print(gyro.getX(), 2);
Serial.print(" GY:");
Serial.print(gyro.getY(), 2);
Serial.print(" GZ:");
Serial.print(gyro.getZ(), 2);
Serial.println();
#endif
}
#endif /*USING_DATA_HELPER*/
delay(50);
}

View File

@ -0,0 +1,278 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Activity .ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-04
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
SensorActivity activity(bhy);
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
float sample_rate = 1.0;
uint32_t report_latency_ms = 0;
/**
* Configure the activity recognition sensor of the BHI260AP sensor.
*
* This function sets the sampling rate and report latency for the activity recognition sensor.
* The sampling rate determines how often the sensor takes measurements, and the report latency
* determines the delay between when a measurement is taken and when it is reported.
* The activity recognition sensor will only be triggered when there is a change.
* @param samplingRate The sampling rate of the sensor. A value greater than 1 enables the sensor,
* while a value of 0 disables it.
* @param latencyMs The report latency in milliseconds.
*/
activity.enable(sample_rate, report_latency_ms);
// Set the specified pin (BHI260_IRQ) as an input pin.
// This prepares the pin to receive external signals.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) to the specified pin (BHI260_IRQ).
// The ISR 'dataReadyISR' will be called whenever a rising edge is detected on the pin.
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
if (activity.hasUpdated()) {
if (activity.isActivitySet(SensorActivity::STILL_ACTIVITY_ENDED)) {
Serial.println("Still activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::WALKING_ACTIVITY_ENDED)) {
Serial.println("Walking activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::RUNNING_ACTIVITY_ENDED)) {
Serial.println("Running activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::ON_BICYCLE_ACTIVITY_ENDED)) {
Serial.println("On Bicycle activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::IN_VEHICLE_ACTIVITY_ENDED)) {
Serial.println("In Vehicle activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::TILTING_ACTIVITY_ENDED)) {
Serial.println("Tilting activity ended is set.");
}
if (activity.isActivitySet(SensorActivity::IN_VEHICLE_STILL_ENDED)) {
Serial.println("In Vehicle still ended is set.");
}
if (activity.isActivitySet(SensorActivity::STILL_ACTIVITY_STARTED)) {
Serial.println("Still activity started is set.");
}
if (activity.isActivitySet(SensorActivity::WALKING_ACTIVITY_STARTED)) {
Serial.println("Walking activity started is set.");
}
if (activity.isActivitySet(SensorActivity::RUNNING_ACTIVITY_STARTED)) {
Serial.println("Running activity started is set.");
}
if (activity.isActivitySet(SensorActivity::ON_BICYCLE_ACTIVITY_STARTED)) {
Serial.println("On Bicycle activity started is set.");
}
if (activity.isActivitySet(SensorActivity::IN_VEHICLE_ACTIVITY_STARTED)) {
Serial.println("In Vehicle activity started is set.");
}
if (activity.isActivitySet(SensorActivity::TILTING_ACTIVITY_STARTED)) {
Serial.println("Tilting activity started is set.");
}
if (activity.isActivitySet(SensorActivity::IN_VEHICLE_STILL_STARTED)) {
Serial.println("In Vehicle still started is set.");
}
}
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
delay(50);
}

View File

@ -0,0 +1,326 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Euler.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-04
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorQuaternion quaternion(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
/**
* @brief Parse the quaternion data from the sensor and convert it to Euler angles.
*
* This function serves as a callback to handle the sensor data related to the game rotation vector.
* It takes the raw quaternion data received from the sensor, converts it into Euler angles (roll, pitch, and yaw),
*
* @param sensor_id The ID of the sensor that generated the data. It helps in identifying which specific sensor
* the data is coming from, especially in systems with multiple sensors.
* @param data_ptr A pointer to the buffer containing the raw quaternion data. The data in this buffer
* represents the orientation of the sensor in quaternion format.
* @param len The length of the data buffer, indicating the size of the quaternion data in bytes.
* @param timestamp A pointer to a 64 - bit unsigned integer representing the timestamp when the sensor data was captured.
* This can be used to correlate the data with a specific point in time.
* @param user_data A generic pointer to user - defined data.
*/
#ifndef USING_DATA_HELPER
void parse_quaternion(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
// Declare variables to store the Euler angles (roll, pitch, and yaw).
float roll, pitch, yaw;
// Call the bhy2_quaternion_to_euler function to convert the raw quaternion data
// pointed to by data_ptr into Euler angles (roll, pitch, and yaw).
bhy2_quaternion_to_euler(data_ptr, &roll, &pitch, &yaw);
// Print the roll angle to the serial monitor.
Serial.print(roll);
// Print a comma as a separator between the roll and pitch angles.
Serial.print(",");
// Print the pitch angle to the serial monitor.
Serial.print(pitch);
// Print a comma as a separator between the pitch and yaw angles.
Serial.print(",");
// Print the yaw angle to the serial monitor and start a new line.
Serial.println(yaw);
}
#endif
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
/**
* @brief Set the axis remapping for the sensor based on the specified orientation.
*
* This function allows you to configure the sensor's axis remapping according to a specific
* physical orientation of the chip. By passing one of the values from the SensorRemap enum,
* you can ensure that the sensor data is correctly interpreted based on how the chip is placed.
* [bst-bhi260ab-ds000.pdf](https://www.mouser.com/datasheet/2/783/bst-bhi260ab-ds000-1816249.pdf)
* 20.3 Sensing axes and axes remapping
* @param remap An enumeration value from SensorRemap that specifies the desired axis remapping.
* @return Returns true if the axis remapping is successfully set; false otherwise.
*/
// Set the sensor's axis remapping based on the chip's orientation.
// These commented-out lines show different ways to configure the sensor according to the chip's corners.
// When the chip is viewed from the top, set the orientation to the top-left corner.
// bhy.setRemapAxes(SensorBHI260AP::TOP_LAYER_LEFT_CORNER);
// When the chip is viewed from the top, set the orientation to the top-right corner.
// bhy.setRemapAxes(SensorBHI260AP::TOP_LAYER_RIGHT_CORNER);
// When the chip is viewed from the top, set the orientation to the bottom-right corner of the top layer.
// bhy.setRemapAxes(SensorBHI260AP::TOP_LAYER_BOTTOM_RIGHT_CORNER);
// When the chip is viewed from the top, set the orientation to the bottom-left corner of the top layer.
// bhy.setRemapAxes(SensorBHI260AP::TOP_LAYER_BOTTOM_LEFT_CORNER);
// When the chip is viewed from the bottom, set the orientation to the top-left corner of the bottom layer.
// bhy.setRemapAxes(SensorBHI260AP::BOTTOM_LAYER_TOP_LEFT_CORNER);
// When the chip is viewed from the bottom, set the orientation to the top-right corner of the bottom layer.
// bhy.setRemapAxes(SensorBHI260AP::BOTTOM_LAYER_TOP_RIGHT_CORNER);
// When the chip is viewed from the bottom, set the orientation to the bottom-right corner of the bottom layer.
// bhy.setRemapAxes(SensorBHI260AP::BOTTOM_LAYER_BOTTOM_RIGHT_CORNER);
// When the chip is viewed from the bottom, set the orientation to the bottom-left corner of the bottom layer.
// bhy.setRemapAxes(SensorBHI260AP::BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
// Define the sample rate for data reading.
// The sensor will read out data measured at a frequency of 100Hz.
float sample_rate = 100.0;
// Define the report latency in milliseconds.
// A value of 0 means the sensor will report the measured data immediately.
uint32_t report_latency_ms = 0;
#ifdef USING_DATA_HELPER
quaternion.enable(sample_rate, report_latency_ms);
#else
// GAME_ROTATION_VECTOR virtual sensor does not rely on external magnetometers, such as BMM150, BMM350
// Configure the sensor to measure the game rotation vector.
// Set the sample rate and report latency for this measurement.
bhy.configure(SensorBHI260AP::GAME_ROTATION_VECTOR, sample_rate, report_latency_ms);
// Register a callback function 'parse_quaternion' to handle the result events of the game rotation vector measurement.
// When the sensor has new data for the game rotation vector, the 'parse_quaternion' function will be called.
bhy.onResultEvent(SensorBHI260AP::GAME_ROTATION_VECTOR, parse_quaternion);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (quaternion.hasUpdated()) {
// Convert rotation vector to Euler angles
quaternion.toEuler();
// Print the roll angle to the serial monitor.
Serial.print(quaternion.getRoll());
// Print a comma as a separator between the roll and pitch angles.
Serial.print(",");
// Print the pitch angle to the serial monitor.
Serial.print(quaternion.getPitch());
// Print a comma as a separator between the pitch and yaw angles.
Serial.print(",");
// Print the yaw angle to the serial monitor and start a new line.
Serial.println(quaternion.getHeading());
}
#endif
delay(50);
}

View File

@ -0,0 +1,319 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Expand_GPIO.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-04
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#include <Commander.h> //Deplib https://github.com/CreativeRobotics/Commander
Commander cmd;
void initialiseCommander();
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
#define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
initialiseCommander();
Serial.println("Hello: Type 'help' to get help");
cmd.printCommandPrompt();
// Register interrupt function
pinMode(BHI260_IRQ, INPUT);
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
uint32_t check_millis = 0;
void loop()
{
//Call the update functions using the activeCommander pointer
cmd.update();
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
}
//All commands for 'master'
//COMMAND ARRAY ------------------------------------------------------------------------------
const commandList_t masterCommands[] = {
{"help", helpHandler, "help"},
{"set gpio", setGpioLevel, "set gpio level"},
{"get gpio", getGpioLevel, "get gpio level"},
{"dis gpio", disGpioMode, "disable gpio"},
};
void initialiseCommander()
{
cmd.begin(&Serial, masterCommands, sizeof(masterCommands));
cmd.commandPrompt(ON); //enable the command prompt
cmd.echo(true); //Echo incoming characters to theoutput port
cmd.errorMessages(ON); //error messages are enabled - it will tell us if we issue any unrecognised commands
//Error messaged do NOT work for quick set and get commands
}
bool helpHandler(Commander &Cmdr)
{
Serial.println("Help:");
Serial.println("\tCustom firmware valid gpio : 1, 4, 5, 6, 14, 15, 16, 17, 18, 19, 20");
Serial.println("\tset gpio [gpio num] [level]");
Serial.println("\tget gpio [gpio num] [pullup]");
Serial.println("\tdis gpio [gpio num]");
return 0;
}
/*
* GPIO Comparison Table
* M1SCX = N.A ! INVALID PIN
* M1SDX = N.A ! INVALID PIN
* M1SDI = N.A ! INVALID PIN
* M2SCX = 14 ! OK
* M2SDX = 15 ! OK
* M2SDI = 16 ! OK
* MCSB1 = 1 ! OK
* MCSB2 = 4 ! OK
* M3SCL = 17 ! OK
* M3SDA = 18 ! OK
* MCSB3 = 5 ! OK
* MCSB4 = 6 ! OK
* JTAG_CLK = 19 ! OK
* JTAG_DIO = 20 ! OK
* RESV1 = 2 ! INVALID PIN
* RESV2 = 3 ! INVALID PIN
* RESV3 = N.A ! INVALID PIN
* */
bool setGpioLevel(Commander &Cmdr)
{
int values[2] = {0, 0};
int items = Cmdr.countItems();
if (items < 2) {
return false;
}
for (int n = 0; n < 2; n++) {
Cmdr.getInt(values[n]);
}
uint8_t pin = values[0];
uint8_t level = values[1];
bhy.digitalWrite(pin, level);
return 0;
}
bool getGpioLevel(Commander &Cmdr)
{
int values[2] = {0, 0};
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
if (items > 2 )items = 2;
for (int n = 0; n < items; n++) {
Cmdr.getInt(values[n]);
}
bool pullup = false;
uint8_t pin = values[0];
if (items == 2 ) {
pullup = values[1];
}
uint8_t level = bhy.digitalRead(pin, pullup);
Serial.print("Get GPIO : "); Serial.print(pin);
Serial.print(" level is "); Serial.println(level);
return 0;
}
bool disGpioMode(Commander &Cmdr)
{
int values[1] = {0};
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
Cmdr.getInt(values[0]);
uint8_t pin = values[0];
bhy.disableGpio(pin);
return 0;
}

View File

@ -0,0 +1,276 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Klio_Recognition.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-02
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#include "SensorBHI260AP_Klio.hpp"
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
SensorBHI260AP_Klio klio(bhy);
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_BHI260_KLIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_BHI260_KLIO_FLASH
// #define BOSCH_BHI260_KLIO_TURBO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
/* Action 1 mode, BHI260 should point upwards, for action instructions,
see action1.gif in the example directory */
uint8_t action1_pattern_id = 1;
uint8_t action1_pattern[] = {
0x52, 0x42, 0x31, 0x06, 0x03, 0xfd, 0xad, 0x80,
0x40, 0x0a, 0xd7, 0x23, 0x3c, 0x78, 0xe2, 0x44,
0xbf, 0x63, 0xe1, 0x0d, 0xc0, 0x19, 0x39, 0x97,
0xbf, 0xdb, 0x93, 0x04, 0x3f, 0xce, 0x07, 0xb7,
0x3e, 0x5e, 0xda, 0xf0, 0x3d, 0xe3, 0x6f, 0x8f,
0x3e, 0x65, 0x7c, 0x4f, 0x40, 0x46, 0x3f, 0xb4,
0x3f, 0xdf, 0xd1, 0x3d, 0xbf, 0xfa, 0x5a, 0x82,
0xbf, 0x35, 0xf6, 0x16, 0x3e, 0xbe, 0x70, 0x82,
0x40, 0xaa, 0x21, 0x70, 0x41, 0xcb, 0x27, 0xf0,
0x40, 0x19, 0x06, 0xd9, 0xbf, 0x3a, 0x10, 0xa7,
0xbf, 0x27, 0x07, 0x31, 0x3f, 0x27, 0x23, 0xc9,
0xbd, 0x44, 0x29, 0x2f, 0x40, 0xa6, 0x61, 0x97,
0xc0, 0x29, 0x5d, 0x21, 0xbe, 0x82, 0xd4, 0x0d,
0x3e, 0xc0, 0xf0, 0x15, 0x3d, 0x00, 0xbc, 0xda,
0x3d, 0x14, 0x0c, 0xc5, 0xbd, 0x46, 0xa0, 0x03,
0x3e, 0xca, 0x5c, 0x95, 0x3d, 0x24, 0xe5, 0x13,
0x3c, 0x70, 0x0a, 0x81, 0x3c, 0x69, 0x22, 0xd6,
0x3c, 0x51, 0xa4, 0xdf, 0x3e, 0x4c, 0xa8, 0x55,
0xbf, 0xe1, 0xe8, 0xc7, 0xbd, 0xe8, 0x7c, 0xbe,
0x3d, 0xf7, 0x5b, 0x21, 0x3c
};
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
// Attempt to initialize the KLIO sensor.
if (!klio.begin()) {
while (1) {
Serial.println("Failed to initialize Klio sensor. Are you currently using a firmware that includes Klio sensor functionality?");
delay(1000);
}
}
// Call the getMaxPatterns() method of the klio object to get the maximum number of patterns allowed by the KLIO sensor.
// This method returns a value of type uint8_t representing the maximum number of patterns and stores it in the variable max_patterns.
uint8_t max_patterns = klio.getMaxPatterns();
Serial.print("Klio sensor max patterns:");
Serial.println(max_patterns);
// Set the callback function for the recognition event of the KLIO sensor.
// The callback function takes a pattern ID, a count value, and a pointer to user data as parameters.
// When a recognition event occurs, the callback function will be called, and it will print
// information about the recognized pattern (pattern ID and count) to the serial monitor.
// The user data pointer setting can be set to nullptr, or custom data can be passed in.
// If the recognition action is successful, the pointer is passed to the callback function
klio.setRecognitionCallback([](uint8_t pattern_id, float count, void *user_data) {
Serial.print("<-Recognition[Id:");
Serial.print(pattern_id);
Serial.print(" Count:");
Serial.print(count);
Serial.print("]");
}, nullptr);
// Try to write a pattern to the KLIO sensor.
// The pattern ID is specified by action1_pattern_id,
// and the pattern data is stored in the action1_pattern array.
// The size of the pattern data is determined by sizeof(action1_pattern).
if (!klio.writePattern(action1_pattern_id,
action1_pattern,
sizeof(action1_pattern))) {
Serial.println("Klio write pattern failed!");
}
// Start the recognition process for a specific pattern.
// Pass the address of action1_pattern_id (indicating the pattern to be recognized)
// and the number of patterns (1 in this case) to the recognition function.
klio.recognition(&action1_pattern_id, 1);
// Define the sample rate at which data will be read from the KLIO sensor.
// Here, the sample rate is set to 25Hz, meaning data will be read 25 times per second.
float sample_rate = 25.0;
// Define the report latency in milliseconds.
// A value of 0 means that the sensor will report data immediately as it is measured.
uint32_t report_latency_ms = 0;
// Enable the KLIO sensor with he specified sample rate and report latency.
// Once enabled, the sensor will start collecting and reporting data according to these settings.
klio.enable(sample_rate, report_latency_ms);
// Set the specified pin (BHI260_IRQ) as an input pin.
// This prepares the pin to receive external signals.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) to the specified pin (BHI260_IRQ).
// The ISR 'dataReadyISR' will be called whenever a rising edge is detected on the pin.
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
delay(50);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,346 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Klio_RecognizeMultiple.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-02
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#include "SensorBHI260AP_Klio.hpp"
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
SensorBHI260AP_Klio klio(bhy);
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_BHI260_KLIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_BHI260_KLIO_FLASH
// #define BOSCH_BHI260_KLIO_TURBO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
/* Action 1 mode, BHI260 should point upwards, for action instructions,
see action1.gif in the example directory */
uint8_t action1_pattern_id = 1;
uint8_t action1_pattern[] = {
0x52, 0x42, 0x31, 0x06, 0x03, 0xfd, 0xad, 0x80,
0x40, 0x0a, 0xd7, 0x23, 0x3c, 0x78, 0xe2, 0x44,
0xbf, 0x63, 0xe1, 0x0d, 0xc0, 0x19, 0x39, 0x97,
0xbf, 0xdb, 0x93, 0x04, 0x3f, 0xce, 0x07, 0xb7,
0x3e, 0x5e, 0xda, 0xf0, 0x3d, 0xe3, 0x6f, 0x8f,
0x3e, 0x65, 0x7c, 0x4f, 0x40, 0x46, 0x3f, 0xb4,
0x3f, 0xdf, 0xd1, 0x3d, 0xbf, 0xfa, 0x5a, 0x82,
0xbf, 0x35, 0xf6, 0x16, 0x3e, 0xbe, 0x70, 0x82,
0x40, 0xaa, 0x21, 0x70, 0x41, 0xcb, 0x27, 0xf0,
0x40, 0x19, 0x06, 0xd9, 0xbf, 0x3a, 0x10, 0xa7,
0xbf, 0x27, 0x07, 0x31, 0x3f, 0x27, 0x23, 0xc9,
0xbd, 0x44, 0x29, 0x2f, 0x40, 0xa6, 0x61, 0x97,
0xc0, 0x29, 0x5d, 0x21, 0xbe, 0x82, 0xd4, 0x0d,
0x3e, 0xc0, 0xf0, 0x15, 0x3d, 0x00, 0xbc, 0xda,
0x3d, 0x14, 0x0c, 0xc5, 0xbd, 0x46, 0xa0, 0x03,
0x3e, 0xca, 0x5c, 0x95, 0x3d, 0x24, 0xe5, 0x13,
0x3c, 0x70, 0x0a, 0x81, 0x3c, 0x69, 0x22, 0xd6,
0x3c, 0x51, 0xa4, 0xdf, 0x3e, 0x4c, 0xa8, 0x55,
0xbf, 0xe1, 0xe8, 0xc7, 0xbd, 0xe8, 0x7c, 0xbe,
0x3d, 0xf7, 0x5b, 0x21, 0x3c
};
/* Action 2 mode, BHI260 should point to the right,
for action instructions, see action2.gif in the example directory*/
uint8_t action2_pattern_id = 2;
const uint8_t action2_pattern[] = {
0x52, 0x42, 0x31, 0x06, 0x03, 0xfd, 0xad, 0x80,
0x40, 0x0a, 0xd7, 0x23, 0x3c, 0x38, 0xf3, 0x08,
0x40, 0x1a, 0x9e, 0x06, 0xbf, 0xde, 0xcd, 0xca,
0x3d, 0x88, 0xb3, 0x9b, 0x3e, 0x01, 0x26, 0xb9,
0x3d, 0x8f, 0xe9, 0x88, 0x3d, 0x6e, 0xc3, 0x13,
0xc1, 0x4f, 0x1e, 0x09, 0x40, 0x75, 0x7a, 0x2d,
0xc0, 0x80, 0x31, 0xdb, 0xbd, 0x2f, 0x1e, 0x83,
0x3f, 0xc0, 0x6f, 0x10, 0x3d, 0xf7, 0xc1, 0x26,
0xbf, 0x5a, 0x36, 0x00, 0x3f, 0x8b, 0x31, 0x77,
0xbe, 0x51, 0x09, 0x3b, 0xbf, 0x16, 0xa9, 0xa0,
0xbf, 0x6d, 0x90, 0x89, 0x3d, 0x39, 0x79, 0xb3,
0x3d, 0x39, 0x0e, 0x9f, 0xbd, 0xfc, 0x77, 0x55,
0xbd, 0x69, 0x44, 0x13, 0xbf, 0x02, 0x31, 0x14,
0x3e, 0x60, 0xe6, 0x75, 0x3b, 0xd2, 0x69, 0x19,
0xbc, 0xa8, 0x41, 0x46, 0x3d, 0x87, 0x45, 0x88,
0x3e, 0x70, 0xf7, 0x87, 0x3d, 0x81, 0x8a, 0xe2,
0x3d, 0xea, 0x15, 0x8d, 0x3b, 0xf5, 0x2e, 0xc1,
0x3c, 0x1e, 0xcc, 0x05, 0x3e, 0x00, 0x70, 0x16,
0x3c, 0x41, 0x8b, 0x07, 0xbe, 0x4e, 0xd8, 0xb0,
0x3d, 0x94, 0xd9, 0x40, 0x3b
};
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
/**
* @brief Callback function for KLIO sensor recognition events.
*
* This function serves as a callback that gets triggered when the KLIO sensor
* successfully recognizes a pattern. It's designed to handle the recognition
* event and provide information about the recognized pattern.
*
* @param pattern_id The unique identifier of the recognized pattern.
* Each pattern in the KLIO sensor's recognition library
* is assigned a distinct ID, and this parameter indicates
* which specific pattern has been recognized.
* @param count A floating point value representing the number of actions with
* the recognized pattern
* @param user_data A generic pointer to user - defined data. This can be used
* to pass additional context or information from the calling
* code to the callback function.
*/
void recognition_event_callback(uint8_t pattern_id, float count, void *user_data)
{
Serial.print("<-Recognition[Id:");
Serial.print(pattern_id);
Serial.print(" Count:");
Serial.print(count);
Serial.print("]");
// When the recognition counter is greater than 10 times, reset the recognition counter
if (count > 10) {
Serial.println("Reset recognition counter!");
// Disable Klio
klio.disable();
// Restart Recognition
beginRecognition();
}
}
void beginRecognition()
{
// Define an array to hold the IDs of the patterns to be written to the KLIO sensor.
// 'action1_pattern_id' and 'action2_pattern_id' are predefined pattern IDs.
uint8_t patterns_ids[] = {action1_pattern_id, action2_pattern_id};
// Define an array of pointers to the actual pattern data.
// 'action1_pattern' and 'action2_pattern' are arrays containing the pattern data.
const uint8_t *patterns[] = {action1_pattern, action2_pattern};
// Define an array to hold the sizes of each pattern.
// Use the sizeof operator to determine the size of each pattern array.
uint16_t patterns_sizes[] = {sizeof(action1_pattern), sizeof(action2_pattern)};
// Calculate the number of patterns in the 'patterns_ids' array.
// This is done by dividing the total size of the array by the size of a single element.
uint8_t patterns_count = sizeof(patterns_ids) / sizeof(patterns_ids[0]);
// Try to write multiple patterns to the KLIO sensor.
// Call the writeMultiplePatterns() method with the arrays of pattern IDs, pattern data pointers,
// pattern sizes, and the number of patterns. If the write operation fails, print an error message.
if (!klio.writeMultiplePatterns(patterns_ids, patterns, patterns_sizes, patterns_count)) {
Serial.println("Klio write multiple patterns failed!");
}
// Start the recognition process for the specified patterns.
// Call the recognition() method with the array of pattern IDs and the number of patterns.
klio.recognition(patterns_ids, patterns_count);
// Define the sample rate for data reading.
// The sample rate is set to 25.0 Hz, meaning data will be read 25 times per second.
float sample_rate = 25.0; /* Read out data measured at 25Hz */
// Define the report latency in milliseconds.
// A value of 0 means that the sensor will report data immediately as it is measured.
uint32_t report_latency_ms = 0; /* Report immediately */
// Enable the KLIO sensor with the specified sample rate and report latency.
// Call the enable() method to activate the sensor and configure it according to the settings.
klio.enable(sample_rate, report_latency_ms);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
// Try to initialize the KLIO sensor.
if (!klio.begin()) {
while (1) {
Serial.println("Failed to initialize Klio sensor. Are you currently using a firmware that includes Klio sensor functionality?");
delay(1000);
}
}
// Set the callback function for recognition events.
// Similar to the learning callback, the setRecognitionCallback() method registers a function
// that will be invoked when a recognition - related event happens in the KLIO sensor.
// 'recognition_event_callback' is the callback function, and 'nullptr' is used as the user data pointer.
klio.setRecognitionCallback(recognition_event_callback, nullptr);
// Start Recognition
beginRecognition();
// Set the specified pin (BHI260_IRQ) as an input pin.
// This prepares the pin to receive external signals.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) to the specified pin (BHI260_IRQ).
// The ISR 'dataReadyISR' will be called whenever a rising edge is detected on the pin.
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
Serial.println("Please check the gif(atcion1.gif,action2.gif) image in the example directory to see the action instructions."
"If the action meets the record value, the action record counter will be triggered.");
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
delay(50);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

View File

@ -0,0 +1,348 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Klio_Selflearning.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-02
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#include "SensorBHI260AP_Klio.hpp"
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
SensorBHI260AP_Klio klio(bhy);
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_BHI260_KLIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_BHI260_KLIO_FLASH
// #define BOSCH_BHI260_KLIO_TURBO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
/**
* @brief Callback function for handling KLIO sensor recognition events.
*
* This function is invoked when the KLIO sensor successfully recognizes a specific pattern.
* Its main purpose is to print information about the recognized pattern, including the pattern ID
* and the recognition count, to the serial monitor. This allows developers to monitor the recognition
* process effectively.
*
* @param pattern_id The unique identifier of the recognized pattern. Each predefined or learned
* pattern in the system has a distinct ID, and this parameter indicates which
* specific pattern has been recognized.
* @param count A floating-point value representing the recognition count. This could be the number
* of times the pattern has been recognized, a confidence level associated with the
* recognition, or some other metric depending on the implementation of the recognition
* algorithm.
* @param user_data A pointer to user-defined data. It can be used to pass additional context or
* information from the calling code to this callback function. In this implementation,
* it is not used, but it is included to maintain compatibility with the callback function signature.
*/
void recognition_event_callback(uint8_t pattern_id, float count, void *user_data)
{
Serial.print("<-Recognition[Id:");
Serial.print(pattern_id);
Serial.print(" Count:");
Serial.print(count);
Serial.print("]");
}
/**
* @brief Callback function for KLIO sensor learning events.
*
* This function is invoked whenever there is a change in the learning process of the KLIO sensor.
* It handles different learning - related events, logs information about the learning progress,
* and takes actions based on the learning results.
*
* @param reason The reason for the learning change. It is an enumeration value from the
* SensorBHI260AP_Klio::LeaningChangeReason type, indicating why the learning state has changed.
* @param progress The current progress of the learning process, represented as an unsigned 32 - bit integer.
* This value typically ranges from 0 to 100, indicating the percentage of the learning completion.
* @param learn_index The index of the learned pattern. If the learning is invalid, it will be set to
* SensorBHI260AP_Klio::INVALID_LEARNING_INDEX. Otherwise, it represents the index of the successfully learned pattern.
* @param user_data A pointer to user - defined data. It can be used to pass additional context information
* from the calling code to this callback function. In this implementation, it may not be used actively.
*/
void learning_event_callback(SensorBHI260AP_Klio::LeaningChangeReason reason, uint32_t progress, int learn_index, void *user_data)
{
// Print the learning event details to the serial monitor, including the progress, reason, and learned pattern index.
Serial.print("->Learning [Progress:");
Serial.print(progress);
Serial.print(" Reason:");
Serial.print(static_cast<uint8_t>(reason));
Serial.print(" ID:");
Serial.print(learn_index);
Serial.println("]");
// Check if the learning index is valid (not equal to INVALID_LEARNING_INDEX).
if (learn_index != SensorBHI260AP_Klio::INVALID_LEARNING_INDEX) {
// Create a buffer to store the learned pattern data. The buffer size is 252 bytes.
uint8_t tmp_buf[252];
// Store the size of the buffer. This variable will be updated with the actual size of the learned pattern.
uint16_t bufsize = sizeof(tmp_buf);
// Try to retrieve the learned pattern from the sensor using the getLearnPattern function.
// The result indicates whether the retrieval is successful.
bool learn_success = klio.getLearnPattern(tmp_buf, &bufsize);
if (!learn_success) {
// If the retrieval fails, print an error message and the specific error reason.
Serial.print("Read learnt failed. Reason:");
Serial.println(klio.errorToString());
} else {
// If the retrieval is successful, print a success message and the details of the learned pattern.
Serial.println("Learning the action successfully");
Serial.println("PATTERN LEARNT: ");
Serial.print("const uint8_t * learn_pattern = { ");
// Iterate through the buffer and print the pattern data in hexadecimal format.
for (uint16_t i = 0; i < bufsize; i++) {
if (i > 0 && i % 8 == 0) {
// Print a new line every 8 bytes for better readability.
Serial.println();
}
Serial.print("0x"); Serial.print(tmp_buf[i], HEX);
if (i < bufsize - 1) {
// Add a comma and a space after each byte except the last one.
Serial.print(", ");
}
}
Serial.println(" \n};\n");
}
// Print a message indicating that the learned pattern will be written.
Serial.println("Write the learning pattern.");
// Define an example pattern ID.
uint8_t examples_id = 1;
// Try to write the learned pattern to the sensor using the writePattern function.
if (!klio.writePattern(examples_id, tmp_buf, bufsize)) {
// If the write operation fails, print an error message.
Serial.println("Klio write pattern failed!");
}
// Print messages indicating that the action recognition will start.
Serial.println("Start recognizing actions");
Serial.println("Please perform the learned action instructions and the sensor will start to recognize the number of actions.");
// Start the recognition process for the specified pattern ID.
klio.recognition(&examples_id, 1);
}
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
// Try to initialize the KLIO sensor.
// The begin() method is called on the 'klio' object to set up the sensor.
if (!klio.begin()) {
while (1) {
Serial.println("Failed to initialize Klio sensor. Are you currently using a firmware that includes Klio sensor functionality?");
delay(1000);
}
}
// Call the getMaxPatterns() method of the klio object to get the maximum number of patterns allowed by the KLIO sensor.
// This method returns a value of type uint8_t representing the maximum number of patterns and stores it in the variable max_patterns.
uint8_t max_patterns = klio.getMaxPatterns();
Serial.print("Klio sensor max patterns:");
Serial.println(max_patterns);
// Set the callback function for learning events.
// The setLearningCallback() method is used to register a function that will be called
// whenever a learning - related event occurs in the KLIO sensor.
// 'learning_event_callback' is the name of the callback function,
// and 'nullptr' is passed as the user data pointer, meaning no additional user - specific data is provided.
klio.setLearningCallback(learning_event_callback, nullptr);
// Set the callback function for recognition events.
// Similar to the learning callback, the setRecognitionCallback() method registers a function
// that will be invoked when a recognition - related event happens in the KLIO sensor.
// 'recognition_event_callback' is the callback function, and 'nullptr' is used as the user data pointer.
klio.setRecognitionCallback(recognition_event_callback, nullptr);
// Start the learning process of the KLIO sensor.
// The learning() method initiates the sensor's functionality to start learning patterns or behaviors.
klio.learning();
// Define the sample rate for data reading.
// The variable'sample_rate' is set to 25.0, which means the sensor will read out data
// at a frequency of 25 Hertz (25 times per second).
float sample_rate = 25.0;
// Define the report latency in milliseconds.
// The variable'report_latency_ms' is set to 0, indicating that the sensor should report
// the measured data immediately without any delay.
uint32_t report_latency_ms = 0;
// Enable the KLIO sensor with he specified sample rate and report latency.
// The enable() method activates the sensor and configures it to operate at the given sample rate
// and report latency. This allows the sensor to start collecting and reporting data according to the settings.
klio.enable(sample_rate, report_latency_ms);
// Set the specified pin (BHI260_IRQ) as an input pin.
// This prepares the pin to receive external signals.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) to the specified pin (BHI260_IRQ).
// The ISR 'dataReadyISR' will be called whenever a rising edge is detected on the pin.
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
Serial.println("Please repeat the movements you want to learn and the sensor will start recording.");
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
delay(50);
}

View File

@ -0,0 +1,303 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_Orientation.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-07
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorOrientation orientation(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void print_orientation(uint8_t direction)
{
char report[256];
switch (direction) {
case SensorBHI260AP::DIRECTION_BOTTOM_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case SensorBHI260AP::DIRECTION_TOP_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBHI260AP::DIRECTION_TOP_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBHI260AP::DIRECTION_BOTTOM_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
default:
sprintf( report, "None of the 3D orientation axes is set in BHI260 - accelerometer.\r\n" );
break;
}
Serial.println(direction);
Serial.println(report);
}
#ifndef USING_DATA_HELPER
void orientation_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
uint8_t direction = *data_ptr;
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
print_orientation(direction);
}
#endif
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Init BHI260AP Sensor success!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
// The orientation sensor will only report when it changes, so the value is 0 ~ 1
float sample_rate = 1;
uint32_t report_latency_ms = 0; /* Report immediately */
#ifdef USING_DATA_HELPER
orientation.enable(sample_rate, report_latency_ms);
#else
// Enable direction detection
bhy.configure(SensorBHI260AP::DEVICE_ORIENTATION, sample_rate, report_latency_ms);
// Set the direction detection result output processing function
bhy.onResultEvent(SensorBHI260AP::DEVICE_ORIENTATION, orientation_process_callback);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (orientation.hasUpdated()) {
print_orientation(orientation.getOrientation());
}
#endif
delay(50);
}

View File

@ -0,0 +1,290 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_StepCounter.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-08
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorStepCounter stepCounter(bhy);
SensorStepDetector stepDetector(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
#define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void step_detector_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
Serial.print(bhy.getSensorName(sensor_id));
Serial.println(" detected.");
}
void step_counter_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(":");
Serial.println(bhy2_parse_step_counter(data_ptr));
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
// The stepcount sensor will only report when it changes, so the value is 0 ~ 1
float sample_rate = 1.0;
uint32_t report_latency_ms = 0; /* Report immediately */
#ifdef USING_DATA_HELPER
stepDetector.enable(sample_rate, report_latency_ms);
stepCounter.enable(sample_rate, report_latency_ms);
#else
// Enable Step detector
bhy.configure(SensorBHI260AP::STEP_DETECTOR, sample_rate, report_latency_ms);
// Enable Step counter
bhy.configure(SensorBHI260AP::STEP_COUNTER, sample_rate, report_latency_ms);
// Set the number of steps to detect the callback function
bhy.onResultEvent(SensorBHI260AP::STEP_DETECTOR, step_detector_process_callback);
bhy.onResultEvent(SensorBHI260AP::STEP_COUNTER, step_counter_process_callback);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
uint32_t s;
uint32_t ns;
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (stepCounter.hasUpdated()) {
stepCounter.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "]: Step Count:", s, ns);
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("]: Step Count:");
#endif
Serial.println(stepCounter.getStepCount());
}
if (stepDetector.hasUpdated()) {
if (stepDetector.isDetected()) {
stepDetector.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "]:", s, ns);
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("]:");
#endif
Serial.println("Step detector detects steps");
}
}
#endif
delay(50);
}

View File

@ -0,0 +1,292 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_UpdateFirmware.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-10-23
* @note Demonstrates loading firmware from a file into BHI260, only testing the NRF52840 platform
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#if defined(ARDUINO_ARCH_NRF52)
#include <SdFat.h> //Deplib https://github.com/adafruit/SdFat.git
#include <SensorBHI260AP.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_SPI_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
#define CS_PIN 5
/***************************************
* SD CARD
***************************************/
SdFat32 sd;
// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
#define SPI_CLOCK SD_SCK_MHZ(8)
//------------------------------------------------------------------------------
// Store error strings in flash to save RAM.
#define error(s) sd.errorHalt(&Serial, F(s))
#define SD_CONFIG SdSpiConfig(CS_PIN, DEDICATED_SPI, SPI_CLOCK)
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
void parse_bme280_sensor_data(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
float humidity = 0;
float temperature = 0;
float pressure = 0;
switch (sensor_id) {
case SensorBHI260AP::HUMIDITY:
bhy2_parse_humidity(data_ptr, &humidity);
Serial.print("humidity:"); Serial.print(humidity); Serial.println("%");
break;
case SensorBHI260AP::TEMPERATURE:
bhy2_parse_temperature_celsius(data_ptr, &temperature);
Serial.print("temperature:"); Serial.print(temperature); Serial.println("*C");
break;
case SensorBHI260AP::BAROMETER:
bhy2_parse_pressure(data_ptr, &pressure);
Serial.print("pressure:"); Serial.print(pressure); Serial.println("hPa");
break;
default:
Serial.println("Unkown.");
break;
}
}
void printResult(uint8_t sensor_id, float sample_rate, bool rlst)
{
const char *sensorName = bhy.getSensorName(sensor_id);
Serial.print("Configure ");
Serial.print(sensorName);
Serial.print(" sensor ");
Serial.print(sample_rate, 2);
Serial.print(" HZ ");
if (rlst) {
Serial.print("successfully");
} else {
Serial.print("failed");
}
Serial.println();
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// In this example, BHI260 and SD Card are on the same SPI bus
SPI.setPins(SPI_MISO, SPI_SCK, SPI_MOSI);
SPI.begin();
/***************************************
* SD CARD
***************************************/
// If multiple SPI peripherals are mounted on a single bus, first set the CS of other peripherals to HIGH
const uint8_t other_spi_dev_cs_pin[] = {5, 28, 40};
for (size_t i = 0; i < sizeof(other_spi_dev_cs_pin); ++i) {
pinMode(other_spi_dev_cs_pin[i], OUTPUT);
digitalWrite(other_spi_dev_cs_pin[i], HIGH);
}
// Initialize the SD card.
Serial.println("Initializing SD Card ...");
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
while (1);
} else {
Serial.println(" success");
}
File firmware_file = sd.open("/BHI260AP_aux_BMM150_BME280_GPIO-flash.fw", FILE_READ);
if (!firmware_file) {
Serial.println("Open firmware file failed!");
while (1);
}
size_t fw_size = firmware_file.size();
Serial.println("Read firmware file successfully .");
uint8_t *firmware = (uint8_t *)malloc(fw_size);
if (!firmware) {
Serial.println("malloc memory failed!");
while (1);
}
firmware_file.readBytes(firmware, fw_size);
firmware_file.close();
/***************************************
* BHI260 Initializing
***************************************/
Serial.println("Initializing Sensors...");
// Set the reset pin
bhy.setPins(BHI260_RST);
// Force update of the current firmware, regardless of whether it exists.
// After uploading the firmware once, you can change it to false to speed up the startup time.
bool force_update = true;
// true : Write firmware to flash , false : Write to ram
bool write_to_flash = true;
// Set the firmware array address and firmware size
bhy.setFirmware(firmware, fw_size, write_to_flash, force_update);
// Set to load firmware from flash or ram
bhy.setBootFromFlash(write_to_flash);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
// Release the requested memory space
free(firmware);
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
/*
* Enable monitoring.
* sample_rate can only control the rate of the pressure sensor.
* Temperature and humidity will only be updated when there is a change.
* * */
float sample_rate = 1.0; /* Set to 1Hz update frequency */
uint32_t report_latency_ms = 0; /* Report immediately */
bool rlst = false;
rlst = bhy.configure(SensorBHI260AP::TEMPERATURE, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::TEMPERATURE, sample_rate, rlst);
rlst = bhy.configure(SensorBHI260AP::BAROMETER, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::BAROMETER, sample_rate, rlst);
rlst = bhy.configure(SensorBHI260AP::HUMIDITY, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::HUMIDITY, sample_rate, rlst);
// Register BME280 data parse callback function
Serial.println("Register sensor result callback function");
bhy.onResultEvent(SensorBHI260AP::TEMPERATURE, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::HUMIDITY, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::BAROMETER, parse_bme280_sensor_data);
// Register interrupt function
pinMode(BHI260_IRQ, INPUT);
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
delay(50);
}
#else
void setup() {}
void loop() {}
#endif

View File

@ -0,0 +1,295 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_aux_BMM150.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-07-22
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorXYZ accel(SensorBHI260AP::ACCEL_PASSTHROUGH, bhy);
SensorXYZ gyro(SensorBHI260AP::GYRO_PASSTHROUGH, bhy);
SensorXYZ mag(SensorBHI260AP::MAGNETOMETER_PASSTHROUGH, bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
#define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void xyz_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_xyz data;
float scaling_factor = bhy.getScaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
Serial.print(bhy.getSensorName(sensor_id));
Serial.print(" ");
Serial.print("x: ");
Serial.print(data.x * scaling_factor);
Serial.print(", y: ");
Serial.print(data.y * scaling_factor);
Serial.print(", z: ");
Serial.print(data.z * scaling_factor);
Serial.println(";");
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
float sample_rate = 10.0; /* Read out data measured at 10Hz */
uint32_t report_latency_ms = 0; /* 0 = report immediately */
#ifdef USING_DATA_HELPER
// Enable acceleration
accel.enable(sample_rate, report_latency_ms);
// Enable gyroscope
gyro.enable(sample_rate, report_latency_ms);
// Enable magnetometer
mag.enable(sample_rate, report_latency_ms);
#else
// Enable acceleration
bhy.configure(SensorBHI260AP::ACCEL_PASSTHROUGH, sample_rate, report_latency_ms);
// Enable gyroscope
bhy.configure(SensorBHI260AP::GYRO_PASSTHROUGH, sample_rate, report_latency_ms);
// Enable magnetometer
bhy.configure(SensorBHI260AP::MAGNETOMETER_PASSTHROUGH, sample_rate, report_latency_ms);
// Set the acceleration sensor result callback function
bhy.onResultEvent(SensorBHI260AP::ACCEL_PASSTHROUGH, xyz_process_callback);
// Set the gyroscope sensor result callback function
bhy.onResultEvent(SensorBHI260AP::GYRO_PASSTHROUGH, xyz_process_callback);
// Set the magnetometer sensor result callback function
bhy.onResultEvent(SensorBHI260AP::MAGNETOMETER_PASSTHROUGH, xyz_process_callback);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (accel.hasUpdated() && gyro.hasUpdated() && mag.hasUpdated()) {
uint32_t s;
uint32_t ns;
accel.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] AX:%+7.2f AY:%+7.2f AZ:%+7.2f GX:%+7.2f GY:%+7.2f GZ:%+7.2f MX:%+7.2f MY:%+7.2f MZ:%+7.2f\n",
s, ns, accel.getX(), accel.getY(), accel.getZ(),
gyro.getX(), gyro.getY(), gyro.getZ(),
mag.getX(), mag.getY(), mag.getZ());
#else
Serial.print("[T: "); Serial.print(s);
Serial.print("."); Serial.print(ns); Serial.print("] ");
Serial.print("AX:"); Serial.print(accel.getX(), 2);
Serial.print(" AY:"); Serial.print(accel.getY(), 2);
Serial.print(" AZ:"); Serial.print(accel.getZ(), 2);
Serial.print(" GX:"); Serial.print(gyro.getX(), 2);
Serial.print(" GY:"); Serial.print(gyro.getY(), 2);
Serial.print(" GZ:"); Serial.print(gyro.getZ(), 2);
Serial.print(" MX:"); Serial.print(mag.getX(), 2);
Serial.print(" MY:"); Serial.print(mag.getY(), 2);
Serial.print(" MZ:"); Serial.print(mag.getZ(), 2);
Serial.println();
#endif
}
#endif
delay(50);
}

View File

@ -0,0 +1,356 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_aux_BMM150_BME280.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-07-24
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorTemperature temperature(bhy);
SensorHumidity humidity(bhy);
SensorPressure pressure(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
#define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void parse_bme280_sensor_data(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
float humidity = 0;
float temperature = 0;
float pressure = 0;
switch (sensor_id) {
case SensorBHI260AP::HUMIDITY:
bhy2_parse_humidity(data_ptr, &humidity);
Serial.print("humidity:"); Serial.print(humidity); Serial.println("%");
break;
case SensorBHI260AP::TEMPERATURE:
bhy2_parse_temperature_celsius(data_ptr, &temperature);
Serial.print("temperature:"); Serial.print(temperature); Serial.println("*C");
break;
case SensorBHI260AP::BAROMETER:
bhy2_parse_pressure(data_ptr, &pressure);
Serial.print("pressure:"); Serial.print(pressure); Serial.println("Pa");
break;
default:
Serial.println("Unkown.");
break;
}
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void printResult(uint8_t sensor_id, float sample_rate, bool rlst)
{
const char *sensorName = bhy.getSensorName(sensor_id);
Serial.print("Configure ");
Serial.print(sensorName);
Serial.print(" sensor ");
Serial.print(sample_rate, 2);
Serial.print(" HZ ");
if (rlst) {
Serial.print("successfully");
} else {
Serial.print("failed");
}
Serial.println();
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
/*
* Enable monitoring.
* sample_rate can only control the rate of the pressure sensor.
* Temperature and humidity will only be updated when there is a change.
* * */
float sample_rate = 2.0; /* Set pressure sensor to 2Hz update frequency */
uint32_t report_latency_ms = 0; /* Report immediately */
/*
* Enable BME280 function
* Function depends on BME280.
* If the hardware is not connected to BME280, the function cannot be used.
* * */
#ifdef USING_DATA_HELPER
temperature.enable();
humidity.enable();
pressure.enable(sample_rate, report_latency_ms);
#else
bool rlst = false;
rlst = bhy.configure(SensorBHI260AP::TEMPERATURE, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::TEMPERATURE, sample_rate, rlst);
rlst = bhy.configure(SensorBHI260AP::BAROMETER, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::BAROMETER, sample_rate, rlst);
rlst = bhy.configure(SensorBHI260AP::HUMIDITY, sample_rate, report_latency_ms);
printResult(SensorBHI260AP::HUMIDITY, sample_rate, rlst);
// Register BME280 data parse callback function
Serial.println("Register sensor result callback function");
bhy.onResultEvent(SensorBHI260AP::TEMPERATURE, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::HUMIDITY, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::BAROMETER, parse_bme280_sensor_data);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
uint32_t s;
uint32_t ns;
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (temperature.hasUpdated()) {
temperature.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] ", s, ns);
Serial.printf("Temperature: %.2f *C %.2f *F %.2f K\n",
temperature.getCelsius(), temperature.getFahrenheit(), temperature.getKelvin());
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("]:");
Serial.print("Temperature: ");
Serial.print(temperature.getCelsius()); Serial.print(" *C");
Serial.print(temperature.getFahrenheit()); Serial.print(" *F");
Serial.print(temperature.getKelvin()); Serial.print(" *F");
Serial.println();
#endif
}
if (humidity.hasUpdated()) {
humidity.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] ", s, ns);
Serial.printf("Humidity: %.2f %%\n", humidity.getHumidity());
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("]:");
Serial.print("Humidity: ");
Serial.print(humidity.getHumidity()); Serial.print(" %");
Serial.println();
#endif
}
if (pressure.hasUpdated()) {
pressure.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] ", s, ns);
Serial.printf("Pressure: %.2f Pascal\n", pressure.getPressure());
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("]:");
Serial.print("Humidity: ");
Serial.print(pressure.getPressure()); Serial.print(" Pascal");
Serial.println();
#endif
}
#endif
delay(50);
}

View File

@ -0,0 +1,414 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_aux_BMM150_BME280_Expand_GPIO.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-10-10
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBHI260AP.hpp"
#include <Commander.h> //Deplib https://github.com/CreativeRobotics/Commander
Commander cmd;
void initialiseCommander();
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
#define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
void parse_bme280_sensor_data(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
float humidity = 0;
float temperature = 0;
float pressure = 0;
switch (sensor_id) {
case SensorBHI260AP::HUMIDITY:
bhy2_parse_humidity(data_ptr, &humidity);
Serial.print("humidity:"); Serial.print(humidity); Serial.println("%");
break;
case SensorBHI260AP::TEMPERATURE:
bhy2_parse_temperature_celsius(data_ptr, &temperature);
Serial.print("temperature:"); Serial.print(temperature); Serial.println("*C");
break;
case SensorBHI260AP::BAROMETER:
bhy2_parse_pressure(data_ptr, &pressure);
Serial.print("pressure:"); Serial.print(pressure); Serial.println("hPa");
break;
default:
Serial.println("Unkown.");
break;
}
}
void sensor_event_callback(uint8_t event, uint8_t sensor_id, uint8_t data)
{
Serial.print("Sensor Event:");
const char *sensorName = bhy.getSensorName(sensor_id);
switch (event) {
case BHY2_META_EVENT_SAMPLE_RATE_CHANGED:
Serial.print("Sample rate changed for ");
Serial.print(sensorName);
Serial.println(" sensor");
break;
case BHY2_META_EVENT_POWER_MODE_CHANGED:
Serial.print("Power mode changed for ");
Serial.print(sensorName);
Serial.println(" sensor");
break;
default:
Serial.print("Other event : ");
Serial.println(event);
break;
}
}
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
Serial.println("Initializing Sensors...");
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Register sensor change event callback
bhy.onEvent(sensor_event_callback);
// Register BME280 data parse callback function
bhy.onResultEvent(SensorBHI260AP::TEMPERATURE, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::HUMIDITY, parse_bme280_sensor_data);
bhy.onResultEvent(SensorBHI260AP::BAROMETER, parse_bme280_sensor_data);
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
initialiseCommander();
Serial.println("Hello: Type 'help' to get help");
cmd.printCommandPrompt();
// Register interrupt function
pinMode(BHI260_IRQ, INPUT);
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
//Call the update functions using the activeCommander pointer
cmd.update();
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
}
//All commands for 'master'
//COMMAND ARRAY ------------------------------------------------------------------------------
const commandList_t masterCommands[] = {
{"help", helpHandler, "help"},
{"set gpio", setGpioLevel, "set gpio level"},
{"get gpio", getGpioLevel, "get gpio level"},
{"dis gpio", disGpioMode, "disable gpio"},
{"temperature", setTemperature, "Temperature"},
{"humidity", setHumidity, "Humidity"},
{"pressure", setPressure, "Pressure"},
};
void initialiseCommander()
{
cmd.begin(&Serial, masterCommands, sizeof(masterCommands));
cmd.commandPrompt(ON); //enable the command prompt
cmd.echo(true); //Echo incoming characters to theoutput port
cmd.errorMessages(ON); //error messages are enabled - it will tell us if we issue any unrecognised commands
//Error messaged do NOT work for quick set and get commands
}
bool helpHandler(Commander &Cmdr)
{
Serial.println("Help:");
Serial.println("\tCustom firmware valid gpio : 1, 5, 6, 14, 15, 16, 19, 20");
Serial.println("\tset gpio [gpio num] [level]");
Serial.println("\tget gpio [gpio num] [pullup]");
Serial.println("\tdis gpio [gpio num]");
Serial.println("\ttemperature [on/off] : range 0 ~ 1");
Serial.println("\thumidity [on/off] : range 0 ~ 1");
Serial.println("\tpressure [sample_rate/HZ] : range 0~1000");
return 0;
}
bool setTemperature(Commander &Cmdr)
{
float sample_rate;
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
Cmdr.getFloat(sample_rate);
bhy.configure(SensorBHI260AP::TEMPERATURE, sample_rate, 0);
return 0;
}
bool setHumidity(Commander &Cmdr)
{
float sample_rate;
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
Cmdr.getFloat(sample_rate);
bhy.configure(SensorBHI260AP::HUMIDITY, sample_rate, 0);
return 0;
}
bool setPressure(Commander &Cmdr)
{
float sample_rate;
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
Cmdr.getFloat(sample_rate);
bhy.configure(SensorBHI260AP::BAROMETER, sample_rate, 0);
return 0;
}
/*
* GPIO Comparison Table
* M1SCX = N.A ! INVALID PIN
* M1SDX = N.A ! INVALID PIN
* M1SDI = N.A ! INVALID PIN
* M2SCX = 14 ! OK
* M2SDX = 15 ! OK
* M2SDI = 16 ! OK
* MCSB1 = 1 ! OK
* MCSB2 = 4 ! aux BMM150
* M3SCL = 17 ! aux BMM150
* M3SDA = 18 ! aux BMM150
* MCSB3 = 5 ! OK
* MCSB4 = 6 ! OK
* JTAG_CLK = 19 ! OK
* JTAG_DIO = 20 ! OK
* RESV1 = 2 ! INVALID PIN
* RESV2 = 3 ! INVALID PIN
* RESV3 = N.A ! INVALID PIN
* */
bool setGpioLevel(Commander &Cmdr)
{
int values[2] = {0, 0};
int items = Cmdr.countItems();
if (items < 2) {
return false;
}
for (int n = 0; n < 2; n++) {
Cmdr.getInt(values[n]);
}
uint8_t pin = values[0];
uint8_t level = values[1];
bhy.digitalWrite(pin, level);
return 0;
}
bool getGpioLevel(Commander &Cmdr)
{
int values[2] = {0, 0};
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
if (items > 2 )items = 2;
for (int n = 0; n < items; n++) {
Cmdr.getInt(values[n]);
}
bool pullup = false;
uint8_t pin = values[0];
if (items == 2 ) {
pullup = values[1];
}
uint8_t level = bhy.digitalRead(pin, pullup);
Serial.print("Get GPIO : "); Serial.print(pin);
Serial.print(" level is "); Serial.println(level);
return 0;
}
bool disGpioMode(Commander &Cmdr)
{
int values[1] = {0};
int items = Cmdr.countItems();
if (items < 1) {
return 0;
}
Cmdr.getInt(values[0]);
uint8_t pin = values[0];
bhy.disableGpio(pin);
return 0;
}

View File

@ -0,0 +1,282 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_aux_BMM150_euler.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-07-23
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorEuler euler(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
#define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void parse_euler(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_orientation data;
uint32_t s, ns;
uint64_t tns;
// Function to parse FIFO frame data into orientation
bhy2_parse_orientation(data_ptr, &data);
uint64_t _timestamp = *timestamp;
time_to_s_ns(_timestamp, &s, &ns, &tns);
uint8_t accuracy = bhy.getAccuracy();
if (accuracy) {
Serial.print("SID:"); Serial.print(sensor_id);
Serial.print(" T:"); Serial.print(s);
Serial.print("."); Serial.print(ns);
Serial.print(" x:"); Serial.print(data.heading * 360.0f / 32768.0f);
Serial.print(" y:"); Serial.print(data.pitch * 360.0f / 32768.0f);
Serial.print(" x:"); Serial.print(data.roll * 360.0f / 32768.0f);
Serial.print(" acc:"); Serial.println(accuracy);
} else {
Serial.print("SID:"); Serial.print(sensor_id);
Serial.print(" T:"); Serial.print(s);
Serial.print("."); Serial.print(ns);
Serial.print(" x:"); Serial.print(data.heading * 360.0f / 32768.0f);
Serial.print(" y:"); Serial.print(data.pitch * 360.0f / 32768.0f);
Serial.print(" x:"); Serial.println(data.roll * 360.0f / 32768.0f);
}
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
float sample_rate = 100.0; /* Read out data measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
/*
* Enable Euler function
* The Euler function depends on BMM150.
* If the hardware is not connected to BMM150, the Euler function cannot be used.
* * */
#ifdef USING_DATA_HELPER
euler.enable(sample_rate, report_latency_ms);
#else
bhy.configure(SensorBHI260AP::ORIENTATION_WAKE_UP, sample_rate, report_latency_ms);
// Register event callback function
bhy.onResultEvent(SensorBHI260AP::ORIENTATION_WAKE_UP, parse_euler);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (euler.hasUpdated()) {
// Print the roll angle to the serial monitor.
Serial.print(euler.getRoll());
// Print a comma as a separator between the roll and pitch angles.
Serial.print(",");
// Print the pitch angle to the serial monitor.
Serial.print(euler.getPitch());
// Print a comma as a separator between the pitch and yaw angles.
Serial.print(",");
// Print the yaw angle to the serial monitor and start a new line.
Serial.println(euler.getHeading());
}
#endif
delay(50);
}

View File

@ -0,0 +1,284 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260AP_aux_BMM150_quaternion.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-07-23
* @note Changed from Boschsensortec API https://github.com/boschsensortec/BHY2_SensorAPI
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorBHI260AP.hpp>
#include <bosch/BoschSensorDataHelper.hpp>
// #define USE_I2C_INTERFACE true
// #define USE_SPI_INTERFACE true
#if !defined(USE_I2C_INTERFACE) && !defined(USE_SPI_INTERFACE)
#define USE_I2C_INTERFACE
#warning "No interface type is selected, use I2C interface"
#endif
#if defined(USE_SPI_INTERFACE)
#ifndef SPI_MOSI
#define SPI_MOSI 33
#endif
#ifndef SPI_MISO
#define SPI_MISO 34
#endif
#ifndef SPI_SCK
#define SPI_SCK 35
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 37
#endif
#ifndef BHI260_CS
#define BHI260_CS 36
#endif
#else //* I2C */
#ifndef BHI260_SDA
#define BHI260_SDA 2
#endif
#ifndef BHI260_SCL
#define BHI260_SCL 3
#endif
#ifndef BHI260_IRQ
#define BHI260_IRQ 8
#endif
#endif /*USE_SPI_INTERFACE*/
#ifndef BHI260_RST
#define BHI260_RST -1
#endif
SensorBHI260AP bhy;
/*
* Define the USING_DATA_HELPER use of data assistants.
* No callback function will be used. Data can be obtained directly through
* the data assistant. Note that this method is not a thread-safe function.
* Please pay attention to protecting data access security.
* */
#define USING_DATA_HELPER
#ifdef USING_DATA_HELPER
SensorQuaternion quaternion(bhy);
#endif
// The firmware runs in RAM and will be lost if the power is off. The firmware will be loaded from RAM each time it is run.
// #define BOSCH_APP30_SHUTTLE_BHI260_FW
#define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO
// #define BOSCH_BHI260_AUX_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO
// #define BOSCH_BHI260_AUX_BMM150_GPIO
// #define BOSCH_BHI260_GPIO
// Firmware is stored in flash and booted from flash,Depends on BHI260 hardware connected to SPI Flash
// #define BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_FLASH
// #define BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH
// #define BOSCH_BHI260_AUX_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_FLASH
// #define BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH
// #define BOSCH_BHI260_AUX_BMM150_GPIO_FLASH
// #define BOSCH_BHI260_GPIO_FLASH
#include <BoschFirmware.h>
// Force update of current firmware, whether it exists or not.
// Only works when external SPI Flash is connected to BHI260.
// After uploading firmware once, you can change this to false to speed up boot time.
bool force_update_flash_firmware = true;
bool isReadyFlag = false;
void dataReadyISR()
{
isReadyFlag = true;
}
#ifndef USING_DATA_HELPER
void parse_quaternion(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_quaternion data;
uint32_t s, ns;
uint64_t tns;
// Function to parse FIFO frame data into orientation
bhy2_parse_quaternion(data_ptr, &data);
uint64_t _timestamp = *timestamp;
time_to_s_ns(_timestamp, &s, &ns, &tns);
Serial.print("SID:"); Serial.print(sensor_id);
Serial.print(" T:"); Serial.print(s);
Serial.print("."); Serial.print(ns);
Serial.print(" x:"); Serial.print(data.x / 16384.0f);
Serial.print(" y:"); Serial.print(data.y / 16384.0f);
Serial.print(" x:"); Serial.print(data.z / 16384.0f);
Serial.print(" w:"); Serial.print(data.w / 16384.0f);
Serial.print(" acc:"); Serial.println(((data.accuracy * 180.0f) / 16384.0f) / 3.141592653589793f);
}
#endif
// Firmware update progress callback
void progress_callback(void *user_data, uint32_t total, uint32_t transferred)
{
float progress = (float)transferred / total * 100;
Serial.print("Upload progress: ");
Serial.print(progress);
Serial.println("%");
}
void setup()
{
Serial.begin(115200);
while (!Serial);
// Set the reset pin
bhy.setPins(BHI260_RST);
Serial.println("Initializing Sensors...");
// Set the firmware array address and firmware size
bhy.setFirmware(bosch_firmware_image, bosch_firmware_size, bosch_firmware_type, force_update_flash_firmware);
// Set the firmware update processing progress callback function
// bhy.setUpdateProcessCallback(progress_callback, NULL);
// Set the maximum transfer bytes of I2C/SPI,The default size is I2C 32 bytes, SPI 256 bytes.
// bhy.setMaxiTransferSize(256);
// Set the processing fifo data buffer size,The default size is 512 bytes.
// bhy.setProcessBufferSize(1024);
// Set to load firmware from flash
bhy.setBootFromFlash(bosch_firmware_type);
#ifdef USE_I2C_INTERFACE
// Using I2C interface
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
if (!bhy.begin(Wire, BHI260AP_SLAVE_ADDRESS_L, BHI260_SDA, BHI260_SCL)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
#ifdef USE_SPI_INTERFACE
// Using SPI interface
if (!bhy.begin(SPI, BHI260_CS, SPI_MOSI, SPI_MISO, SPI_SCK)) {
Serial.print("Failed to initialize sensor - error code:");
Serial.println(bhy.getError());
while (1) {
delay(1000);
}
}
#endif
Serial.println("Initializing the sensor successfully!");
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
#ifdef PLATFORM_HAS_PRINTF
info.printInfo(Serial);
#else
info.printInfo();
#endif
float sample_rate = 100.0; /* Read out data measured at 100Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
/*
* Enable Quaternion function
* The Quaternion function depends on BMM150.
* If the hardware is not connected to BMM150, the Quaternion function cannot be used.
* * */
#ifdef USING_DATA_HELPER
quaternion.enable(sample_rate, report_latency_ms);
#else
bhy.configure(SensorBHI260AP::ROTATION_VECTOR, sample_rate, report_latency_ms);
// Register event callback function
bhy.onResultEvent(SensorBHI260AP::ROTATION_VECTOR, parse_quaternion);
#endif
// Set the specified pin (BHI260_IRQ) as an input pin.
pinMode(BHI260_IRQ, INPUT);
// Attach an interrupt service routine (ISR) 'dataReadyISR' to the specified pin (BHI260_IRQ).
attachInterrupt(BHI260_IRQ, dataReadyISR, RISING);
}
void loop()
{
// Update sensor fifo
if (isReadyFlag) {
isReadyFlag = false;
bhy.update();
}
#ifdef USING_DATA_HELPER
if (quaternion.hasUpdated()) {
uint32_t s;
uint32_t ns;
quaternion.getLastTime(s, ns);
#ifdef PLATFORM_HAS_PRINTF
Serial.printf("[T: %" PRIu32 ".%09" PRIu32 "] QX:%+7.2f QY:%+7.2f QZ:%+7.2f QW:%+7.2f\n",
s, ns, quaternion.getX(), quaternion.getY(), quaternion.getZ(), quaternion.getW());
#else
Serial.print("[T: ");
Serial.print(s);
Serial.print(".");
Serial.print(ns);
Serial.print("] ");
Serial.print("QX:");
Serial.print(quaternion.getX(), 2);
Serial.print(" QY:");
Serial.print(quaternion.getY(), 2);
Serial.print(" QZ:");
Serial.print(quaternion.getZ(), 2);
Serial.print(" QW:");
Serial.print(quaternion.getW(), 2);
Serial.println();
#endif
}
#endif
delay(50);
}

View File

@ -0,0 +1,92 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423_Accelerometer.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
uint32_t intervalue;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
/*
* BMA423_I2C_ADDR_PRIMARY = 0x18
* BMA423_I2C_ADDR_SECONDARY = 0x19
* * */
if (!accel.begin(Wire, BMA423_I2C_ADDR_SECONDARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
}
void loop()
{
int16_t x = 0, y = 0, z = 0;
accel.getAccelerometer(x, y, z);
Serial.print("X:");
Serial.print(x); Serial.print(" ");
Serial.print("Y:");
Serial.print(y); Serial.print(" ");
Serial.print("Z:");
Serial.print(z);
Serial.println();
delay(50);
}

View File

@ -0,0 +1,145 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423_Feature.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
uint32_t intervalue;
bool sensorIRQ = false;
void setFlag()
{
sensorIRQ = true;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
attachInterrupt(SENSOR_IRQ, setFlag, RISING);
/*
* BMA423_I2C_ADDR_PRIMARY = 0x18
* BMA423_I2C_ADDR_SECONDARY = 0x19
* * */
if (!accel.begin(Wire, BMA423_I2C_ADDR_SECONDARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
// Enable acceleration sensor
accel.enableAccelerometer();
// Enable pedometer steps
accel.enablePedometer();
// Emptying the pedometer steps
accel.resetPedometer();
// Enable sensor features
accel.enableFeature(SensorBMA423::FEATURE_STEP_CNTR |
SensorBMA423::FEATURE_ANY_MOTION |
SensorBMA423::FEATURE_ACTIVITY |
SensorBMA423::FEATURE_TILT |
SensorBMA423::FEATURE_WAKEUP,
true);
// Pedometer interrupt enable
accel.enablePedometerIRQ();
// Tilt interrupt enable
accel.enableTiltIRQ();
// DoubleTap interrupt enable
accel.enableWakeupIRQ();
// Any motion / no motion interrupt enable
accel.enableAnyNoMotionIRQ();
// Activity interruption enable
accel.enableActivityIRQ();
// Chip interrupt function enable
accel.configInterrupt();
}
void loop()
{
if (sensorIRQ) {
sensorIRQ = false;
// The interrupt status must be read after an interrupt is detected
uint16_t status = accel.readIrqStatus();
Serial.print("Accelerometer interrupt mask : 0x");
Serial.println(status, HEX);
if (accel.isPedometer()) {
uint32_t stepCounter = accel.getPedometerCounter();
Serial.print("Step count interrupt,step Counter:");
Serial.println(stepCounter);
}
if (accel.isActivity()) {
Serial.println("Activity interrupt");
}
if (accel.isTilt()) {
Serial.println("Tilt interrupt");
}
if (accel.isDoubleTap()) {
Serial.println("DoubleTap interrupt");
}
if (accel.isAnyNoMotion()) {
Serial.println("Any motion / no motion interrupt");
}
}
delay(50);
}

View File

@ -0,0 +1,147 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423_Orientation.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
char report[256];
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
/*
* BMA423_I2C_ADDR_PRIMARY = 0x18
* BMA423_I2C_ADDR_SECONDARY = 0x19
* * */
if (!accel.begin(Wire, BMA423_I2C_ADDR_SECONDARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
Serial.println("Output ...");
}
void loop()
{
uint8_t direction = accel.direction();
switch (direction) {
case SensorBMA423::DIRECTION_BOTTOM_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_TOP_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_TOP_LEFT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | * | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_BOTTOM_RIGHT:
sprintf( report, "\r\n ________________ " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | | " \
"\r\n | * | " \
"\r\n |________________| \r\n" );
break;
case SensorBMA423::DIRECTION_BOTTOM:
sprintf( report, "\r\n ________________ " \
"\r\n |________________| " \
"\r\n * \r\n" );
break;
case SensorBMA423::DIRECTION_TOP:
sprintf( report, "\r\n __*_____________ " \
"\r\n |________________| \r\n" );
break;
default:
sprintf( report, "None of the 3D orientation axes is set in BMA423 - accelerometer.\r\n" );
break;
}
Serial.println(direction);
Serial.println(report);
delay(1000);
}

View File

@ -0,0 +1,84 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423_Temperature.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 39
#endif
SensorBMA423 accel;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT);
Serial.println("BMA423 Sensor Temperature");
/*
* BMA423_I2C_ADDR_PRIMARY = 0x18
* BMA423_I2C_ADDR_SECONDARY = 0x19
* * */
if (!accel.begin(Wire, BMA423_I2C_ADDR_SECONDARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BAM423 Sensor success!");
}
void loop()
{
Serial.print("getTemperature:");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_DEG));
Serial.print("*C ");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_FAHRENHEIT));
Serial.print("*F");
Serial.println();
delay(1000);
}

View File

@ -0,0 +1,102 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMM150_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-10
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorBMM150.hpp"
#include "SensorWireHelper.h"
#ifndef SENSOR_SDA
#define SENSOR_SDA 33
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 35
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ -1
#endif
#ifndef SENSOR_RST
#define SENSOR_RST -1
#endif
SensorBMM150 bmm;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Using I2C interface
if (!bmm.begin(Wire, BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW, SENSOR_SDA, SENSOR_SCL)) {
Serial.print("Failed to init BMM150 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BMM150 Sensor success!");
/* Set magnetometer run mode */
/**
* * POWERMODE_NORMAL,
* * POWERMODE_FORCED,
* * POWERMODE_SLEEP,
* * POWERMODE_SUSPEND,
*/
bmm.setMode(SensorBMM150::POWERMODE_NORMAL);
}
void loop()
{
int16_t x, y, z;
/* Read mag data */
/* Unit for magnetometer data is micro tesla(uT) */
if (bmm.getMag(x, y, z)) {
Serial.print("X:");
Serial.print(x);
Serial.print("uT,");
Serial.print("Y:");
Serial.print(y);
Serial.print("uT,");
Serial.print("Z:");
Serial.print(z);
Serial.println("uT");
}
delay(50);
}

View File

@ -0,0 +1,260 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BQ27220_GaugeExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-13
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <GaugeBQ27220.hpp>
#ifndef SENSOR_SDA
#define SENSOR_SDA 2
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 3
#endif
GaugeBQ27220 gauge;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!gauge.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to BQ27220 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init BQ27220 Sensor success!");
/**
* @brief Set the new design capacity and full charge capacity of the battery.
*
* This function is responsible for updating the design capacity and full charge capacity of the battery.
* It first checks the device's access settings, enters the configuration update mode, writes the new capacity values
* and checksums, and finally exits the configuration update mode. If the device was previously in a sealed state,
* it will be restored to the sealed mode after the operation is completed.
* For new devices, use the default key for access. If it is an encrypted device, use setAccessKey(uint32_t key) to set the key.
* @param newDesignCapacity The new design capacity to be set, of type uint16_t.
* @param newFullChargeCapacity The new full charge capacity to be set, of type uint16_t.
* @return bool Returns true if the setting is successful, false otherwise.
*/
// uint32_t key = 0x12345678;
// gauge.setAccessKey(key)
uint16_t newDesignCapacity = 3500;
uint16_t newFullChargeCapacity = 3500;
gauge.setNewCapacity(newDesignCapacity, newFullChargeCapacity);
OperationConfig config = gauge.getOperationConfig();
//* OperationConfig A *//
Serial.print("OperationConfigA Values:0x");
Serial.println(config.getConfigA(), HEX);
Serial.print("External Thermistor Selected: ");
Serial.println(config.isTempsSet() ? "YES" : "NO");
Serial.print("BATT_GD Pin Polarity High: ");
Serial.println(config.isBatgPolHigh() ? "YES" : "NO");
Serial.print("BATT_GD Function Enabled: ");
Serial.println(config.isBatgEnEnabled() ? "YES" : "NO");
Serial.print("Can Enter SLEEP State: ");
Serial.println(config.canEnterSleep() ? "YES" : "NO");
Serial.print("slpwakechg Function Enabled: ");
Serial.println(config.isSlpwakechgEnabled() ? "YES" : "NO");
Serial.print("Write Temperature Function Enabled: ");
Serial.println(config.isWrtempEnabled() ? "YES" : "NO");
Serial.print("Battery Insertion Detection Enabled: ");
Serial.println(config.isBienableEnabled() ? "YES" : "NO");
Serial.print("Battery Insertion Pin Pull - Up Enabled: ");
Serial.println(config.isBlPupEnEnabled() ? "YES" : "NO");
Serial.print("Pin Function Code (PFC) Mode: ");
Serial.println(config.getPfcCfg());
Serial.print("Wake - Up Function Enabled: ");
Serial.println(config.isWakeEnEnabled() ? "YES" : "NO");
Serial.print("Wake - Up Threshold 1: ");
Serial.println(config.getWkTh1());
Serial.print("Wake - Up Threshold 0: ");
Serial.println(config.getWkTh0());
//* OperationConfig B *//
Serial.print("\nOperationConfigB Values:0x");
Serial.println(config.getConfigB(), HEX);
Serial.print("Default Seal Option Enabled: ");
Serial.println(config.isDefaultSealEnabled() ? "YES" : "NO");
Serial.print("Non - Removable Option Set: ");
Serial.println(config.isNonRemovableSet() ? "YES" : "NO");
Serial.print("INT_BREM Function Enabled: ");
Serial.println(config.isIntBremEnabled() ? "YES" : "NO");
Serial.print("INT_BATL Function Enabled: ");
Serial.println(config.isIntBatLEnabled() ? "YES" : "NO");
Serial.print("INT_STATE Function Enabled: ");
Serial.println(config.isIntStateEnabled() ? "YES" : "NO");
Serial.print("INT_OCV Function Enabled: ");
Serial.println(config.isIntOcvEnabled() ? "YES" : "NO");
Serial.print("INT_OT Function Enabled: ");
Serial.println(config.isIntOtEnabled() ? "YES" : "NO");
Serial.print("INT_POL Function Enabled (High - Level Polarity): ");
Serial.println(config.isIntPolHigh() ? "YES" : "NO");
Serial.print("INT_FOCV Function Enabled: ");
Serial.println(config.isIntFocvEnabled() ? "YES" : "NO");
delay(10000);
}
void loop()
{
uint32_t startMeasTime = millis();
if (gauge.refresh()) {
uint32_t endMesTime = millis();
Serial.print("Polling time: "); Serial.print(endMesTime - startMeasTime); Serial.println(" ms");
Serial.println("\nStandard query:");
Serial.print("\t- AtRate:"); Serial.print(gauge.getAtRate()); Serial.println(" mA");
Serial.print("\t- AtRateTimeToEmpty:"); Serial.print(gauge.getAtRateTimeToEmpty()); Serial.println(" minutes");
Serial.print("\t- Temperature:"); Serial.print(gauge.getTemperature() ); Serial.println("");
Serial.print("\t- BatteryVoltage:"); Serial.print(gauge.getVoltage()); Serial.println(" mV");
Serial.print("\t- InstantaneousCurrent:"); Serial.print(gauge.getCurrent()); Serial.println(" mAh");
Serial.print("\t- RemainingCapacity:"); Serial.print(gauge.getRemainingCapacity()); Serial.println(" mAh");
Serial.print("\t- FullChargeCapacity:"); Serial.print(gauge.getFullChargeCapacity()); Serial.println(" mAh");
Serial.print("\t- DesignCapacity:"); Serial.print(gauge.getDesignCapacity()); Serial.println(" mAh");
Serial.print("\t- TimeToEmpty:"); Serial.print(gauge.getTimeToEmpty()); Serial.println(" minutes");
Serial.print("\t- TimeToFull:"); Serial.print(gauge.getTimeToFull()); Serial.println(" minutes");
Serial.print("\t- StandbyCurrent:"); Serial.print(gauge.getStandbyCurrent()); Serial.println(" mA");
Serial.print("\t- StandbyTimeToEmpty:"); Serial.print(gauge.getStandbyTimeToEmpty()); Serial.println(" minutes");
Serial.print("\t- MaxLoadCurrent:"); Serial.print(gauge.getMaxLoadCurrent()); Serial.println(" mA");
Serial.print("\t- MaxLoadTimeToEmpty:"); Serial.print(gauge.getMaxLoadTimeToEmpty()); Serial.println(" minute");
Serial.print("\t- RawCoulombCount:"); Serial.print(gauge.getRawCoulombCount()); Serial.println(" mAh");
Serial.print("\t- AveragePower:"); Serial.print(gauge.getAveragePower()); Serial.println(" mW");
Serial.print("\t- InternalTemperature:"); Serial.print(gauge.getInternalTemperature()); Serial.println("");
Serial.print("\t- CycleCount:"); Serial.println(gauge.getCycleCount());
Serial.print("\t- StateOfCharge:"); Serial.print(gauge.getStateOfCharge()); Serial.println(" %");
Serial.print("\t- StateOfHealth:"); Serial.print(gauge.getStateOfHealth()); Serial.println(" %");
Serial.print("\t- RequestChargingVoltage:"); Serial.print(gauge.getRequestChargingVoltage()); Serial.println(" mV");
Serial.print("\t- RequestChargingCurrent:"); Serial.print(gauge.getRequestChargingCurrent()); Serial.println(" mA");
Serial.print("\t- BTPDischargeSet:"); Serial.print(gauge.getBTPDischargeSet()); Serial.println(" mAh");
Serial.print("\t- BTPChargeSet:"); Serial.print(gauge.getBTPChargeSet()); Serial.println(" mAh");
FuelGaugeOperationStatus status = gauge.getOperationStatus();
BatteryStatus batteryStatus = gauge.getBatteryStatus();
Serial.println("\nOperation Status:");
Serial.print("\t- getIsConfigUpdateMode:"); Serial.println(status.getIsConfigUpdateMode() ? "YES" : "NO");
Serial.print("\t- getIsBtpThresholdExceeded:"); Serial.println(status.getIsBtpThresholdExceeded() ? "YES" : "NO");
Serial.print("\t- getIsCapacityAccumulationThrottled:"); Serial.println(status.getIsCapacityAccumulationThrottled() ? "YES" : "NO");
Serial.print("\t- getIsInitializationComplete:"); Serial.println(status.getIsInitializationComplete() ? "YES" : "NO");
Serial.print("\t- getIsDischargeCycleCompliant:"); Serial.println(status.getIsDischargeCycleCompliant() ? "YES" : "NO");
Serial.print("\t- getIsBatteryVoltageBelowEdv2:"); Serial.println(status.getIsBatteryVoltageBelowEdv2() ? "YES" : "NO");
Serial.print("\t- getSecurityAccessLevel:"); Serial.println(status.getSecurityAccessLevel());
Serial.print("\t- getIsCalibrationModeEnabled:"); Serial.println(status.getIsCalibrationModeEnabled() ? "YES" : "NO");
Serial.println("\nBattery Status:");
if (batteryStatus.isFullDischargeDetected()) {
Serial.println("\t- Full discharge detected.");
}
if (batteryStatus.isOcvMeasurementUpdateComplete()) {
Serial.println("\t- OCV measurement update is complete.");
}
if (batteryStatus.isOcvReadFailedDueToCurrent()) {
Serial.println("\t- Status bit indicating that an OCV read failed due to current.");
Serial.println("\tThis bit can only be set if a battery is present after receiving an OCV_CMD().");
}
if (batteryStatus.isInSleepMode()) {
Serial.println("\t- The device operates in SLEEP mode");
}
if (batteryStatus.isOverTemperatureDuringCharging()) {
Serial.println("\t- Over-temperature is detected during charging.");
}
if (batteryStatus.isOverTemperatureDuringDischarge()) {
Serial.println("\t- Over-temperature detected during discharge condition.");
}
if (batteryStatus.isFullChargeDetected()) {
Serial.println("\t- Full charge detected.");
}
if (batteryStatus.isChargeInhibited()) {
Serial.println("\t- Charge Inhibit: If set, indicates that charging should not begin because the Temperature() is outside the range");
Serial.println("\t[Charge Inhibit Temp Low, Charge Inhibit Temp High]. ");
}
if (batteryStatus.isChargingTerminationAlarm()) {
Serial.println("\t- Termination of charging alarm. This flag is set and cleared based on the selected SOC Flag Config A option.");
}
if (batteryStatus.isGoodOcvMeasurement()) {
Serial.println("\t- A good OCV measurement was made.");
}
if (batteryStatus.isBatteryInserted()) {
Serial.println("\t- Detects inserted battery.");
}
if (batteryStatus.isBatteryPresent()) {
Serial.println("\t- Battery presence detected.");
}
if (batteryStatus.isDischargeTerminationAlarm()) {
Serial.println("\t- Termination discharge alarm. This flag is set and cleared according to the selected SOC Flag Config A option.");
}
if (batteryStatus.isSystemShutdownRequired()) {
Serial.println("\t- System shutdown bit indicating that the system should be shut down. True when set. If set, the SOC_INT pin toggles once.");
}
if (batteryStatus.isInDischargeMode()) {
Serial.println("\t- When set, the device is in DISCHARGE mode; when cleared, the device is in CHARGING or RELAXATION mode.");
}
Serial.println("===============================================");
}
delay(3000);
}

View File

@ -0,0 +1,98 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CM32181_LightSensor.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorCM32181.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 39
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 40
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
SensorCM32181 light;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!light.begin(Wire, CM32181_ADDR_PRIMARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find CM32181 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init CM32181 Sensor success!");
int id = light.getChipID();
Serial.print("CM32181 ID = "); Serial.println(id);
/*
Sensitivity mode selection
SAMPLING_X1
SAMPLING_X2
SAMPLING_X1_8
SAMPLING_X1_4
*/
light.setSampling(SensorCM32181::SAMPLING_X2);
//Power On sensor
light.powerOn();
}
void loop()
{
// Get raw data
uint16_t raw = light.getRaw();
// Get conversion data , The manual does not provide information on how to obtain the
// calibration value, now use the calibration value 0.28 provided by the manual
float lux = light.getLux();
Serial.print(" RAW:"); Serial.print(raw);
Serial.print(" Lux:"); Serial.println(lux);
delay(500);
}

View File

@ -0,0 +1,158 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CM32181_LightSensorInterrupt.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-13
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorCM32181.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 39
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 40
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 1
#endif
SensorCM32181 light;
#ifdef ARDUINO_T_AMOLED_147
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
XPowersAXP2101 power;
#endif
void beginPower()
{
// T_AMOLED_147 The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_AMOLED_147)
bool ret = power.begin(Wire, AXP2101_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL);
if (!ret) {
Serial.println("PMU NOT FOUND!\n");
}
power.setALDO1Voltage(1800); power.enableALDO1();
power.setALDO3Voltage(3300); power.enableALDO3();
power.setBLDO1Voltage(1800); power.enableBLDO1();
#endif
}
#include "SensorWireHelper.h"
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
SensorWireHelper::dumpDevices(Wire);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!light.begin(Wire, CM32181_ADDR_PRIMARY, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find CM32181 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init CM32181 Sensor success!");
int id = light.getChipID();
Serial.print("CM32181 ID = "); Serial.println(id);
/*
Sensitivity mode selection
SAMPLING_X1
SAMPLING_X2
SAMPLING_X1_8
SAMPLING_X1_4
*/
light.setSampling(SensorCM32181::SAMPLING_X2,
SensorCM32181::INTEGRATION_TIME_400MS
);
// Set high and low thresholds. If the threshold is higher or lower than the set threshold, an interrupt will be triggered.
uint16_t lowThresholdRaw = 100;
uint16_t highThresholdRaw = 250;
light.setIntThreshold(lowThresholdRaw, highThresholdRaw);
//Power On sensor
light.powerOn();
// Turn on interrupt
light.enableINT();
}
void loop()
{
int pinVal = digitalRead(SENSOR_IRQ) ;
if (pinVal == LOW) {
// After triggering the interrupt, the interrupt status must be read
SensorCM32181::InterruptEvent event = light.getIrqStatus();
// Turn off interrupts
light.disableINT();
// Get Status
switch (event) {
case SensorCM32181::ALS_EVENT_LOW_TRIGGER:
Serial.println("Low interrupt event");
break;
case SensorCM32181::ALS_EVENT_HIGH_TRIGGER:
Serial.println("High interrupt event");
break;
default:
Serial.println("This is an impossible place to reach");
break;
}
// Get raw data
uint16_t raw = light.getRaw();
// Get conversion data , The manual does not provide information on how to obtain the
// calibration value, now use the calibration value 0.28 provided by the manual
float lux = light.getLux();
Serial.print(" IRQ:"); Serial.print(pinVal);
Serial.print(" RAW:"); Serial.print(raw);
Serial.print(" Lux:"); Serial.println(lux);
// Turn on interrupts
light.enableINT();
}
delay(800);
}

View File

@ -0,0 +1,297 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CustomCallbackTouchDrvInterface.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-21
* @note CustomCallbackTouchDrvInterface use LilyGo T-RGB,T-RGB has three types of screens, each of which uses different touch driver chips.
* The example demonstrates using the touch interface class and one sketch is suitable for three types of touch chips.
* The example demonstrates using custom callbacks to read touch or sensors. This method is also applicable to other platforms.
* The prerequisite compilation platform must support C++11.
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvFT6X36.hpp"
#include "TouchDrvCSTXXX.hpp"
#include "TouchDrvGT911.hpp"
#include "ExtensionIOXL9555.hpp"
#include "SensorWireHelper.h"
#ifndef TOUCH_SDA
#define TOUCH_SDA 8
#endif
#ifndef TOUCH_SCL
#define TOUCH_SCL 48
#endif
#ifndef TOUCH_IRQ
#define TOUCH_IRQ 1
#endif
#ifndef TOUCH_RST
#define TOUCH_RST 1
#endif
// Use the TouchDrvInterface base class for automatic discovery and use of multi-touch devices
TouchDrvInterface *touchDrv;
// T-RGB uses XL9555 as the reset control of the touch screen
ExtensionIOXL9555 extension;
int16_t x[5], y[5];
ExtensionIOXL9555::ExtensionGPIO tp_reset = ExtensionIOXL9555::IO1;
/**
* @brief i2c_wr_function
* @note I2C communication using custom callbacks
* @param addr: 7-Bit Device Address
* @param reg: Register address, only needs to be written when writeReg is true
* @param *buf: When isWrite is true, it represents the written buf, otherwise it is the read data buffer
* @param len: When isWrite is true, it indicates the length of data written , otherwise it is the data read length
* @param writeReg: writeReg is the register address that needs to be written, otherwise the register address is not written
* @param isWrite: Data write and read direction, true means write, false means read
* @retval True means the device is executed successfully, false means it fails
*/
bool i2c_wr_function(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite)
{
if (isWrite) {
Wire.beginTransmission(addr);
if (writeReg) {
Wire.write(reg);
}
if (buf && len > 0) {
Wire.write(buf, len);
}
return (Wire.endTransmission() == 0);
} else {
if (writeReg) {
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
}
Wire.requestFrom(addr, static_cast<uint8_t>(len));
for (size_t i = 0; i < len; ++i) {
if (Wire.available()) {
buf[i] = Wire.read();
} else {
return false;
}
}
return true;
}
}
uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2)
{
switch (op) {
// Set GPIO mode
case SensorCommCustomHal::OP_PINMODE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t mode = reinterpret_cast<uintptr_t>(param2);
pinMode(pin, mode);
}
break;
// Set GPIO level
case SensorCommCustomHal::OP_DIGITALWRITE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t level = reinterpret_cast<uintptr_t>(param2);
digitalWrite(pin, level);
}
break;
// Read GPIO level
case SensorCommCustomHal::OP_DIGITALREAD: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
return digitalRead(pin);
}
break;
// Get the current running milliseconds
case SensorCommCustomHal::OP_MILLIS:
return millis();
// Delay in milliseconds
case SensorCommCustomHal::OP_DELAY: {
if (param1) {
uint32_t ms = reinterpret_cast<uintptr_t>(param1);
delay(ms);
}
}
break;
// Delay in microseconds
case SensorCommCustomHal::OP_DELAYMICROSECONDS: {
uint32_t us = reinterpret_cast<uintptr_t>(param1);
delayMicroseconds(us);
}
break;
default:
break;
}
return 0;
}
void TouchDrvDigitalWrite(uint8_t gpio, uint8_t level)
{
if (gpio & 0x80) {
extension.digitalWrite(gpio & 0x7F, level);
} else {
digitalWrite(gpio, level);
}
}
uint8_t TouchDrvDigitalRead(uint8_t gpio)
{
if (gpio & 0x80) {
return extension.digitalRead(gpio & 0x7F);
} else {
return digitalRead(gpio);
}
}
void TouchDrvPinMode(uint8_t gpio, uint8_t mode)
{
if (gpio & 0x80) {
extension.pinMode(gpio & 0x7F, mode);
} else {
pinMode(gpio, mode);
}
}
bool setupTouchDrv()
{
// Add the highest bit to indicate that the GPIO extension is used, not the ESP's GPIO
const uint8_t touch_reset_pin = tp_reset | 0x80;
const uint8_t touch_irq_pin = TOUCH_IRQ;
bool result = false;
touchDrv = new TouchDrvCSTXXX();
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(i2c_wr_function, hal_callback, CST816_SLAVE_ADDRESS);
if (result) {
const char *model = touchDrv->getModelName();
Serial.print("Successfully initialized "); Serial.print(model);
Serial.print(",using "); Serial.print(model); Serial.println(" Driver!");
return true;
}
delete touchDrv;
touchDrv = new TouchDrvGT911();
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(i2c_wr_function, hal_callback, GT911_SLAVE_ADDRESS_L);
if (result) {
const char *model = touchDrv->getModelName();
Serial.print("Successfully initialized "); Serial.print(model);
Serial.print(",using "); Serial.print(model); Serial.println(" Driver!");
return true;
}
delete touchDrv;
touchDrv = new TouchDrvFT6X36();
touchDrv->setGpioCallback(TouchDrvPinMode, TouchDrvDigitalWrite, TouchDrvDigitalRead);
touchDrv->setPins(touch_reset_pin, touch_irq_pin);
result = touchDrv->begin(i2c_wr_function, hal_callback, FT3267_SLAVE_ADDRESS);
if (result) {
TouchDrvFT6X36 *tmp = static_cast<TouchDrvFT6X36 *>(touchDrv);
tmp->interruptTrigger();
const char *model = touchDrv->getModelName();
Serial.print("Successfully initialized "); Serial.print(model);
Serial.print(",using "); Serial.print(model); Serial.println(" Driver!");
return true;
}
delete touchDrv;
Serial.println("Unable to find touch device.");
touchDrv = NULL;
return false;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println("Start!");
#if (defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_STM32)) && !defined(ARDUINO_ARCH_MBED)
Wire.setSCL(TOUCH_SCL);
Wire.setSDA(TOUCH_SDA);
Wire.begin();
#elif defined(ARDUINO_ARCH_NRF52)
Wire.setPins(TOUCH_SDA, TOUCH_SCL);
Wire.begin();
#elif defined(ARDUINO_ARCH_ESP32)
Wire.begin(TOUCH_SDA, TOUCH_SCL);
#else
Wire.begin();
#endif
SensorWireHelper::dumpDevices(Wire);
// Use unspecified address to test the address discovery function.
// T-RGB XL9555 uses 0X20 device address
if (!extension.begin(i2c_wr_function, XL9555_UNKOWN_ADDRESS)) {
Serial.println("Failed to find XL9555 - check your wiring!");
while (1) {
delay(1000);
}
}
if (!setupTouchDrv()) {
while (1) {
delay(3000);
}
}
}
void loop()
{
if (touchDrv->isPressed()) {
uint8_t touched = touchDrv->getPoint(x, y, touchDrv->getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
Serial.print("X[");
Serial.print(i);
Serial.print("]:");
Serial.print(x[i]);
Serial.print(" ");
Serial.print(" Y[");
Serial.print(i);
Serial.print("]:");
Serial.print(y[i]);
Serial.print(" ");
}
Serial.println();
}
}
delay(5);
}

View File

@ -0,0 +1,219 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CustomCallbackUsageExamples.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-20
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF8563.hpp"
#include "SensorBMA423.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
SensorPCF8563 rtc;
SensorBMA423 accel;
uint32_t intervalue;
char buf[64];
bool i2c_wr_function(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite)
{
if (isWrite) {
Wire.beginTransmission(addr);
if (writeReg) {
Wire.write(reg);
}
if (buf && len > 0) {
Wire.write(buf, len);
}
return (Wire.endTransmission() == 0);
} else {
if (writeReg) {
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
}
Wire.requestFrom(addr, static_cast<uint8_t>(len));
for (size_t i = 0; i < len; ++i) {
if (Wire.available()) {
buf[i] = Wire.read();
} else {
return false;
}
}
return true;
}
}
uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2)
{
switch (op) {
case SensorCommCustomHal::OP_PINMODE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t mode = reinterpret_cast<uintptr_t>(param2);
pinMode(pin, mode);
}
break;
case SensorCommCustomHal::OP_DIGITALWRITE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t level = reinterpret_cast<uintptr_t>(param2);
digitalWrite(pin, level);
}
break;
case SensorCommCustomHal::OP_DIGITALREAD: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
return digitalRead(pin);
}
break;
case SensorCommCustomHal::OP_MILLIS:
return millis();
break;
case SensorCommCustomHal::OP_DELAY: {
if (param1) {
uint32_t ms = reinterpret_cast<uintptr_t>(param1);
delay(ms);
}
}
break;
case SensorCommCustomHal::OP_DELAYMICROSECONDS: {
uint32_t us = reinterpret_cast<uintptr_t>(param1);
delayMicroseconds(us);
}
break;
default:
break;
}
return 0;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
#if (defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_STM32)) && !defined(ARDUINO_ARCH_MBED)
Wire.setSCL(SENSOR_SCL);
Wire.setSDA(SENSOR_SDA);
Wire.begin();
#elif defined(ARDUINO_ARCH_NRF52)
Wire.setPins(SENSOR_SDA, SENSOR_SCL);
Wire.begin();
#elif defined(ARDUINO_ARCH_ESP32)
Wire.begin(SENSOR_SDA, SENSOR_SCL);
#else
Wire.begin();
#endif
// Using SensorLib with callback functions
// Other sensor classes also support the same methods and can be applied to different platforms
if (!rtc.begin(i2c_wr_function)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
// The simplest way to set up
rtc.setDateTime(2024, 1, 17, 4, 21, 30);
// Unix tm structure sets the time
struct tm timeinfo;
timeinfo.tm_yday = 2025 - 1900; //Counting starts from 1900, so subtract 1900 here
timeinfo.tm_mon = 1 - 1; //Months start at 0, so you need to subtract 1.
timeinfo.tm_mday = 17;
timeinfo.tm_hour = 4;
timeinfo.tm_min = 30;
timeinfo.tm_sec = 30;
rtc.setDateTime(timeinfo);
if (!accel.begin(i2c_wr_function, hal_callback)) {
Serial.println("Failed to find BMA423 - check your wiring!");
while (1) {
delay(1000);
}
}
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
}
void loop()
{
if (millis() - intervalue > 1000) {
intervalue = millis();
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
Serial.print("Temperature:");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_DEG));
Serial.print("*C ");
Serial.print(accel.getTemperature(SensorBMA423::TEMP_FAHRENHEIT));
Serial.print("*F");
Serial.print("Dir:");
Serial.print(accel.direction());
Serial.println();
}
}

View File

@ -0,0 +1,464 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file DRV2605_Basic.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorDRV2605.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 21
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 22
#endif
SensorDRV2605 drv;
uint8_t effect = 1;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!drv.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find DRV2605 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init DRV2605 Sensor success!");
drv.selectLibrary(1);
// I2C trigger by sending 'run' command
// default, internal trigger when sending RUN command
drv.setMode(SensorDRV2605::MODE_INTTRIG);
}
void loop()
{
Serial.print("Effect #"); Serial.println(effect);
if (effect == 1) {
Serial.println("11.2 Waveform Library Effects List");
}
if (effect == 1) {
Serial.println(F("1 - Strong Click - 100%"));
}
if (effect == 2) {
Serial.println(F("2 - Strong Click - 60%"));
}
if (effect == 3) {
Serial.println(F("3 - Strong Click - 30%"));
}
if (effect == 4) {
Serial.println(F("4 - Sharp Click - 100%"));
}
if (effect == 5) {
Serial.println(F("5 - Sharp Click - 60%"));
}
if (effect == 6) {
Serial.println(F("6 - Sharp Click - 30%"));
}
if (effect == 7) {
Serial.println(F("7 - Soft Bump - 100%"));
}
if (effect == 8) {
Serial.println(F("8 - Soft Bump - 60%"));
}
if (effect == 9) {
Serial.println(F("9 - Soft Bump - 30%"));
}
if (effect == 10) {
Serial.println(F("10 - Double Click - 100%"));
}
if (effect == 11) {
Serial.println(F("11 - Double Click - 60%"));
}
if (effect == 12) {
Serial.println(F("12 - Triple Click - 100%"));
}
if (effect == 13) {
Serial.println(F("13 - Soft Fuzz - 60%"));
}
if (effect == 14) {
Serial.println(F("14 - Strong Buzz - 100%"));
}
if (effect == 15) {
Serial.println(F("15 - 750 ms Alert 100%"));
}
if (effect == 16) {
Serial.println(F("16 - 1000 ms Alert 100%"));
}
if (effect == 17) {
Serial.println(F("17 - Strong Click 1 - 100%"));
}
if (effect == 18) {
Serial.println(F("18 - Strong Click 2 - 80%"));
}
if (effect == 19) {
Serial.println(F("19 - Strong Click 3 - 60%"));
}
if (effect == 20) {
Serial.println(F("20 - Strong Click 4 - 30%"));
}
if (effect == 21) {
Serial.println(F("21 - Medium Click 1 - 100%"));
}
if (effect == 22) {
Serial.println(F("22 - Medium Click 2 - 80%"));
}
if (effect == 23) {
Serial.println(F("23 - Medium Click 3 - 60%"));
}
if (effect == 24) {
Serial.println(F("24 - Sharp Tick 1 - 100%"));
}
if (effect == 25) {
Serial.println(F("25 - Sharp Tick 2 - 80%"));
}
if (effect == 26) {
Serial.println(F("26 - Sharp Tick 3 - 60%"));
}
if (effect == 27) {
Serial.println(F("27 - Short Double Click Strong 1 - 100%"));
}
if (effect == 28) {
Serial.println(F("28 - Short Double Click Strong 2 - 80%"));
}
if (effect == 29) {
Serial.println(F("29 - Short Double Click Strong 3 - 60%"));
}
if (effect == 30) {
Serial.println(F("30 - Short Double Click Strong 4 - 30%"));
}
if (effect == 31) {
Serial.println(F("31 - Short Double Click Medium 1 - 100%"));
}
if (effect == 32) {
Serial.println(F("32 - Short Double Click Medium 2 - 80%"));
}
if (effect == 33) {
Serial.println(F("33 - Short Double Click Medium 3 - 60%"));
}
if (effect == 34) {
Serial.println(F("34 - Short Double Sharp Tick 1 - 100%"));
}
if (effect == 35) {
Serial.println(F("35 - Short Double Sharp Tick 2 - 80%"));
}
if (effect == 36) {
Serial.println(F("36 - Short Double Sharp Tick 3 - 60%"));
}
if (effect == 37) {
Serial.println(F("37 - Long Double Sharp Click Strong 1 - 100%"));
}
if (effect == 38) {
Serial.println(F("38 - Long Double Sharp Click Strong 2 - 80%"));
}
if (effect == 39) {
Serial.println(F("39 - Long Double Sharp Click Strong 3 - 60%"));
}
if (effect == 40) {
Serial.println(F("40 - Long Double Sharp Click Strong 4 - 30%"));
}
if (effect == 41) {
Serial.println(F("41 - Long Double Sharp Click Medium 1 - 100%"));
}
if (effect == 42) {
Serial.println(F("42 - Long Double Sharp Click Medium 2 - 80%"));
}
if (effect == 43) {
Serial.println(F("43 - Long Double Sharp Click Medium 3 - 60%"));
}
if (effect == 44) {
Serial.println(F("44 - Long Double Sharp Tick 1 - 100%"));
}
if (effect == 45) {
Serial.println(F("45 - Long Double Sharp Tick 2 - 80%"));
}
if (effect == 46) {
Serial.println(F("46 - Long Double Sharp Tick 3 - 60%"));
}
if (effect == 47) {
Serial.println(F("47 - Buzz 1 - 100%"));
}
if (effect == 48) {
Serial.println(F("48 - Buzz 2 - 80%"));
}
if (effect == 49) {
Serial.println(F("49 - Buzz 3 - 60%"));
}
if (effect == 50) {
Serial.println(F("50 - Buzz 4 - 40%"));
}
if (effect == 51) {
Serial.println(F("51 - Buzz 5 - 20%"));
}
if (effect == 52) {
Serial.println(F("52 - Pulsing Strong 1 - 100%"));
}
if (effect == 53) {
Serial.println(F("53 - Pulsing Strong 2 - 60%"));
}
if (effect == 54) {
Serial.println(F("54 - Pulsing Medium 1 - 100%"));
}
if (effect == 55) {
Serial.println(F("55 - Pulsing Medium 2 - 60%"));
}
if (effect == 56) {
Serial.println(F("56 - Pulsing Sharp 1 - 100%"));
}
if (effect == 57) {
Serial.println(F("57 - Pulsing Sharp 2 - 60%"));
}
if (effect == 58) {
Serial.println(F("58 - Transition Click 1 - 100%"));
}
if (effect == 59) {
Serial.println(F("59 - Transition Click 2 - 80%"));
}
if (effect == 60) {
Serial.println(F("60 - Transition Click 3 - 60%"));
}
if (effect == 61) {
Serial.println(F("61 - Transition Click 4 - 40%"));
}
if (effect == 62) {
Serial.println(F("62 - Transition Click 5 - 20%"));
}
if (effect == 63) {
Serial.println(F("63 - Transition Click 6 - 10%"));
}
if (effect == 64) {
Serial.println(F("64 - Transition Hum 1 - 100%"));
}
if (effect == 65) {
Serial.println(F("65 - Transition Hum 2 - 80%"));
}
if (effect == 66) {
Serial.println(F("66 - Transition Hum 3 - 60%"));
}
if (effect == 67) {
Serial.println(F("67 - Transition Hum 4 - 40%"));
}
if (effect == 68) {
Serial.println(F("68 - Transition Hum 5 - 20%"));
}
if (effect == 69) {
Serial.println(F("69 - Transition Hum 6 - 10%"));
}
if (effect == 70) {
Serial.println(F("70 - Transition Ramp Down Long Smooth 1 - 100 to 0%"));
}
if (effect == 71) {
Serial.println(F("71 - Transition Ramp Down Long Smooth 2 - 100 to 0%"));
}
if (effect == 72) {
Serial.println(F("72 - Transition Ramp Down Medium Smooth 1 - 100 to 0%"));
}
if (effect == 73) {
Serial.println(F("73 - Transition Ramp Down Medium Smooth 2 - 100 to 0%"));
}
if (effect == 74) {
Serial.println(F("74 - Transition Ramp Down Short Smooth 1 - 100 to 0%"));
}
if (effect == 75) {
Serial.println(F("75 - Transition Ramp Down Short Smooth 2 - 100 to 0%"));
}
if (effect == 76) {
Serial.println(F("76 - Transition Ramp Down Long Sharp 1 - 100 to 0%"));
}
if (effect == 77) {
Serial.println(F("77 - Transition Ramp Down Long Sharp 2 - 100 to 0%"));
}
if (effect == 78) {
Serial.println(F("78 - Transition Ramp Down Medium Sharp 1 - 100 to 0%"));
}
if (effect == 79) {
Serial.println(F("79 - Transition Ramp Down Medium Sharp 2 - 100 to 0%"));
}
if (effect == 80) {
Serial.println(F("80 - Transition Ramp Down Short Sharp 1 - 100 to 0%"));
}
if (effect == 81) {
Serial.println(F("81 - Transition Ramp Down Short Sharp 2 - 100 to 0%"));
}
if (effect == 82) {
Serial.println(F("82 - Transition Ramp Up Long Smooth 1 - 0 to 100%"));
}
if (effect == 83) {
Serial.println(F("83 - Transition Ramp Up Long Smooth 2 - 0 to 100%"));
}
if (effect == 84) {
Serial.println(F("84 - Transition Ramp Up Medium Smooth 1 - 0 to 100%"));
}
if (effect == 85) {
Serial.println(F("85 - Transition Ramp Up Medium Smooth 2 - 0 to 100%"));
}
if (effect == 86) {
Serial.println(F("86 - Transition Ramp Up Short Smooth 1 - 0 to 100%"));
}
if (effect == 87) {
Serial.println(F("87 - Transition Ramp Up Short Smooth 2 - 0 to 100%"));
}
if (effect == 88) {
Serial.println(F("88 - Transition Ramp Up Long Sharp 1 - 0 to 100%"));
}
if (effect == 89) {
Serial.println(F("89 - Transition Ramp Up Long Sharp 2 - 0 to 100%"));
}
if (effect == 90) {
Serial.println(F("90 - Transition Ramp Up Medium Sharp 1 - 0 to 100%"));
}
if (effect == 91) {
Serial.println(F("91 - Transition Ramp Up Medium Sharp 2 - 0 to 100%"));
}
if (effect == 92) {
Serial.println(F("92 - Transition Ramp Up Short Sharp 1 - 0 to 100%"));
}
if (effect == 93) {
Serial.println(F("93 - Transition Ramp Up Short Sharp 2 - 0 to 100%"));
}
if (effect == 94) {
Serial.println(F("94 - Transition Ramp Down Long Smooth 1 - 50 to 0%"));
}
if (effect == 95) {
Serial.println(F("95 - Transition Ramp Down Long Smooth 2 - 50 to 0%"));
}
if (effect == 96) {
Serial.println(F("96 - Transition Ramp Down Medium Smooth 1 - 50 to 0%"));
}
if (effect == 97) {
Serial.println(F("97 - Transition Ramp Down Medium Smooth 2 - 50 to 0%"));
}
if (effect == 98) {
Serial.println(F("98 - Transition Ramp Down Short Smooth 1 - 50 to 0%"));
}
if (effect == 99) {
Serial.println(F("99 - Transition Ramp Down Short Smooth 2 - 50 to 0%"));
}
if (effect == 100) {
Serial.println(F("100 - Transition Ramp Down Long Sharp 1 - 50 to 0%"));
}
if (effect == 101) {
Serial.println(F("101 - Transition Ramp Down Long Sharp 2 - 50 to 0%"));
}
if (effect == 102) {
Serial.println(F("102 - Transition Ramp Down Medium Sharp 1 - 50 to 0%"));
}
if (effect == 103) {
Serial.println(F("103 - Transition Ramp Down Medium Sharp 2 - 50 to 0%"));
}
if (effect == 104) {
Serial.println(F("104 - Transition Ramp Down Short Sharp 1 - 50 to 0%"));
}
if (effect == 105) {
Serial.println(F("105 - Transition Ramp Down Short Sharp 2 - 50 to 0%"));
}
if (effect == 106) {
Serial.println(F("106 - Transition Ramp Up Long Smooth 1 - 0 to 50%"));
}
if (effect == 107) {
Serial.println(F("107 - Transition Ramp Up Long Smooth 2 - 0 to 50%"));
}
if (effect == 108) {
Serial.println(F("108 - Transition Ramp Up Medium Smooth 1 - 0 to 50%"));
}
if (effect == 109) {
Serial.println(F("109 - Transition Ramp Up Medium Smooth 2 - 0 to 50%"));
}
if (effect == 110) {
Serial.println(F("110 - Transition Ramp Up Short Smooth 1 - 0 to 50%"));
}
if (effect == 111) {
Serial.println(F("111 - Transition Ramp Up Short Smooth 2 - 0 to 50%"));
}
if (effect == 112) {
Serial.println(F("112 - Transition Ramp Up Long Sharp 1 - 0 to 50%"));
}
if (effect == 113) {
Serial.println(F("113 - Transition Ramp Up Long Sharp 2 - 0 to 50%"));
}
if (effect == 114) {
Serial.println(F("114 - Transition Ramp Up Medium Sharp 1 - 0 to 50%"));
}
if (effect == 115) {
Serial.println(F("115 - Transition Ramp Up Medium Sharp 2 - 0 to 50%"));
}
if (effect == 116) {
Serial.println(F("116 - Transition Ramp Up Short Sharp 1 - 0 to 50%"));
}
if (effect == 117) {
Serial.println(F("117 - Transition Ramp Up Short Sharp 2 - 0 to 50%"));
}
if (effect == 118) {
Serial.println(F("118 - Long buzz for programmatic stopping - 100%"));
}
if (effect == 119) {
Serial.println(F("119 - Smooth Hum 1 (No kick or brake pulse) - 50%"));
}
if (effect == 120) {
Serial.println(F("120 - Smooth Hum 2 (No kick or brake pulse) - 40%"));
}
if (effect == 121) {
Serial.println(F("121 - Smooth Hum 3 (No kick or brake pulse) - 30%"));
}
if (effect == 122) {
Serial.println(F("122 - Smooth Hum 4 (No kick or brake pulse) - 20%"));
}
if (effect == 123) {
Serial.println(F("123 - Smooth Hum 5 (No kick or brake pulse) - 10%"));
}
// set the effect to play
drv.setWaveform(0, effect); // play effect
drv.setWaveform(1, 0); // end waveform
// play the effect!
drv.run();
// wait a bit
delay(500);
effect++;
if (effect > 117) effect = 1;
}

View File

@ -0,0 +1,9 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS ../../../SensorLib)
project(ESP_IDF_SensorExamples)

View File

@ -0,0 +1,10 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := ESP_IDF_SensorPCF8563
EXTRA_COMPONENT_DIRS = ../../../SensorLib
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,840 @@
# ESP-IDF Sensor hub examples
## Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `SensorLib Example Configuration` menu:
* Select Sensor Type , Different sensors have different transmission methods, I2C, SPI
- BHI260 Sensor (I2C & SPI)
- PCF8563 (I2C Only)
- BMA423 (I2C Only)
- FT636X (I2C Only)
- XL9555 (I2C Only)
- The other models are the same
* If you choose a sensor with I2C communication, there will be three methods to choose from:
* Configuring the sensor pins
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`. default use **esp32**
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
The output information is to configure the output voltage and enable status of the Sensor
### LL Driver
```bash
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7176
load:0x40078000,len:15564
ho 0 tail 12 room 4
load:0x40080400,len:4
0x40080400: _init at ??:?
load:0x40080404,len:3904
entry 0x40080640
I (30) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (30) boot: compile time Jan 22 2025 17:30:49
I (33) boot: Multicore bootloader
I (37) boot: chip revision: v1.0
I (41) boot.esp32: SPI Speed : 40MHz
I (45) boot.esp32: SPI Mode : DIO
I (50) boot.esp32: SPI Flash Size : 2MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label Usage Type ST Offset Length
I (71) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (78) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (85) boot: 2 factory factory app 00 00 00010000 00100000
I (93) boot: End of partition table
I (97) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0d54ch ( 54604) map
I (124) esp_image: segment 1: paddr=0001d574 vaddr=3ffb0000 size=022b8h ( 8888) load
I (128) esp_image: segment 2: paddr=0001f834 vaddr=40080000 size=007e4h ( 2020) load
I (131) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=1c450h (115792) map
I (178) esp_image: segment 4: paddr=0003c478 vaddr=400807e4 size=0bf98h ( 49048) load
I (204) boot: Loaded app from partition at offset 0x10000
I (204) boot: Disabling RNG early entropy source...
I (216) cpu_start: Multicore app
I (224) cpu_start: Pro cpu start user code
I (224) cpu_start: cpu freq: 240000000 Hz
I (224) app_init: Application information:
I (227) app_init: Project name: ESP_IDF_TouchDrv_Example
I (234) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (240) app_init: Compile time: Jan 22 2025 17:32:37
I (246) app_init: ELF file SHA256: ef2e805bc...
I (251) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (258) efuse_init: Min chip rev: v0.0
I (263) efuse_init: Max chip rev: v3.99
I (268) efuse_init: Chip rev: v1.0
I (273) heap_init: Initializing. RAM available for dynamic allocation:
I (280) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (286) heap_init: At 3FFB2BD0 len 0002D430 (181 KiB): DRAM
I (292) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (299) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (305) heap_init: At 4008C77C len 00013884 (78 KiB): IRAM
I (313) spi_flash: detected chip: winbond
I (316) spi_flash: flash io: dio
W (320) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (334) main_task: Started on CPU0
I (344) main_task: Calling app_main()
I (344) I2C: Implemented using read and write callback methods (Use higher version >= 5.0 API)
W (344) i2c.master: Please check pull-up resistances whether be connected properly. Otherwise unexpected behavior would happen. For more detailed information, please read docs
I (364) gpio: GPIO[21]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0
I (374) gpio: GPIO[22]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0
I (384) main: I2C initialized successfully
Scan I2C Devices:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- 35 -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (434) RTC: ----DRIVER PCF8563 ----
I (434) RTC: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
Using ESP-IDF Driver interface.Added Device Address : 0x51 New Dev Address: 0x3ffb4f9c Speed :400000 I (444) RTC: Initializing PCF8563 real-time clock successfully!
I (464) BMA: ----DRIVER BMA423----
I (464) BMA: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
Using ESP-IDF Driver interface.Added Device Address : 0x19 New Dev Address: 0x3ffb4ffc Speed :400000 No need configure!I (474) BMA: Initialization of BMA423 accelerometer is successful!
I (494) main: Run...
I (494) main_task: Returned from app_main()
I (494) RTC: Friday, January 17 2025 04:30:30
I (504) RTC: Jan 17 2025 04:30:30
I (504) RTC: Friday, 17. January 2025 04:30AM
I (514) BMA423: Temperature:38.00*C
I (514) BMA423: Temperature:100.40*F
I (524) BMA423: Direction:5
I (1524) RTC: Friday, January 17 2025 04:30:31
I (1524) RTC: Jan 17 2025 04:30:31
I (1524) RTC: Friday, 17. January 2025 04:30AM
I (1524) BMA423: Temperature:38.00*C
I (1524) BMA423: Temperature:100.40*F
I (1534) BMA423: Direction:5
I (2534) RTC: Friday, January 17 2025 04:30:32
I (2534) RTC: Jan 17 2025 04:30:32
I (2534) RTC: Friday, 17. January 2025 04:30AM
I (2534) BMA423: Temperature:38.00*C
I (2534) BMA423: Temperature:100.40*F
I (2544) BMA423: Direction:5
I (3544) RTC: Friday, January 17 2025 04:30:33
I (3544) RTC: Jan 17 2025 04:30:33
I (3544) RTC: Friday, 17. January 2025 04:30AM
I (3544) BMA423: Temperature:38.00*C
I (3544) BMA423: Temperature:100.40*F
```
### Legacy Driver
```bash
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7176
load:0x40078000,len:15564
ho 0 tail 12 room 4
load:0x40080400,len:4
0x40080400: _init at ??:?
load:0x40080404,len:3904
entry 0x40080640
I (30) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (31) boot: compile time Jan 22 2025 17:30:49
I (33) boot: Multicore bootloader
I (37) boot: chip revision: v1.0
I (41) boot.esp32: SPI Speed : 40MHz
I (45) boot.esp32: SPI Mode : DIO
I (50) boot.esp32: SPI Flash Size : 2MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label Usage Type ST Offset Length
I (71) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (78) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (86) boot: 2 factory factory app 00 00 00010000 00100000
I (93) boot: End of partition table
I (97) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0d200h ( 53760) map
I (124) esp_image: segment 1: paddr=0001d228 vaddr=3ffb0000 size=022e8h ( 8936) load
I (128) esp_image: segment 2: paddr=0001f518 vaddr=40080000 size=00b00h ( 2816) load
I (131) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=1b71ch (112412) map
I (177) esp_image: segment 4: paddr=0003b744 vaddr=40080b00 size=0ccd8h ( 52440) load
I (204) boot: Loaded app from partition at offset 0x10000
I (205) boot: Disabling RNG early entropy source...
I (216) cpu_start: Multicore app
I (225) cpu_start: Pro cpu start user code
I (225) cpu_start: cpu freq: 240000000 Hz
I (225) app_init: Application information:
I (228) app_init: Project name: ESP_IDF_SensorPCF8563
I (234) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (240) app_init: Compile time: Jan 22 2025 17:47:23
I (246) app_init: ELF file SHA256: 0fcff42da...
I (251) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (258) efuse_init: Min chip rev: v0.0
I (263) efuse_init: Max chip rev: v3.99
I (268) efuse_init: Chip rev: v1.0
I (273) heap_init: Initializing. RAM available for dynamic allocation:
I (280) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (286) heap_init: At 3FFB2BF0 len 0002D410 (181 KiB): DRAM
I (292) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (299) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (305) heap_init: At 4008D7D8 len 00012828 (74 KiB): IRAM
I (313) spi_flash: detected chip: winbond
I (316) spi_flash: flash io: dio
W (320) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
W (333) i2c: This driver is an old driver, please migrate your application code to adapt `driver/i2c_master.h`
I (344) main_task: Started on CPU0
I (354) main_task: Calling app_main()
I (354) I2C: Implemented using read and write callback methods (Use lower version < 5.0 API)
I (354) main: I2C initialized successfully
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- 35 -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (404) RTC: ----DRIVER PCF8563 ----
I (404) RTC: Implemented using built-in read and write methods (Use lower version < 5.0 API)
I (414) RTC: Initializing PCF8563 real-time clock successfully!
I (424) BMA: ----DRIVER BMA423----
I (424) BMA: Implemented using built-in read and write methods (Use lower version < 5.0 API)
I (444) BMA: Initialization of BMA423 accelerometer is successful!
I (444) main: Run...
I (444) main_task: Returned from app_main()
I (454) RTC: Friday, January 17 2025 04:30:30
I (454) RTC: Jan 17 2025 04:30:30
I (464) RTC: Friday, 17. January 2025 04:30AM
I (464) BMA423: Temperature:37.00*C
I (474) BMA423: Temperature:98.60*F
I (474) BMA423: Direction:5
I (1474) RTC: Friday, January 17 2025 04:30:31
I (1474) RTC: Jan 17 2025 04:30:31
I (1474) RTC: Friday, 17. January 2025 04:30AM
I (1474) BMA423: Temperature:37.00*C
I (1474) BMA423: Temperature:98.60*F
I (1484) BMA423: Direction:5
```
### Use Read/Write/Hal Callback
```bash
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7176
load:0x40078000,len:15564
ho 0 tail 12 room 4
load:0x40080400,len:4
0x40080400: _init at ??:?
load:0x40080404,len:3904
entry 0x40080640
I (30) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (31) boot: compile time Jan 22 2025 17:30:49
I (33) boot: Multicore bootloader
I (37) boot: chip revision: v1.0
I (41) boot.esp32: SPI Speed : 40MHz
I (45) boot.esp32: SPI Mode : DIO
I (50) boot.esp32: SPI Flash Size : 2MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label Usage Type ST Offset Length
I (71) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (78) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (86) boot: 2 factory factory app 00 00 00010000 00100000
I (93) boot: End of partition table
I (97) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0d2b0h ( 53936) map
I (124) esp_image: segment 1: paddr=0001d2d8 vaddr=3ffb0000 size=022e8h ( 8936) load
I (128) esp_image: segment 2: paddr=0001f5c8 vaddr=40080000 size=00a50h ( 2640) load
I (131) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=1b97ch (113020) map
I (177) esp_image: segment 4: paddr=0003b9a4 vaddr=40080a50 size=0cd88h ( 52616) load
I (205) boot: Loaded app from partition at offset 0x10000
I (205) boot: Disabling RNG early entropy source...
I (216) cpu_start: Multicore app
I (225) cpu_start: Pro cpu start user code
I (225) cpu_start: cpu freq: 240000000 Hz
I (225) app_init: Application information:
I (228) app_init: Project name: ESP_IDF_SensorPCF8563
I (234) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (240) app_init: Compile time: Jan 22 2025 18:19:56
I (246) app_init: ELF file SHA256: 952e2e97b...
I (252) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (259) efuse_init: Min chip rev: v0.0
I (263) efuse_init: Max chip rev: v3.99
I (268) efuse_init: Chip rev: v1.0
I (273) heap_init: Initializing. RAM available for dynamic allocation:
I (281) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (286) heap_init: At 3FFB2BF0 len 0002D410 (181 KiB): DRAM
I (293) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (299) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (306) heap_init: At 4008D7D8 len 00012828 (74 KiB): IRAM
I (313) spi_flash: detected chip: winbond
I (316) spi_flash: flash io: dio
W (320) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
W (333) i2c: This driver is an old driver, please migrate your application code to adapt `driver/i2c_master.h`
I (345) main_task: Started on CPU0
I (355) main_task: Calling app_main()
I (355) I2C: Implemented using read and write callback methods (Use lower version < 5.0 API)
I (355) main: I2C initialized successfully
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- 35 -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (405) RTC: ----DRIVER PCF8563 ----
I (405) RTC: Implemented using read and write callback methods
I (415) RTC: Initializing PCF8563 real-time clock successfully!
I (425) BMA: ----DRIVER BMA423----
I (425) BMA: Implemented using read and write callback methods
I (435) BMA: Initialization of BMA423 accelerometer is successful!
I (445) main: Run...
I (445) main_task: Returned from app_main()
I (445) RTC: Friday, January 17 2025 04:30:30
I (455) RTC: Jan 17 2025 04:30:30
I (455) RTC: Friday, 17. January 2025 04:30AM
I (465) BMA423: Temperature:35.00*C
I (465) BMA423: Temperature:95.00*F
I (475) BMA423: Direction:5
I (1475) RTC: Friday, January 17 2025 04:30:31
I (1475) RTC: Jan 17 2025 04:30:31
I (1475) RTC: Friday, 17. January 2025 04:30AM
I (1475) BMA423: Temperature:35.00*C
I (1475) BMA423: Temperature:95.00*F
I (1485) BMA423: Direction:5
I (2485) RTC: Friday, January 17 2025 04:30:32
I (2485) RTC: Jan 17 2025 04:30:32
I (2485) RTC: Friday, 17. January 2025 04:30AM
```
### BHI260AP SPI Interface
```bash
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2810,len:0x178c
load:0x403c8700,len:0x4
load:0x403c8704,len:0xc10
load:0x403cb700,len:0x2dac
entry 0x403c8904
I (26) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (27) boot: compile time Jan 23 2025 11:42:56
I (27) boot: Multicore bootloader
I (27) boot: chip revision: v0.1
I (27) boot.esp32s3: Boot SPI Speed : 80MHz
I (27) boot.esp32s3: SPI Mode : DIO
I (28) boot.esp32s3: SPI Flash Size : 2MB
I (28) boot: Enabling RNG early entropy source...
I (28) boot: Partition Table:
I (28) boot: ## Label Usage Type ST Offset Length
I (29) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (29) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (29) boot: 2 factory factory app 00 00 00010000 00100000
I (30) boot: End of partition table
I (30) esp_image: segment 0: paddr=00010020 vaddr=3c030020 size=29698h (169624) map
I (61) esp_image: segment 1: paddr=000396c0 vaddr=3fc94a00 size=02b0ch ( 11020) load
I (64) esp_image: segment 2: paddr=0003c1d4 vaddr=40374000 size=03e44h ( 15940) load
I (68) esp_image: segment 3: paddr=00040020 vaddr=42000020 size=28a70h (166512) map
I (98) esp_image: segment 4: paddr=00068a98 vaddr=40377e44 size=0cb2ch ( 52012) load
I (116) boot: Loaded app from partition at offset 0x10000
I (117) boot: Disabling RNG early entropy source...
I (117) cpu_start: Multicore app
I (127) cpu_start: Pro cpu start user code
I (127) cpu_start: cpu freq: 240000000 Hz
I (127) app_init: Application information:
I (127) app_init: Project name: ESP_IDF_SensorExamples
I (127) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (128) app_init: Compile time: Jan 23 2025 11:44:54
I (128) app_init: ELF file SHA256: 3512ddfc8...
I (128) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (128) efuse_init: Min chip rev: v0.0
I (128) efuse_init: Max chip rev: v0.99
I (128) efuse_init: Chip rev: v0.1
I (129) heap_init: Initializing. RAM available for dynamic allocation:
I (129) heap_init: At 3FC97EC0 len 00051850 (326 KiB): RAM
I (129) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (129) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (130) heap_init: At 600FE100 len 00001EE8 (7 KiB): RTCRAM
I (131) spi_flash: detected chip: generic
I (131) spi_flash: flash io: dio
W (131) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (132) sleep: Configure to isolate all GPIO pins in sleep state
I (132) sleep: Enable automatic switching of GPIO sleep configuration
I (133) main_task: Started on CPU0
I (143) main_task: Calling app_main()
I (143) BHI: ----DRIVER BHI260AP----
I (143) gpio: GPIO[36]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (153) SensorLib: BHI260/BHA260 found. Product ID read 0x89
I (583) SensorLib: Boot successful. Kernel version 5991.
I (583) SensorLib: [META EVENT WAKE UP] Firmware initialized. Firmware version 5991
I (583) SensorLib: [META EVENT] Firmware initialized. Firmware version 5991
I (943) BHI: Initialization of BHI260AP is successful!
Product ID : 89
Kernel version : 5991
User version : 5991
ROM version : 5166
Power state : sleeping
Host interface : SPI
Feature status : 0x4a
Boot Status : 0x38: No flash installed. Host interface ready. Firmware verification done. Virtual sensor list.
Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |
----------+--------------------------------------+-----+-----+-----------+-----------|
1 | Accelerometer passthrough | 205 | 1 | 1.5625 | 400.0000 |
3 | Accelerometer uncalibrated | 203 | 1 | 1.5625 | 400.0000 |
4 | Accelerometer corrected | 241 | 1 | 1.5625 | 400.0000 |
5 | Accelerometer offset | 209 | 1 | 1.0000 | 1.0000 |
6 | Accelerometer corrected wake up | 192 | 1 | 1.5625 | 400.0000 |
7 | Accelerometer uncalibrated wake up | 204 | 1 | 1.5625 | 400.0000 |
10 | Gyroscope passthrough | 207 | 1 | 1.5625 | 400.0000 |
12 | Gyroscope uncalibrated | 244 | 1 | 1.5625 | 400.0000 |
13 | Gyroscope corrected | 243 | 1 | 1.5625 | 400.0000 |
14 | Gyroscope offset | 208 | 1 | 1.0000 | 1.0000 |
15 | Gyroscope wake up | 194 | 1 | 1.5625 | 400.0000 |
16 | Gyroscope uncalibrated wake up | 195 | 1 | 1.5625 | 400.0000 |
28 | Gravity vector | 247 | 1 | 1.5625 | 400.0000 |
29 | Gravity vector wake up | 198 | 1 | 1.5625 | 400.0000 |
31 | Linear acceleration | 246 | 1 | 1.5625 | 400.0000 |
32 | Linear acceleration wake up | 197 | 1 | 1.5625 | 400.0000 |
37 | Game rotation vector | 252 | 1 | 1.5625 | 400.0000 |
38 | Game rotation vector wake up | 200 | 1 | 1.5625 | 400.0000 |
48 | Tilt detector | 236 | 1 | 1.0000 | 1.0000 |
50 | Step detector | 248 | 1 | 1.0000 | 1.0000 |
52 | Step counter | 249 | 1 | 1.0000 | 1.0000 |
53 | Step counter wake up | 231 | 1 | 0.0005 | 25.0000 |
55 | Significant motion | 250 | 1 | 1.0000 | 1.0000 |
57 | Wake gesture | 232 | 1 | 1.0000 | 1.0000 |
59 | Glance gesture | 234 | 1 | 1.0000 | 1.0000 |
61 | Pickup gesture | 233 | 1 | 1.0000 | 1.0000 |
63 | Activity recognition | 235 | 1 | 1.0000 | 1.0000 |
67 | Wrist tilt gesture | 162 | 1 | 1.0000 | 1.0000 |
69 | Device orientation | 163 | 1 | 1.0000 | 1.0000 |
70 | Device orientation wake up | 164 | 1 | 1.0000 | 1.0000 |
75 | Stationary detect | 161 | 1 | 1.0000 | 1.0000 |
77 | Motion detect | 160 | 1 | 1.0000 | 1.0000 |
94 | Step detector wake up | 230 | 1 | 1.0000 | 1.0000 |
I (1293) gpio: GPIO[37]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2
I (1293) main: Run...
I (1293) main_task: Returned from app_main()
I (1683) SensorLib: [META EVENT] Power mode changed for sensor id 1
I (1683) SensorLib: [META EVENT] Sample rate changed for sensor id 1
I (1683) SensorLib: [META EVENT] Power mode changed for sensor id 10
I (1683) SensorLib: [META EVENT] Sample rate changed for sensor id 10
I (1683) BHI: Accelerometer passthrough: x: -0.212646, y: 0.300293, z: 0.953613;
I (1683) BHI: Gyroscope passthrough: x: -0.671387, y: -0.732422, z: -0.122070;
I (2313) BHI: Accelerometer passthrough: x: -0.213379, y: 0.302734, z: 0.960205;
I (2313) BHI: Gyroscope passthrough: x: -0.610352, y: -0.671387, z: -0.061035;
I (2953) BHI: Accelerometer passthrough: x: -0.213623, y: 0.302734, z: 0.960449;
I (2953) BHI: Gyroscope passthrough: x: -0.671387, y: -0.732422, z: -0.061035;
I (3583) BHI: Accelerometer passthrough: x: -0.213379, y: 0.302979, z: 0.960205;
I (3583) BHI: Gyroscope passthrough: x: -0.610352, y: -0.610352, z: -0.061035;
I (4223) BHI: Accelerometer passthrough: x: -0.213623, y: 0.302490, z: 0.960449;
I (4223) BHI: Gyroscope passthrough: x: -0.610352, y: -0.671387, z: -0.122070;
I (4853) BHI: Accelerometer passthrough: x: -0.213867, y: 0.303467, z: 0.960205;
I (4853) BHI: Gyroscope passthrough: x: -0.610352, y: -0.671387, z: -0.122070;
```
### BHI260 I2C Interface
```bash
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2810,len:0x178c
load:0x403c8700,len:0x4
load:0x403c8704,len:0xcb8
load:0x403cb700,len:0x2d9c
entry 0x403c8914
I (26) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (27) boot: compile time Jan 23 2025 14:20:21
I (28) boot: Multicore bootloader
I (32) boot: chip revision: v0.2
I (36) boot.esp32s3: Boot SPI Speed : 80MHz
I (41) boot.esp32s3: SPI Mode : DIO
I (45) boot.esp32s3: SPI Flash Size : 2MB
I (50) boot: Enabling RNG early entropy source...
I (55) boot: Partition Table:
I (59) boot: ## Label Usage Type ST Offset Length
I (66) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (74) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (81) boot: 2 factory factory app 00 00 00010000 00100000
I (89) boot: End of partition table
I (93) esp_image: segment 0: paddr=00010020 vaddr=3c030020 size=2abc8h (175048) map
I (133) esp_image: segment 1: paddr=0003abf0 vaddr=3fc95300 size=02bcch ( 11212) load
I (135) esp_image: segment 2: paddr=0003d7c4 vaddr=40374000 size=02854h ( 10324) load
I (141) esp_image: segment 3: paddr=00040020 vaddr=42000020 size=2b8d8h (178392) map
I (179) esp_image: segment 4: paddr=0006b900 vaddr=40376854 size=0ea24h ( 59940) load
I (199) boot: Loaded app from partition at offset 0x10000
I (200) boot: Disabling RNG early entropy source...
I (211) cpu_start: Multicore app
I (220) cpu_start: Pro cpu start user code
I (221) cpu_start: cpu freq: 160000000 Hz
I (221) app_init: Application information:
I (223) app_init: Project name: ESP_IDF_SensorExamples
I (230) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (236) app_init: Compile time: Jan 23 2025 14:33:38
I (242) app_init: ELF file SHA256: 54e4e1748...
I (247) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (254) efuse_init: Min chip rev: v0.0
I (259) efuse_init: Max chip rev: v0.99
I (264) efuse_init: Chip rev: v0.2
I (269) heap_init: Initializing. RAM available for dynamic allocation:
I (276) heap_init: At 3FC988C8 len 00050E48 (323 KiB): RAM
I (282) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (288) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (294) heap_init: At 600FE100 len 00001EE8 (7 KiB): RTCRAM
I (302) spi_flash: detected chip: winbond
I (305) spi_flash: flash io: dio
W (309) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (322) sleep: Configure to isolate all GPIO pins in sleep state
I (329) sleep: Enable automatic switching of GPIO sleep configuration
I (337) main_task: Started on CPU0
I (347) main_task: Calling app_main()
I (347) I2C: Implemented using read and write callback methods (Use higher version >= 5.0 API)
W (357) i2c.master: Please check pull-up resistances whether be connected properly. Otherwise unexpected behavior would happen. For more detailed information, please read docs
I (367) gpio: GPIO[2]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0
I (377) gpio: GPIO[3]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0
I (387) main: I2C initialized successfully
Scan I2C Devices:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- 28 -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- 5a -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- 6b -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (437) BHI: ----DRIVER BHI260AP----
I (447) BHI: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
I (457) SensorLib: Using ESP-IDF Driver interface.
I (457) SensorLib: Added Device Address : 0x28 New Dev Address: 0x3fc9cc34 Speed :400000
I (477) SensorLib: BHI260/BHA260 found. Product ID read 0x89
I (3497) SensorLib: Boot successful. Kernel version 5991.
I (3497) SensorLib: [META EVENT WAKE UP] Firmware initialized. Firmware version 5991
I (3497) SensorLib: [META EVENT] Firmware initialized. Firmware version 5991
I (3597) BHI: Initialize BHI260AP using I2C interface
Product ID : 89
Kernel version : 5991
User version : 5991
ROM version : 5166
Power state : sleeping
Host interface : I2C
Feature status : 0x4a
Boot Status : 0x38: No flash installed. Host interface ready. Firmware verification done. Virtual sensor list.
Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |
----------+--------------------------------------+-----+-----+-----------+-----------|
1 | Accelerometer passthrough | 205 | 1 | 1.5625 | 400.0000 |
3 | Accelerometer uncalibrated | 203 | 1 | 1.5625 | 400.0000 |
4 | Accelerometer corrected | 241 | 1 | 1.5625 | 400.0000 |
5 | Accelerometer offset | 209 | 1 | 1.0000 | 1.0000 |
6 | Accelerometer corrected wake up | 192 | 1 | 1.5625 | 400.0000 |
7 | Accelerometer uncalibrated wake up | 204 | 1 | 1.5625 | 400.0000 |
10 | Gyroscope passthrough | 207 | 1 | 1.5625 | 400.0000 |
12 | Gyroscope uncalibrated | 244 | 1 | 1.5625 | 400.0000 |
13 | Gyroscope corrected | 243 | 1 | 1.5625 | 400.0000 |
14 | Gyroscope offset | 208 | 1 | 1.0000 | 1.0000 |
15 | Gyroscope wake up | 194 | 1 | 1.5625 | 400.0000 |
16 | Gyroscope uncalibrated wake up | 195 | 1 | 1.5625 | 400.0000 |
28 | Gravity vector | 247 | 1 | 1.5625 | 400.0000 |
29 | Gravity vector wake up | 198 | 1 | 1.5625 | 400.0000 |
31 | Linear acceleration | 246 | 1 | 1.5625 | 400.0000 |
32 | Linear acceleration wake up | 197 | 1 | 1.5625 | 400.0000 |
37 | Game rotation vector | 252 | 1 | 1.5625 | 400.0000 |
38 | Game rotation vector wake up | 200 | 1 | 1.5625 | 400.0000 |
48 | Tilt detector | 236 | 1 | 1.0000 | 1.0000 |
50 | Step detector | 248 | 1 | 1.0000 | 1.0000 |
52 | Step counter | 249 | 1 | 1.0000 | 1.0000 |
53 | Step counter wake up | 231 | 1 | 0.0005 | 25.0000 |
55 | Significant motion | 250 | 1 | 1.0000 | 1.0000 |
57 | Wake gesture | 232 | 1 | 1.0000 | 1.0000 |
59 | Glance gesture | 234 | 1 | 1.0000 | 1.0000 |
61 | Pickup gesture | 233 | 1 | 1.0000 | 1.0000 |
63 | Activity recognition | 235 | 1 | 1.0000 | 1.0000 |
67 | Wrist tilt gesture | 162 | 1 | 1.0000 | 1.0000 |
69 | Device orientation | 163 | 1 | 1.0000 | 1.0000 |
70 | Device orientation wake up | 164 | 1 | 1.0000 | 1.0000 |
75 | Stationary detect | 161 | 1 | 1.0000 | 1.0000 |
77 | Motion detect | 160 | 1 | 1.0000 | 1.0000 |
94 | Step detector wake up | 230 | 1 | 1.0000 | 1.0000 |
I (3937) gpio: GPIO[8]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2
I (3947) main: Run...
I (3947) main_task: Returned from app_main()
I (4347) SensorLib: [META EVENT] Power mode changed for sensor id 1
I (4347) SensorLib: [META EVENT] Sample rate changed for sensor id 1
I (4347) SensorLib: [META EVENT] Power mode changed for sensor id 10
I (4357) SensorLib: [META EVENT] Sample rate changed for sensor id 10
I (4357) BHI: Accelerometer passthrough: x: 0.129395, y: 0.024658, z: 1.018799;
I (4367) BHI: Gyroscope passthrough: x: -0.305176, y: 0.183105, z: 0.183105;
I (4987) BHI: Accelerometer passthrough: x: 0.129639, y: 0.024414, z: 1.024902;
I (4987) BHI: Gyroscope passthrough: x: -0.244141, y: 0.183105, z: 0.183105;
I (5627) BHI: Accelerometer passthrough: x: 0.129639, y: 0.025391, z: 1.025635;
I (5627) BHI: Gyroscope passthrough: x: -0.305176, y: 0.183105, z: 0.183105;
I (6267) BHI: Accelerometer passthrough: x: 0.130127, y: 0.025146, z: 1.025391;
I (6267) BHI: Gyroscope passthrough: x: -0.244141, y: 0.244141, z: 0.183105;
I (6907) BHI: Accelerometer passthrough: x: 0.129883, y: 0.024902, z: 1.025635;
I (6907) BHI: Gyroscope passthrough: x: -0.305176, y: 0.244141, z: 0.244141;
I (7547) BHI: Accelerometer passthrough: x: 0.129883, y: 0.025635, z: 1.025635;
I (7547) BHI: Gyroscope passthrough: x: -0.305176, y: 0.183105, z: 0.244141;
I (8187) BHI: Accelerometer passthrough: x: 0.130127, y: 0.025146, z: 1.026123;
I (8187) BHI: Gyroscope passthrough: x: -0.305176, y: 0.244141, z: 0.183105;
I (8827) BHI: Accelerometer passthrough: x: 0.129883, y: 0.024902, z: 1.025879;
I (8827) BHI: Gyroscope passthrough: x: -0.305176, y: 0.183105, z: 0.183105;
```
### FT63XX
```bash
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7176
load:0x40078000,len:15564
ho 0 tail 12 room 4
load:0x40080400,len:4
0x40080400: _init at ??:?
load:0x40080404,len:3904
entry 0x40080640
I (30) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (30) boot: compile time Jan 23 2025 15:30:25
I (33) boot: Multicore bootloader
I (37) boot: chip revision: v1.0
I (41) boot.esp32: SPI Speed : 40MHz
I (45) boot.esp32: SPI Mode : DIO
I (50) boot.esp32: SPI Flash Size : 2MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label Usage Type ST Offset Length
I (71) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (78) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (85) boot: 2 factory factory app 00 00 00010000 00100000
I (93) boot: End of partition table
I (97) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=0b860h ( 47200) map
I (122) esp_image: segment 1: paddr=0001b888 vaddr=3ffb0000 size=02258h ( 8792) load
I (125) esp_image: segment 2: paddr=0001dae8 vaddr=40080000 size=02530h ( 9520) load
I (131) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=18744h (100164) map
I (170) esp_image: segment 4: paddr=0003876c vaddr=40082530 size=0a210h ( 41488) load
I (193) boot: Loaded app from partition at offset 0x10000
I (193) boot: Disabling RNG early entropy source...
I (205) cpu_start: Multicore app
I (214) cpu_start: Pro cpu start user code
I (214) cpu_start: cpu freq: 160000000 Hz
I (214) app_init: Application information:
I (217) app_init: Project name: ESP_IDF_SensorExamples
I (223) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (229) app_init: Compile time: Jan 23 2025 15:44:44
I (235) app_init: ELF file SHA256: fe7a7c460...
I (240) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (247) efuse_init: Min chip rev: v0.0
I (252) efuse_init: Max chip rev: v3.99
I (257) efuse_init: Chip rev: v1.0
I (262) heap_init: Initializing. RAM available for dynamic allocation:
I (269) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (275) heap_init: At 3FFB2B78 len 0002D488 (181 KiB): DRAM
I (281) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (288) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (294) heap_init: At 4008C740 len 000138C0 (78 KiB): IRAM
I (302) spi_flash: detected chip: winbond
I (305) spi_flash: flash io: dio
W (309) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (323) main_task: Started on CPU0
I (333) main_task: Calling app_main()
I (333) I2C: Implemented using read and write callback methods (Use higher version >= 5.0 API)
I (333) gpio: GPIO[23]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (343) gpio: GPIO[32]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (353) main: I2C initialized successfully
Scan I2C Devices:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (403) FT63XX: ----DRIVER FT63XX----
I (403) FT63XX: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
I (413) SensorLib: Using ESP-IDF Driver interface.
I (423) SensorLib: Added Device Address : 0x38 New Dev Address: 0x3ffb4f58 Speed :400000
I (433) SensorLib: Vend ID: 0x11
I (433) SensorLib: Chip ID: 0x64
I (443) SensorLib: Firm Version: 0x3
I (443) SensorLib: Point Rate Hz: 10
I (453) SensorLib: Thresh : 60
I (453) SensorLib: Chip library version : 0x501
I (453) SensorLib: Chip period of monitor status : 0x28
I (463) FT63XX: Initialization of FT63XX is successful!
I (473) main: Run...
I (473) main_task: Returned from app_main()
I (6733) FT63X6: Point[00] - X:113 Y:126
I (6743) FT63X6: Point[00] - X:113 Y:126
I (6753) FT63X6: Point[00] - X:113 Y:126
I (6763) FT63X6: Point[00] - X:113 Y:126
I (6773) FT63X6: Point[00] - X:113 Y:126
I (6783) FT63X6: Point[00] - X:113 Y:126
I (6793) FT63X6: Point[00] - X:113 Y:128
I (6803) FT63X6: Point[00] - X:110 Y:140
I (6813) FT63X6: Point[00] - X:109 Y:150
I (6823) FT63X6: Point[00] - X:107 Y:162
I (6833) FT63X6: Point[00] - X:105 Y:176
I (6843) FT63X6: Point[00] - X:100 Y:193
I (6853) FT63X6: Point[00] - X:92 Y:206
I (7273) FT63X6: Point[00] - X:88 Y:273
I (7283) FT63X6: Point[00] - X:88 Y:273
I (7293) FT63X6: Point[00] - X:88 Y:273
I (7303) FT63X6: Point[00] - X:90 Y:270
I (7313) FT63X6: Point[00] - X:93 Y:266
I (7323) FT63X6: Point[00] - X:99 Y:259
I (7333) FT63X6: Point[00] - X:109 Y:247
I (7343) FT63X6: Point[00] - X:118 Y:236
I (7353) FT63X6: Point[00] - X:128 Y:223
I (7363) FT63X6: Point[00] - X:138 Y:209
I (7373) FT63X6: Point[00] - X:148 Y:195
I (7383) FT63X6: Point[00] - X:158 Y:180
I (7393) FT63X6: Point[00] - X:165 Y:169
I (7403) FT63X6: Point[00] - X:170 Y:160
I (7413) FT63X6: Point[00] - X:174 Y:153
I (7423) FT63X6: Point[00] - X:177 Y:148
I (7433) FT63X6: Point[00] - X:178 Y:145
```
### XL9555
```bash
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2810,len:0x178c
load:0x403c8700,len:0x4
load:0x403c8704,len:0xcb8
load:0x403cb700,len:0x2d9c
entry 0x403c8914
I (26) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (27) boot: compile time Jan 23 2025 16:15:44
I (28) boot: Multicore bootloader
I (32) boot: chip revision: v0.1
I (36) boot.esp32s3: Boot SPI Speed : 80MHz
I (41) boot.esp32s3: SPI Mode : DIO
I (45) boot.esp32s3: SPI Flash Size : 2MB
I (50) boot: Enabling RNG early entropy source...
I (55) boot: Partition Table:
I (59) boot: ## Label Usage Type ST Offset Length
I (66) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (74) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (81) boot: 2 factory factory app 00 00 00010000 00100000
I (89) boot: End of partition table
I (93) esp_image: segment 0: paddr=00010020 vaddr=3c030020 size=0c95ch ( 51548) map
I (110) esp_image: segment 1: paddr=0001c984 vaddr=3fc93300 size=02ad8h ( 10968) load
I (113) esp_image: segment 2: paddr=0001f464 vaddr=40374000 size=00bb4h ( 2996) load
I (119) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=20b8ch (134028) map
I (151) esp_image: segment 4: paddr=00040bb4 vaddr=40374bb4 size=0e6c4h ( 59076) load
I (170) boot: Loaded app from partition at offset 0x10000
I (170) boot: Disabling RNG early entropy source...
I (182) cpu_start: Multicore app
I (191) cpu_start: Pro cpu start user code
I (191) cpu_start: cpu freq: 160000000 Hz
I (192) app_init: Application information:
I (194) app_init: Project name: ESP_IDF_SensorExamples
I (200) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (207) app_init: Compile time: Jan 23 2025 16:28:47
I (213) app_init: ELF file SHA256: c5b0aa4bb...
I (218) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (225) efuse_init: Min chip rev: v0.0
I (230) efuse_init: Max chip rev: v0.99
I (235) efuse_init: Chip rev: v0.1
I (240) heap_init: Initializing. RAM available for dynamic allocation:
I (247) heap_init: At 3FC967E8 len 00052F28 (331 KiB): RAM
I (253) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (259) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (265) heap_init: At 600FE100 len 00001EE8 (7 KiB): RTCRAM
I (272) spi_flash: detected chip: winbond
I (276) spi_flash: flash io: dio
W (280) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (293) sleep: Configure to isolate all GPIO pins in sleep state
I (300) sleep: Enable automatic switching of GPIO sleep configuration
I (307) main_task: Started on CPU0
I (317) main_task: Calling app_main()
I (317) I2C: Implemented using read and write callback methods (Use higher version >= 5.0 API)
I (327) gpio: GPIO[8]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (337) gpio: GPIO[48]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (347) main: I2C initialized successfully
Scan I2C Devices:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (397) XL9555: ----DRIVER XL9555 ----
I (397) XL9555: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
I (407) SensorLib: Using ESP-IDF Driver interface.
I (417) SensorLib: Added Device Address : 0xFF New Dev Address: 0x3fc9aad8 Speed :400000
I (417) SensorLib: i2c_master_bus_rm_device
I (427) SensorLib: Using ESP-IDF Driver interface.
I (427) SensorLib: Added Device Address : 0x20 New Dev Address: 0x3fc9aad8 Speed :400000
I (437) XL9555: Initializing XL9555 successfully!
I (447) main: Run...
I (447) main_task: Returned from app_main()
```
## Build process example
Assuming you don't have esp-idf yet
```bash
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
git clone https://github.com/lewisxhe/SensorLib.git
cd esp-idf
./install.sh
. ./export.sh
cd ..
cd SensorLib/examples/ESP_IDF_SensorExamples
Configure Sensor Type
Configure I2C Pins or SPI Pins
...
idf.py set-target esp32
idf.py menuconfig
idf.py build
idf.py -b 921600 flash
idf.py monitor
```

View File

@ -0,0 +1,9 @@
idf_component_register(SRCS
"sensor_pcf8563.cpp"
"sensor_bma423.cpp"
"sensor_bhi260.cpp"
"i2c_driver.cpp"
"touch_ft63x6.cpp"
"sensor_xl9555.cpp"
"main.cpp"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,115 @@
menu "SensorLib Example Configuration"
choice SENSOR_TYPE
prompt "Select Sensor Type"
default PCF8563
help
Choose the type of sensor you are using.
config PCF8563
bool "PCF8563 Sensor"
config BMA423
bool "BMA423 Sensor"
config BHI260
bool "BHI260 Sensor"
config FT636X
bool "FT636X Capacitive touch"
config XL9555
bool "XL9555 GPIO expansion"
endchoice
choice BHI260_COMMUNICATION_TYPE
prompt "Select BHI260 Communication Type"
default USE_I2C_INTERFACE
depends on BHI260
help
Choose the communication type for BHI260 sensor.
config USE_I2C_INTERFACE
bool "I2C Communication"
config USE_SPI_INTERFACE
bool "SPI Communication"
endchoice
choice I2C_COMMUNICATION_METHOD
prompt "SensorLib read and write methods"
default I2C_COMMUNICATION_METHOD_BUILTIN_RW
depends on (PCF8563 || BMA423 || FT636X || XL9555 || (BHI260 && USE_I2C_INTERFACE))
help
Define SensorLib read and write methods
config I2C_COMMUNICATION_METHOD_BUILTIN_RW
bool "Implemented using built-in read and write methods"
config I2C_COMMUNICATION_METHOD_CALLBACK_RW
bool "Implemented using read and write callback methods"
endchoice
config I2C_MASTER_PORT_NUM
int "Sensor I2C Port Number"
default 1
depends on (PCF8563 || BMA423 || FT636X || XL9555 || (BHI260 && USE_I2C_INTERFACE))
help
Port number for I2C Master device.
config I2C_MASTER_FREQUENCY
int "Master Frequency"
default 100000
depends on (PCF8563 || BMA423 || FT636X || XL9555 || (BHI260 && USE_I2C_INTERFACE))
help
I2C Speed of Master device.
config SENSOR_SCL
int "Sensor SCL GPIO Num"
default 22
depends on (PCF8563 || BMA423 || FT636X || XL9555 || (BHI260 && USE_I2C_INTERFACE))
help
GPIO number for I2C clock line.
config SENSOR_SDA
int "Sensor SDA GPIO Num"
default 21
depends on (PCF8563 || BMA423 || FT636X || XL9555 || (BHI260 && USE_I2C_INTERFACE))
help
GPIO number for I2C data line.
config SPI_MISO
int "SPI MISO GPIO Num"
default 34
depends on (BHI260 && USE_SPI_INTERFACE)
help
GPIO number for Sensor SPI MISO line.
config SPI_MOSI
int "SPI MOSI GPIO Num"
default 33
depends on (BHI260 && USE_SPI_INTERFACE)
help
GPIO number for Sensor SPI MOSI line.
config SPI_SCK
int "SPI SCK GPIO Num"
default 35
depends on (BHI260 && USE_SPI_INTERFACE)
help
GPIO number for Sensor SPI SCK line.
config SPI_CS
int "SPI CS GPIO Num"
default 36
depends on (BHI260 && USE_SPI_INTERFACE)
help
GPIO number for Sensor SPI CS line.
config SENSOR_IRQ
int "Sensor Interrupt Pin"
default 37
help
GPIO number for Sensor Interrupt line.
config SENSOR_RST
int "Sensor reset Pin"
default 47
help
GPIO number for Sensor Reset line.
endmenu

View File

@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -0,0 +1,378 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file i2c_driver.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "i2c_driver.h"
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW || CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
static const char *TAG = "I2C";
#define I2C_MASTER_NUM (i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM
#define I2C_MASTER_SDA_IO (gpio_num_t)CONFIG_SENSOR_SDA
#define I2C_MASTER_SCL_IO (gpio_num_t)CONFIG_SENSOR_SCL
#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "soc/clk_tree_defs.h"
i2c_master_dev_handle_t i2c_device;
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
i2c_master_bus_handle_t bus_handle;
#endif
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
bool i2c_wr_function(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite)
{
if (isWrite) {
esp_err_t ret;
if (buf == NULL) {
return false;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
if (writeReg) {
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1));
if (!write_buffer) {
return -1;
}
write_buffer[0] = reg;
memcpy(write_buffer + 1, buf, len);
ret = i2c_master_transmit(
i2c_device,
write_buffer,
len + 1,
-1);
free(write_buffer);
} else {
ret = i2c_master_transmit(i2c_device, buf, len, -1);
}
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
if (writeReg) {
i2c_master_write_byte(cmd, reg, true);
}
i2c_master_write(cmd, buf, len, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_write_error.");
}
#endif
return ret == ESP_OK ? true : false;
} else {
esp_err_t ret;
if (len == 0) {
return true;
}
if (buf == NULL) {
return false;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ret = i2c_master_transmit_receive(i2c_device, (const uint8_t *)&reg, 1, buf, len, -1);
#else
i2c_cmd_handle_t cmd;
if (writeReg) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_master_cmd_begin failed!");
return false;
}
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, true);
if (len > 1) {
i2c_master_read(cmd, buf, len - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, &buf[len - 1], I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_read_error.");
}
#endif
return ret == ESP_OK ? true : false;
}
}
/**
* @brief Read a sequence of bytes from a pmu registers
*/
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (len == 0) {
return ESP_OK;
}
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ret = i2c_master_transmit_receive(
i2c_device,
(const uint8_t *)&regAddr,
1,
data,
len,
-1);
#else
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_master_cmd_begin failed!");
return ESP_FAIL;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, true);
if (len > 1) {
i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, &data[len - 1], I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_read_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
/**
* @brief Write a byte to a pmu register
*/
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1));
if (!write_buffer) {
return -1;
}
write_buffer[0] = regAddr;
memcpy(write_buffer + 1, data, len);
ret = i2c_master_transmit(
i2c_device,
write_buffer,
len + 1,
-1);
free(write_buffer);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_write(cmd, data, len, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_write_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
esp_err_t i2c_drv_device_init(uint8_t address)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
i2c_device_config_t i2c_dev_conf = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = address,
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
};
return i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &i2c_device);
#else
return ESP_OK;
#endif
}
#endif //CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief i2c master initialization
*/
esp_err_t i2c_drv_init(void)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use higher version >= 5.0 API)");
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = I2C_MASTER_NUM;
i2c_bus_config.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO;
i2c_bus_config.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO;
i2c_bus_config.glitch_ignore_cnt = 7;
i2c_bus_config.flags.enable_internal_pullup = true;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
return ESP_OK;
#else
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use lower version < 5.0 API)");
i2c_config_t i2c_conf ;
memset(&i2c_conf, 0, sizeof(i2c_conf));
i2c_conf.mode = I2C_MODE_MASTER;
i2c_conf.sda_io_num = I2C_MASTER_SDA_IO;
i2c_conf.scl_io_num = I2C_MASTER_SCL_IO;
i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(I2C_MASTER_NUM, &i2c_conf);
return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
#endif
}
void i2c_drv_scan()
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
esp_err_t err = ESP_OK;
uint8_t address = 0x00;
printf("Scan I2C Devices:\n");
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
err = i2c_master_probe(bus_handle, address, 100);
if (err == ESP_OK) {
printf("%02x ", address);
} else if (err == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
printf("\n\n\n");
#else
uint8_t address;
printf("Scan I2C Devices:\n");
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret == ESP_OK) {
printf("%02x ", address);
} else if (ret == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
#endif
}
bool i2c_drv_probe(uint8_t devAddr)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
return ESP_OK == i2c_master_probe(bus_handle, devAddr, 1000);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return (ret == ESP_OK);
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
}
#endif

View File

@ -0,0 +1,54 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file i2c_driver.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#pragma once
#include "esp_err.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "driver/i2c_master.h"
#else
#include "driver/i2c.h"
#endif //ESP_IDF_VERSION
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW || CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
esp_err_t i2c_drv_init(void);
void i2c_drv_scan();
bool i2c_drv_probe(uint8_t devAddr);
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
bool i2c_wr_function(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite);
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
esp_err_t i2c_drv_device_init(uint8_t address);
#endif
#endif

View File

@ -0,0 +1,199 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file main.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "i2c_driver.h"
static const char *TAG = "main";
#ifdef CONFIG_PCF8563
extern esp_err_t pcf8563_init();
extern void pcf8563_loop();
#endif
#ifdef CONFIG_BMA423
extern esp_err_t bma423_init();
extern void bma423_loop();
#endif
#ifdef CONFIG_FT636X
extern esp_err_t ft63x6_init();
extern void ft63x6_loop();
#endif
#ifdef CONFIG_BHI260
extern esp_err_t bhi260_init();
extern void bhi260_loop();
#endif
#ifdef CONFIG_XL9555
extern esp_err_t xl9555_init();
extern void xl9555_loop();
#endif
static void app_task(void *args);
extern "C" void app_main(void)
{
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW || CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
ESP_ERROR_CHECK(i2c_drv_init());
ESP_LOGI(TAG, "I2C initialized successfully");
// Run bus scan
i2c_drv_scan();
#endif
#ifdef CONFIG_PCF8563
ESP_ERROR_CHECK(pcf8563_init());
#endif
#ifdef CONFIG_BMA423
ESP_ERROR_CHECK(bma423_init());
#endif
#ifdef CONFIG_FT636X
ESP_ERROR_CHECK(ft63x6_init());
#endif
#ifdef CONFIG_BHI260
ESP_ERROR_CHECK(bhi260_init());
#endif
#ifdef CONFIG_XL9555
xl9555_init();
#endif
ESP_LOGI(TAG, "Run...");
xTaskCreate(app_task, "App", 20 * 1024, NULL, 10, NULL);
}
static void app_task(void *args)
{
while (1) {
#ifdef CONFIG_BMA423
bma423_loop();
vTaskDelay(pdMS_TO_TICKS(1000));
#endif
#ifdef CONFIG_FT636X
ft63x6_loop();
#endif
#ifdef CONFIG_BHI260
bhi260_loop();
#endif
#ifdef CONFIG_XL9555
xl9555_loop();
#endif
vTaskDelay(pdMS_TO_TICKS(10));
}
}
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief hal_callback
* @note SensorLib hal callback
* @param op: Operation Code
* @param *param1: parameter
* @param *param2: parameter
* @retval
*/
uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2)
{
switch (op) {
// Set GPIO mode
case SensorCommCustomHal::OP_PINMODE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t mode = reinterpret_cast<uintptr_t>(param2);
gpio_config_t config;
memset(&config, 0, sizeof(config));
config.pin_bit_mask = 1ULL << pin;
switch (mode) {
case INPUT:
config.mode = GPIO_MODE_INPUT;
break;
case OUTPUT:
config.mode = GPIO_MODE_OUTPUT;
break;
}
config.pull_up_en = GPIO_PULLUP_DISABLE;
config.pull_down_en = GPIO_PULLDOWN_DISABLE;
config.intr_type = GPIO_INTR_DISABLE;
ESP_ERROR_CHECK(gpio_config(&config));
}
break;
// Set GPIO level
case SensorCommCustomHal::OP_DIGITALWRITE: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
uint8_t level = reinterpret_cast<uintptr_t>(param2);
gpio_set_level((gpio_num_t )pin, level);
}
break;
// Read GPIO level
case SensorCommCustomHal::OP_DIGITALREAD: {
uint8_t pin = reinterpret_cast<uintptr_t>(param1);
return gpio_get_level((gpio_num_t)pin);
}
break;
// Get the current running milliseconds
case SensorCommCustomHal::OP_MILLIS:
return (uint32_t) (esp_timer_get_time() / 1000LL);
// Delay in milliseconds
case SensorCommCustomHal::OP_DELAY: {
if (param1) {
uint32_t ms = reinterpret_cast<uintptr_t>(param1);
ets_delay_us((ms % portTICK_PERIOD_MS) * 1000UL);
}
}
break;
// Delay in microseconds
case SensorCommCustomHal::OP_DELAYMICROSECONDS: {
uint32_t us = reinterpret_cast<uintptr_t>(param1);
ets_delay_us(us);
}
break;
default:
break;
}
return 0;
}
#endif

View File

@ -0,0 +1,205 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file sensor_bhi260.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-23
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "SensorBHI260AP.hpp"
#if CONFIG_BHI260
static const char *TAG = "BHI";
extern uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2);
SensorBHI260AP bhy;
static volatile bool dataReady = false;
static bool init_done = false;
static void IRAM_ATTR bhi260_set_flag(void *arg)
{
dataReady = true;
}
static void bhi260_isr_init()
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_SENSOR_IRQ);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
gpio_set_intr_type((gpio_num_t)CONFIG_SENSOR_IRQ, GPIO_INTR_POSEDGE);
//install gpio isr service
gpio_install_isr_service(0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add((gpio_num_t)CONFIG_SENSOR_IRQ, bhi260_set_flag, NULL);
}
static void accel_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_xyz data;
float scaling_factor = get_sensor_default_scaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
ESP_LOGI(TAG, "%s: x: %f, y: %f, z: %f;", bhy.getSensorName(sensor_id),
data.x * scaling_factor,
data.y * scaling_factor,
data.z * scaling_factor);
}
static void gyro_process_callback(uint8_t sensor_id, uint8_t *data_ptr, uint32_t len, uint64_t *timestamp, void *user_data)
{
struct bhy2_data_xyz data;
float scaling_factor = get_sensor_default_scaling(sensor_id);
bhy2_parse_xyz(data_ptr, &data);
ESP_LOGI(TAG, "%s: x: %f, y: %f, z: %f;", bhy.getSensorName(sensor_id),
data.x * scaling_factor,
data.y * scaling_factor,
data.z * scaling_factor);
}
esp_err_t bhi260_init()
{
ESP_LOGI(TAG, "----DRIVER BHI260AP----");
// Set the reset pin
bhy.setPins(CONFIG_SENSOR_RST);
/*Set the default firmware, only 6 axes, no other functions*/
bhy.setFirmware(bhy2_firmware_image, sizeof(bhy2_firmware_image));
#if CONFIG_USE_I2C_INTERFACE
// BHI260AP_SLAVE_ADDRESS_L = 0x28
// BHI260AP_SLAVE_ADDRESS_H = 0x29
uint8_t address = BHI260AP_SLAVE_ADDRESS_L;
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (bhy.begin(i2c_wr_function, hal_callback, address)) {
ESP_LOGI(TAG, "Initialize BHI260AP using I2C interface");
} else {
ESP_LOGE(TAG, "Failed to initialize the BHI260AP !");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (bhy.begin(bus_handle, address)) {
ESP_LOGI(TAG, "Initialize BHI260AP using I2C interface");
} else {
ESP_LOGE(TAG, "Failed to initialize the BHI260AP !");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (bhy.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, address, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initialize BHI260AP using I2C interface");
} else {
ESP_LOGE(TAG, "Failed to initialize the BHI260AP !");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#else //USE_I2C_INTERFACE
// Bus handle
spi_device_handle_t spi = NULL;
// Using SPI interface
if (bhy.begin(SPI2_HOST, spi, CONFIG_SPI_CS, CONFIG_SPI_MOSI, CONFIG_SPI_MISO, CONFIG_SPI_SCK)) {
ESP_LOGI(TAG, "Initialize BHI260AP using SPI interface");
} else {
ESP_LOGE(TAG, "Failed to initialize the BHI260AP !");
return ESP_FAIL;
}
#endif //USE_SPI_INTERFACE
// Output all sensors info to Serial
BoschSensorInfo info = bhy.getSensorInfo();
info.printInfo();
float sample_rate = 1.0; /* Read out hintr_ctrl measured at 1Hz */
uint32_t report_latency_ms = 0; /* Report immediately */
// Enable acceleration
bhy.configure(SensorBHI260AP::ACCEL_PASSTHROUGH, sample_rate, report_latency_ms);
// Enable gyroscope
bhy.configure(SensorBHI260AP::GYRO_PASSTHROUGH, sample_rate, report_latency_ms);
// Set the acceleration sensor result callback function
bhy.onResultEvent(SensorBHI260AP::ACCEL_PASSTHROUGH, accel_process_callback);
// Set the gyroscope sensor result callback function
bhy.onResultEvent(SensorBHI260AP::GYRO_PASSTHROUGH, gyro_process_callback);
// Registration interruption
bhi260_isr_init();
init_done = true;
return ESP_OK;
}
void bhi260_loop()
{
if (!init_done) {
return;
}
if (dataReady) {
dataReady = false;
bhy.update();
}
}
#endif

View File

@ -0,0 +1,119 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file sensor_bma423.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#ifdef CONFIG_BMA423
#include "SensorBMA423.hpp"
static const char *TAG = "BMA";
SensorBMA423 accel;
extern uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2);
static bool init_done = false;
esp_err_t bma423_init()
{
uint8_t address = BMA423_I2C_ADDR_SECONDARY;
ESP_LOGI(TAG, "----DRIVER BMA423----");
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (accel.begin(i2c_wr_function, hal_callback, address)) {
ESP_LOGI(TAG, "Initialization of BMA423 accelerometer is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the BMA423 accelerometer!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (accel.begin(bus_handle, address)) {
ESP_LOGI(TAG, "Initialization of BMA423 accelerometer is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the BMA423 accelerometer!");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (accel.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, address, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initialization of BMA423 accelerometer is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the BMA423 accelerometer!");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
//Default 4G ,200HZ
accel.configAccelerometer();
accel.enableAccelerometer();
init_done = true;
return ESP_OK;
}
void bma423_loop()
{
if (!init_done) {
return;
}
ESP_LOGI("BMA423", "Temperature:%.2f*C", accel.getTemperature(SensorBMA423::TEMP_DEG));
ESP_LOGI("BMA423", "Temperature:%.2f*F", accel.getTemperature(SensorBMA423::TEMP_FAHRENHEIT));
ESP_LOGI("BMA423", "Direction:%u", accel.direction());
}
#endif

View File

@ -0,0 +1,137 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file sensor_pcf8563.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#ifdef CONFIG_PCF8563
#include "SensorPCF8563.hpp"
static const char *TAG = "RTC";
SensorPCF8563 rtc;
static bool init_done = false;
esp_err_t pcf8563_init()
{
ESP_LOGI(TAG, "----DRIVER PCF8563 ----");
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
uint8_t address = 0x51;
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (rtc.begin(i2c_wr_function)) {
ESP_LOGI(TAG, "Initializing PCF8563 real-time clock successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize PCF8563 real time clock!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (rtc.begin(bus_handle)) {
ESP_LOGI(TAG, "Initializing PCF8563 real-time clock successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize PCF8563 real time clock!");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (rtc.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initializing PCF8563 real-time clock successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize PCF8563 real time clock!");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
// Unix tm structure sets the time
struct tm timeinfo;
timeinfo.tm_yday = 2025 - 1900; //Counting starts from 1900, so subtract 1900 here
timeinfo.tm_mon = 1 - 1; //Months start at 0, so you need to subtract 1.
timeinfo.tm_mday = 17;
timeinfo.tm_hour = 4;
timeinfo.tm_min = 30;
timeinfo.tm_sec = 30;
rtc.setDateTime(timeinfo);
init_done = true;
return ESP_OK;
}
void pcf8563_loop()
{
if (!init_done) {
return;
}
char buf[64];
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
ESP_LOGI("RTC", "%s", buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
ESP_LOGI("RTC", "%s", buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
ESP_LOGI("RTC", "%s", buf);
}
}
#endif

View File

@ -0,0 +1,107 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file sensor_xl9555.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-23
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#ifdef CONFIG_XL9555
#include "ExtensionIOXL9555.hpp"
static const char *TAG = "XL9555";
ExtensionIOXL9555 io;
static bool init_done = false;
esp_err_t xl9555_init()
{
ESP_LOGI(TAG, "----DRIVER XL9555 ----");
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
uint8_t address = XL9555_SLAVE_ADDRESS0;
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (io.begin(i2c_wr_function)) {
ESP_LOGI(TAG, "Initializing XL9555 successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize XL9555 failed!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (io.begin(bus_handle)) {
ESP_LOGI(TAG, "Initializing XL9555 successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize XL9555 failed!");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (io.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initializing XL9555 successfully!");
} else {
ESP_LOGE(TAG, "Failed to initialize XL9555 failed!");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
return ESP_OK;
}
void xl9555_loop()
{
if (!init_done) {
return;
}
}
#endif

View File

@ -0,0 +1,116 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file ft63x6.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-19
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#ifdef CONFIG_FT636X
#include "TouchDrvFT6X36.hpp"
static const char *TAG = "FT63XX";
TouchDrvFT6X36 touch;
extern uint32_t hal_callback(SensorCommCustomHal::Operation op, void *param1, void *param2);
static bool init_done = false;
esp_err_t ft63x6_init()
{
ESP_LOGI(TAG, "----DRIVER FT63XX----");
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
uint8_t address = FT3267_SLAVE_ADDRESS;
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (touch.begin(i2c_wr_function, hal_callback, address)) {
ESP_LOGI(TAG, "Initialization of FT63XX is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the FT63XX!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (touch.begin(bus_handle)) {
ESP_LOGI(TAG, "Initialization of FT63XX is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the FT63XX!");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (touch.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initialization of FT63XX is successful!");
} else {
ESP_LOGE(TAG, "Failed to initialize the FT63XX!");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
init_done = true;
return ESP_OK;
}
void ft63x6_loop()
{
if (!init_done) {
return;
}
int16_t x[2], y[2];
uint8_t numPoint = touch.getPoint(x, y, 2);
for (int i = 0; i < numPoint; ++i) {
ESP_LOGI("FT63X6", "Point[%02d] - X:%02d Y:%02d", i, x[i], y[i]);
}
}
#endif

View File

@ -0,0 +1,9 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS ../../../SensorLib)
project(ESP_IDF_TouchDrvExample)

View File

@ -0,0 +1,10 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := ESP_IDF_TouchDrv_Example
EXTRA_COMPONENT_DIRS = ../../../SensorLib
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,154 @@
# ESP-IDF SensorLib TouchDrv examples
```bash
The current example only writes the CSTxxx series touch application.
```
## Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `SensorLib Example Configuration` menu:
* Select the communication method, will interface, callback interface, LL new version interface
1. Implemented using built-in read and write methods (Read and write methods are provided internally by SensorLib, supporting high version esp-idf >= 5.0, and low version methods (< 5.0))
2. Implemented using read and write callback methods (Implemented using externally provided methods, suitable for multiple platforms)
* In `Sensor SCL GPIO Num` select the clock pin to connect to the PMU,the default is 7
* In `Sensor SDA GPIO Num` select the data pin connected to the PMU,the default is 6
* Select the interrupt pin connected to the PMU in `Sensor Interrupt Pin`, the default is 8
* Select `Sensor reset Pin` , the default is 17
* `Master Frequency` The maximum communication frequency defaults to 100000HZ, and you can decide whether to change it according to the situation.
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`. default use **esp32s3**
## Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
The output information is to configure the output voltage and enable status of the PMU
```bash
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2810,len:0x178c
load:0x403c8700,len:0x4
load:0x403c8704,len:0xc10
load:0x403cb700,len:0x2dac
entry 0x403c8904
I (26) boot: ESP-IDF v5.3-beta1-105-g3f632df143-dirt 2nd stage bootloader
I (27) boot: compile time Jan 23 2025 16:49:34
I (27) boot: Multicore bootloader
I (27) boot: chip revision: v0.2
I (27) boot.esp32s3: Boot SPI Speed : 80MHz
I (28) boot.esp32s3: SPI Mode : DIO
I (28) boot.esp32s3: SPI Flash Size : 2MB
I (28) boot: Enabling RNG early entropy source...
I (28) boot: Partition Table:
I (28) boot: ## Label Usage Type ST Offset Length
I (29) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (29) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (30) boot: 2 factory factory app 00 00 00010000 00100000
I (30) boot: End of partition table
I (30) esp_image: segment 0: paddr=00010020 vaddr=3c030020 size=0ca94h ( 51860) map
I (40) esp_image: segment 1: paddr=0001cabc vaddr=3fc92e00 size=02a38h ( 10808) load
I (43) esp_image: segment 2: paddr=0001f4fc vaddr=40374000 size=00b1ch ( 2844) load
I (44) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=21020h (135200) map
I (69) esp_image: segment 4: paddr=00041048 vaddr=40374b1c size=0e254h ( 57940) load
I (88) boot: Loaded app from partition at offset 0x10000
I (88) boot: Disabling RNG early entropy source...
I (88) cpu_start: Multicore app
I (98) cpu_start: Pro cpu start user code
I (98) cpu_start: cpu freq: 240000000 Hz
I (98) app_init: Application information:
I (98) app_init: Project name: ESP_IDF_TouchDrvExample
I (98) app_init: App version: v0.2.5-8-gde9a1d2-dirty
I (99) app_init: Compile time: Jan 23 2025 16:51:47
I (99) app_init: ELF file SHA256: 179a53fa8...
I (99) app_init: ESP-IDF: v5.3-beta1-105-g3f632df143-dirt
I (99) efuse_init: Min chip rev: v0.0
I (99) efuse_init: Max chip rev: v0.99
I (100) efuse_init: Chip rev: v0.2
I (100) heap_init: Initializing. RAM available for dynamic allocation:
I (100) heap_init: At 3FC96158 len 000535B8 (333 KiB): RAM
I (100) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (101) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (101) heap_init: At 600FE100 len 00001EE8 (7 KiB): RTCRAM
I (102) spi_flash: detected chip: winbond
I (102) spi_flash: flash io: dio
W (102) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (103) sleep: Configure to isolate all GPIO pins in sleep state
I (103) sleep: Enable automatic switching of GPIO sleep configuration
I (104) main_task: Started on CPU0
I (114) main_task: Calling app_main()
I (114) I2C: Implemented using read and write callback methods (Use higher version >= 5.0 API)
I (114) gpio: GPIO[6]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (114) gpio: GPIO[7]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (114) main: I2C initialized successfully
I (114) TOUCH: ----SensorLib TouchDrv Examples----
Scand I2C Devices:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- 5a -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- 6a -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (224) TOUCH: Find touch address 0x5A
I (224) TOUCH: Implemented using built-in read and write methods (Use higher version >= 5.0 API)
I (224) SensorLib: Using ESP-IDF Driver interface.
I (224) SensorLib: Added Device Address : 0x5A New Dev Address: 0x3fc9a3a0 Speed :400000
I (224) TOUCH: Initializing the capacitive touch screen successfully
I (224) TOUCH: Using CST226SE model
I (224) gpio: GPIO[8]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (224) main: Run...
I (224) main_task: Returned from app_main()
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
X[0]:143 Y[0]:167
```
## Build process example
Assuming you don't have esp-idf yet
```bash
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
git clone https://github.com/lewisxhe/SensorLib.git
cd esp-idf
./install.sh
. ./export.sh
cd ..
cd SensorLib/examples/ESP_IDF_TouchDrvExample
Configure SDA,SCL,INT,RST,Pin
...
idf.py menuconfig
idf.py build
idf.py -b 921600 flash
idf.py monitor
```

View File

@ -0,0 +1,5 @@
idf_component_register(SRCS
"touch_drv.cpp"
"i2c_driver.cpp"
"main.cpp"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,52 @@
menu "SensorLib Example Configuration"
choice I2C_COMMUNICATION_METHOD
prompt "SensorLib read and write methods"
default I2C_COMMUNICATION_METHOD_BUILTIN_RW
help
Define SensorLib read and write methods
config I2C_COMMUNICATION_METHOD_BUILTIN_RW
bool "Implemented using built-in read and write methods"
config I2C_COMMUNICATION_METHOD_CALLBACK_RW
bool "Implemented using read and write callback methods"
endchoice
config I2C_MASTER_PORT_NUM
int "Sensor I2C Port Number"
default 1
help
Port number for I2C Master device.
config I2C_MASTER_FREQUENCY
int "Master Frequency"
default 100000
help
I2C Speed of Master device.
config SENSOR_SCL
int "Sensor SCL GPIO Num"
default 7
help
GPIO number for I2C clock line.
config SENSOR_SDA
int "Sensor SDA GPIO Num"
default 6
help
GPIO number for I2C data line.
config SENSOR_IRQ
int "Sensor Interrupt Pin"
default 8
help
Sensor interrupt pin.
config SENSOR_RST
int "Sensor reset Pin"
default 17
help
Sensor reset pin.
endmenu

View File

@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -0,0 +1,275 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file port_i2c.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "i2c_driver.h"
static const char *TAG = "I2C";
#define I2C_MASTER_NUM (i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM
#define I2C_MASTER_SDA_IO (gpio_num_t)CONFIG_SENSOR_SDA
#define I2C_MASTER_SCL_IO (gpio_num_t)CONFIG_SENSOR_SCL
#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "soc/clk_tree_defs.h"
i2c_master_dev_handle_t i2c_device;
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
i2c_master_bus_handle_t bus_handle;
#endif
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief Read a sequence of bytes from a pmu registers
*/
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (len == 0) {
return ESP_OK;
}
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ret = i2c_master_transmit_receive(
i2c_device,
(const uint8_t *)&regAddr,
1,
data,
len,
-1);
#else
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "PMU i2c_master_cmd_begin FAILED! > ");
return ESP_FAIL;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, true);
if (len > 1) {
i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, &data[len - 1], I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_read_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
/**
* @brief Write a byte to a pmu register
*/
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1));
if (!write_buffer) {
return -1;
}
write_buffer[0] = regAddr;
memcpy(write_buffer + 1, data, len);
ret = i2c_master_transmit(
i2c_device,
write_buffer,
len + 1,
-1);
free(write_buffer);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, regAddr, true);
i2c_master_write(cmd, data, len, true);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "i2c_write_error.");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
esp_err_t i2c_drv_device_init(uint8_t address)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
i2c_device_config_t i2c_dev_conf = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = address,
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
};
return i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &i2c_device);
#else
return ESP_OK;
#endif
}
#endif //CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
/**
* @brief i2c master initialization
*/
esp_err_t i2c_drv_init(void)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use higher version >= 5.0 API)");
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = I2C_MASTER_NUM;
i2c_bus_config.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO;
i2c_bus_config.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO;
i2c_bus_config.glitch_ignore_cnt = 7;
i2c_bus_config.flags.enable_internal_pullup = true;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
return ESP_OK;
#else
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use lower version < 5.0 API)");
i2c_config_t i2c_conf ;
memset(&i2c_conf, 0, sizeof(i2c_conf));
i2c_conf.mode = I2C_MODE_MASTER;
i2c_conf.sda_io_num = I2C_MASTER_SDA_IO;
i2c_conf.scl_io_num = I2C_MASTER_SCL_IO;
i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(I2C_MASTER_NUM, &i2c_conf);
return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
#endif
}
void i2c_drv_scan()
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
esp_err_t err = ESP_OK;
uint8_t address = 0x00;
printf("Scand I2C Devices:\n");
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
err = i2c_master_probe(bus_handle, address, 1000);
if (err == ESP_OK) {
printf("%02x ", address);
} else if (err == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
printf("\n\n\n");
#else
uint8_t address;
printf("Scand I2C Devices:\n");
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for (int j = 0; j < 16; j++) {
fflush(stdout);
address = i + j;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (ret == ESP_OK) {
printf("%02x ", address);
} else if (ret == ESP_ERR_TIMEOUT) {
printf("UU ");
} else {
printf("-- ");
}
}
printf("\r\n");
}
#endif
}
bool i2c_drv_probe(uint8_t devAddr)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
return ESP_OK == i2c_master_probe(bus_handle, devAddr, 1000);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 50 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return (ret == ESP_OK);
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
}

View File

@ -0,0 +1,53 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file i2c_driver.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#pragma once
#include "esp_err.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
#include "driver/i2c_master.h"
#else
#include "driver/i2c.h"
#endif //ESP_IDF_VERSION
esp_err_t i2c_drv_init(void);
void i2c_drv_scan();
bool i2c_drv_probe(uint8_t devAddr);
int i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
int i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
esp_err_t i2c_drv_device_init(uint8_t address);
#endif

View File

@ -0,0 +1,67 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file main.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "freertos/queue.h"
#include "i2c_driver.h"
static const char *TAG = "main";
extern esp_err_t sensor_drv_init();
extern esp_err_t touch_drv_init();
extern void touch_loop();
static void touch_task(void *);
extern "C" void app_main(void)
{
ESP_ERROR_CHECK(i2c_drv_init());
ESP_LOGI(TAG, "I2C initialized successfully");
ESP_ERROR_CHECK(touch_drv_init());
xTaskCreate(touch_task, "touch", 4 * 1024, NULL, 10, NULL);
ESP_LOGI(TAG, "Run...");
}
static void touch_task(void *args)
{
while (1) {
touch_loop();
// vTaskDelay(pdMS_TO_TICKS(10));
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}

View File

@ -0,0 +1,227 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file touch_drv.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "i2c_driver.h"
#include "freertos/FreeRTOS.h"
#include "TouchDrvCSTXXX.hpp"
static const char *TAG = "TOUCH";
#define SENSOR_INPUT_PIN (gpio_num_t)CONFIG_SENSOR_IRQ
#define SENSOR_INPUT_PIN_SEL (1ULL<<SENSOR_INPUT_PIN)
TouchDrvCSTXXX touch;
static QueueHandle_t xQueue;
static void touch_home_button_callback(void *user_data)
{
ESP_LOGI(TAG, "Touch Home button pressed!");
}
static void IRAM_ATTR sensor_irq_handler(void *arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(xQueue, &gpio_num, NULL);
}
static void irq_init()
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = SENSOR_INPUT_PIN_SEL;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
// gpio_set_intr_type(SENSOR_INPUT_PIN, GPIO_INTR_NEGEDGE);
// //install gpio isr service
// gpio_install_isr_service(0);
// //hook isr handler for specific gpio pin
// gpio_isr_handler_add(SENSOR_INPUT_PIN, sensor_irq_handler, (void *) SENSOR_INPUT_PIN);
}
esp_err_t touch_drv_init()
{
uint8_t address = 0xFF;
ESP_LOGI(TAG, "----SensorLib TouchDrv Examples----");
/*
* CST816, CST328 Some chips have automatic sleep function.
* If you want to scan the device address,
* must reset the chip first. If the reset pin is not connected,
* you may not be able to obtain the device address by scanning the bus.
*/
gpio_num_t gpio_num = (gpio_num_t)CONFIG_SENSOR_RST;
ESP_ERROR_CHECK(gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT));
gpio_set_level(gpio_num, 0);
vTaskDelay(pdMS_TO_TICKS(15));
gpio_set_level(gpio_num, 1);
vTaskDelay(pdMS_TO_TICKS(80));
// Run bus scan
i2c_drv_scan();
// Get known address
if (i2c_drv_probe(CST816_SLAVE_ADDRESS)) {
address = CST816_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
} else if (i2c_drv_probe(CST226SE_SLAVE_ADDRESS)) {
address = CST226SE_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
} else if (i2c_drv_probe(CST328_SLAVE_ADDRESS)) {
address = CST328_SLAVE_ADDRESS;
ESP_LOGI(TAG, "Find touch address 0x%X", address);
}
if (address == 0xFF) {
ESP_LOGE(TAG, "Could't find touch chip!");
return ESP_FAIL;
}
// Set reset and interrupt pin
touch.setPins(CONFIG_SENSOR_RST, CONFIG_SENSOR_IRQ);
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
// * Provide the device address to the callback function
i2c_drv_device_init(address);
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (touch.begin(address, i2c_read_callback, i2c_write_callback)) {
ESP_LOGI(TAG, "Initializing the capacitive touch screen successfully");
} else {
ESP_LOGE(TAG, "Failed to initialize the capacitive touch screen");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_SENSORLIB_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (touch.begin(bus_handle, address)) {
ESP_LOGI(TAG, "Initializing the capacitive touch screen successfully");
} else {
ESP_LOGE(TAG, "Failed to initialize the capacitive touch screen");
return ESP_FAIL;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (touch.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, address, CONFIG_SENSOR_SDA, CONFIG_SENSOR_SCL)) {
ESP_LOGI(TAG, "Initializing the capacitive touch screen successfully");
} else {
ESP_LOGE(TAG, "Failed to initialize the capacitive touch screen");
return ESP_FAIL;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
const char *model = touch.getModelName();
ESP_LOGI(TAG, "Using %s model", model);
if (strncmp(model, "CST8", 4) == 0) {
ESP_LOGI(TAG, "Some CST816 will automatically enter sleep,can use the touch.disableAutoSleep() to turn off");
// Some CST816 will automatically enter sleep,
// can use the touch.disableAutoSleep() to turn off
touch.disableAutoSleep();
/**
* Some touch screens have touch buttons,
* and the touch coordinates need to be given
* before the touch button callback function can be used.
*/
// Example touch coordinates using T-Display-S3 touch
touch.setCenterButtonCoordinate(85, 360);
touch.setHomeButtonCallback(touch_home_button_callback);
}
// Set the maximum valid coordinates
// touch.setMaxCoordinates(320, 170);
// Swap XY coordinates
// touch.setSwapXY(true);
// Mirror XY coordinates
// touch.setMirrorXY(false, true);
// Create a queue to handle gpio event from isr
xQueue = xQueueCreate(5, sizeof(uint32_t));
// Register Sensor interrupt pins
irq_init();
return ESP_OK;
}
void touch_drv_isr_handler()
{
int16_t x[5], y[5];
uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());
if (touched) {
for (int i = 0; i < touched; ++i) {
printf("X[");
printf("%d", i);
printf("]:");
printf("%d", x[i]);
printf(" ");
printf(" Y[");
printf("%d", i);
printf("]:");
printf("%d", y[i]);
printf(" ");
}
printf("\n");
}
}
void touch_loop()
{
uint32_t io_num;
// if (xQueueReceive(xQueue, &io_num, pdMS_TO_TICKS(10))) {
// if (gpio_get_level((gpio_num_t)CONFIG_SENSOR_IRQ) == 0) {
touch_drv_isr_handler();
// }
// }
}

View File

@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240

View File

@ -0,0 +1,193 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file LTR553ALS_Sensor.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorLTR553.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 5
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 6
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 21
#endif
SensorLTR553 als;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!als.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find LTR553 - check your wiring!");
while (1) {
delay(1000);
}
}
Serial.println("Init LTR553 Sensor success!");
// Set the ambient light high and low thresholds.
// If the value exceeds or falls below the set value, an interrupt will be triggered.
als.setLightSensorThreshold(10, 200);
// Set the high and low thresholds of the proximity sensor.
// If the value exceeds or falls below the set value, an interrupt will be triggered.
als.setProximityThreshold(10, 30);
// Controls the Light Sensor N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
als.setLightSensorPersists(5);
// Controls the Proximity N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
als.setProximityPersists(5);
/*
* ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default)
* ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1
* * */
als.setIRQLevel(SensorLTR553::ALS_IRQ_ACTIVE_LOW);
/*
* ALS_IRQ_ONLY_PS, // Only PS measurement can trigger interrupt
* ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt
* ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt
* * * */
als.enableIRQ(SensorLTR553::ALS_IRQ_BOTH);
/*
* ALS_GAIN_1X , -> 1 lux to 64k lux (default)
* ALS_GAIN_2X , -> 0.5 lux to 32k lux
* ALS_GAIN_4X , -> 0.25 lux to 16k lux
* ALS_GAIN_8X , -> 0.125 lux to 8k lux
* ALS_GAIN_48X , -> 0.02 lux to 1.3k lux
* ALS_GAIN_96X , -> 0.01 lux to 600 lux
* */
als.setLightSensorGain(SensorLTR553::ALS_GAIN_8X);
/*
* PS_LED_PLUSE_30KHZ,
* PS_LED_PLUSE_40KHZ,
* PS_LED_PLUSE_50KHZ,
* PS_LED_PLUSE_60KHZ,
* PS_LED_PLUSE_70KHZ,
* PS_LED_PLUSE_80KHZ,
* PS_LED_PLUSE_90KHZ,
* PS_LED_PLUSE_100KHZ,
* * * * * * * * * * */
als.setPsLedPulsePeriod(SensorLTR553::PS_LED_PLUSE_100KHZ);
/*
* PS_LED_DUTY_25,
* PS_LED_DUTY_50,
* PS_LED_DUTY_75,
* PS_LED_DUTY_100,
* * * */
als.setPsLedDutyCycle(SensorLTR553::PS_LED_DUTY_100);
/*
* PS_LED_CUR_5MA,
* PS_LED_CUR_10MA,
* PS_LED_CUR_20MA,
* PS_LED_CUR_50MA,
* PS_LED_CUR_100MA,
* * * * * * * */
als.setPsLedCurrent(SensorLTR553::PS_LED_CUR_50MA);
/*
* PS_MEAS_RATE_50MS,
* PS_MEAS_RATE_70MS,
* PS_MEAS_RATE_100MS,
* PS_MEAS_RATE_200MS,
* PS_MEAS_RATE_500MS,
* PS_MEAS_RATE_1000MS,
* PS_MEAS_RATE_2000MS,
* PS_MEAS_RATE_10MS
* * * * * * * */
als.setProximityRate(SensorLTR553::PS_MEAS_RATE_200MS);
// Number of pulses
als.setPsLedPulses(1);
// Enable proximity sensor saturation indication
als.enablePsIndicator();
// Enable ambient light sensor
als.enableLightSensor();
// Enable proximity sensor
als.enableProximity();
}
bool canRead()
{
#if SENSOR_IRQ != -1
return digitalRead(SENSOR_IRQ) == LOW;
#else
static uint32_t lastReadMillis;
if (millis() > lastReadMillis) {
lastReadMillis = millis() + 500;
return true;
}
return false;
#endif
}
void loop()
{
/*
* PS Saturation Flag is used for monitoring the internal IC saturation.
* It will be flagged when the IC has reached saturation
* and not able to perform any further PS measurement
* */
bool saturated = false;
if (canRead()) {
Serial.print(" ALS: CH1:"); Serial.print(als.getLightSensor(1));
Serial.print(" - CH0:"); Serial.print(als.getLightSensor(0));
Serial.print(" - PS:"); Serial.print(als.getProximity(&saturated));
Serial.print(" - "); Serial.println(saturated ? "PS saturated" : "PS not saturated");
}
delay(5);
}

View File

@ -0,0 +1,214 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF85063_AlarmByUnits.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-12-11
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "SensorPCF85063.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 4
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 5
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
SensorPCF85063 rtc;
uint32_t intervalue = 0;
uint8_t nextHour = 22;
uint8_t nextMonth = 1;
uint8_t nextDay = 1;
uint8_t nextMinute = 59;
uint8_t nextSecond = 20;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF85063 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextSecond = 55;
// First test alarm seconds
rtc.setAlarmBySecond(30);
rtc.enableAlarm();
}
void printDateTime()
{
if (millis() - intervalue > 1000) {
/**
/// Format output time*
Option:
DT_FMT_HM, // Format Style : Hour:Minute
DT_FMT_HMS, // Format Style : Hour:Minute:Second
DT_FMT_YMD, // Format Style : Year-Month-Day
DT_FMT_MDY, // Format Style : Month-Day-Year
DT_FMT_DMY, // Format Style : Day-Month-Year
DT_FMT_YMD_HMS, // Format Style : Year-Month-Day/Hour:Minute:Second
Default : DT_FMT_YMD_HMS_WEEK // Format Style : Year-Month-Day/Hour:Minute:Second - Weekday
*/
Serial.println(rtc.strftime());
intervalue = millis();
}
}
// Test seconds timing
void testAlarmSeconds()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmSeconds Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByMinutes(0);
return;
}
}
printDateTime();
}
}
// Test minute timing
void testAlarmMinute()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmMinute Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextHour++;
if (nextHour >= 24) {
nextHour = 23;
nextDay = 25;
rtc.setAlarmByHours(0);
Serial.println("setAlarmByHours");
return;
}
}
}
printDateTime();
}
}
// Test hour timing
void testAlarmHour()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmHour Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextDay++;
if (nextDay >= 30) {
nextMonth = 1;
nextHour = 23;
nextMinute = 59;
nextSecond = 55;
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByDays(1);
Serial.println("setAlarmByDays");
return;
}
}
}
printDateTime();
}
}
// Test day timing
void testAlarmDay()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmDay Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextMonth++;
if (nextMonth >= 12) {
return;
}
}
}
printDateTime();
}
}
void loop()
{
testAlarmSeconds();
testAlarmMinute();
testAlarmHour();
testAlarmDay();
Serial.println("Test done ...");
while (1) {
delay(100);
}
}

View File

@ -0,0 +1,101 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF85063_ClockOutput.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-07-24
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF85063.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 7
#endif
SensorPCF85063::ClockHz clock_array[] = {
SensorPCF85063::CLK_32768HZ,
SensorPCF85063::CLK_16384HZ,
SensorPCF85063::CLK_8192HZ,
SensorPCF85063::CLK_4096HZ,
SensorPCF85063::CLK_2048HZ,
SensorPCF85063::CLK_1024HZ,
SensorPCF85063::CLK_1HZ,
SensorPCF85063::CLK_LOW,
};
String freq_hz_str[] = {
"32.768KHZ",
"16.384KHZ",
"8.192KHZ",
"4.096KHZ",
"2.048KHZ",
"1.024KHZ",
"1HZ",
"LOW"
};
SensorPCF85063 rtc;
uint32_t intervalue;
uint8_t i = 0;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF85063 - check your wiring!");
while (1) {
delay(1000);
}
}
}
void loop()
{
if (millis() - intervalue > 5000) {
intervalue = millis();
Serial.print("Set freq : ");
Serial.println(freq_hz_str[i]);
rtc.setClockOutput(clock_array[i]);
i++;
i %= 8;
}
}

View File

@ -0,0 +1,184 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF85063_SimpleTime.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorPCF85063.hpp>
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 7
#endif
SensorPCF85063 rtc;
uint32_t interval = 0;
uint32_t loopCount = 0;
void printInt(int val)
{
if (val < 10) {
Serial.print("0");
}
Serial.print(val);
}
void setup()
{
Serial.begin(115200);
// Wait for the serial port to be ready
while (!Serial);
// Try to initialize the RTC module using I2C with specified SDA and SCL pins
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF85063 - check your wiring!");
// Enter an infinite loop to halt the program
while (1) {
delay(1000);
}
}
uint16_t year = 2023;
uint8_t month = 9;
uint8_t day = 7;
uint8_t hour = 11;
uint8_t minute = 24;
uint8_t second = 30;
// Set the defined date and time on the RTC
rtc.setDateTime(year, month, day, hour, minute, second);
if (!rtc.isClockIntegrityGuaranteed()) {
Serial.println("[ERROR]:Clock integrity is not guaranteed; oscillator has stopped or has been interrupted");
}
}
void loop()
{
// Check if one second has passed since the last update
if (millis() > interval) {
// Update the interval to the current time
interval = millis() + 1000;
// Retrieve the current date and time from the RTC
RTC_DateTime datetime = rtc.getDateTime();
Serial.print("[RTC ]:");
Serial.print(" Year :"); printInt(datetime.getYear());
Serial.print(" Month:"); printInt(datetime.getMonth());
Serial.print(" Day :"); printInt(datetime.getDay());
Serial.print(" Hour:"); printInt(datetime.getHour());
Serial.print(" Minute:"); printInt(datetime.getMinute());
Serial.print(" Sec :"); printInt(datetime.getSecond());
Serial.println();
// Convert the RTC date and time to Unix time
struct tm info = datetime.toUnixTime();
Serial.print("[UNIX]:");
Serial.print(" Year :"); printInt(info.tm_year + 1900); // tm_year starts counting from 1900
Serial.print(" Month:"); printInt(info.tm_mon + 1); // tm_mon range is 0 - 11, 0 means January
Serial.print(" Day :"); printInt(info.tm_mday);
Serial.print(" Hour:"); printInt(info.tm_hour);
Serial.print(" Minute:"); printInt(info.tm_min);
Serial.print(" Sec :"); printInt(info.tm_sec);
Serial.println();
// Set a new Unix time at the 10th loop iteration
if (loopCount == 10) {
Serial.print("Set Unix Time:");
Serial.println();
Serial.println();
struct tm utc_tm;
utc_tm.tm_year = 2025 - 1900; // tm_year starts counting from 1900
utc_tm.tm_mon = 0; // tm_mon range is 0 - 11, 0 means January
utc_tm.tm_mday = 23;
utc_tm.tm_hour = 7;
utc_tm.tm_min = 1;
utc_tm.tm_sec = 28;
rtc.setDateTime(utc_tm);
}
// Set a UTC time with a time zone offset of 8 hours at the 20th loop iteration
if (loopCount == 20) {
Serial.print("Set UTC time to time zone offset 8 hours:");
Serial.println();
Serial.println();
struct tm utc_tm;
utc_tm.tm_year = 2025 - 1900; // tm_year starts counting from 1900
utc_tm.tm_mon = 0; // tm_mon range is 0 - 11, 0 means January
utc_tm.tm_mday = 23;
utc_tm.tm_hour = 7;
utc_tm.tm_min = 1;
utc_tm.tm_sec = 28;
rtc.convertUtcToTimezone(utc_tm, 8 * 3600);
rtc.setDateTime(utc_tm);
}
if (loopCount > 30) {
char buf[64];
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
}
++loopCount;
}
}

View File

@ -0,0 +1,191 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563_AlarmByUnits.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-11
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <time.h>
#include "SensorPCF8563.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 42
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 41
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
SensorPCF8563 rtc;
uint32_t intervalue = 0;
uint8_t nextHour = 22;
uint8_t nextMonth = 1;
uint8_t nextDay = 1;
uint8_t nextMinute = 59;
uint8_t nextSecond = 55;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
pinMode(SENSOR_IRQ, INPUT_PULLUP);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
// From minute timer
rtc.setAlarmByMinutes(0);
rtc.enableAlarm();
}
void printDateTime()
{
if (millis() - intervalue > 1000) {
/**
/// Format output time*
Option:
DT_FMT_HM, // Format Style : Hour:Minute
DT_FMT_HMS, // Format Style : Hour:Minute:Second
DT_FMT_YMD, // Format Style : Year-Month-Day
DT_FMT_MDY, // Format Style : Month-Day-Year
DT_FMT_DMY, // Format Style : Day-Month-Year
DT_FMT_YMD_HMS, // Format Style : Year-Month-Day/Hour:Minute:Second
Default : DT_FMT_YMD_HMS_WEEK // Format Style : Year-Month-Day/Hour:Minute:Second - Weekday
*/
Serial.println(rtc.strftime());
intervalue = millis();
}
}
// Test minute timing
void testAlarmMinute()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmMinute Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextHour++;
if (nextHour >= 24) {
nextHour = 23;
nextDay = 25;
rtc.setAlarmByHours(0);
Serial.println("setAlarmByHours");
return;
}
}
}
printDateTime();
}
}
// Test hour timing
void testAlarmHour()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmHour Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextDay++;
if (nextDay >= 30) {
nextMonth = 1;
nextHour = 23;
nextMinute = 59;
nextSecond = 55;
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
rtc.setAlarmByDays(1);
Serial.println("setAlarmByDays");
return;
}
}
}
printDateTime();
}
}
// Test day timing
void testAlarmDay()
{
while (1) {
if (digitalRead(SENSOR_IRQ) == LOW) {
Serial.println("testAlarmDay Interrupt .... ");
if (rtc.isAlarmActive()) {
Serial.println("Alarm active");
rtc.resetAlarm();
nextDay = rtc.getDaysInMonth(nextMonth, 2022);
rtc.setDateTime(2022, nextMonth, nextDay, nextHour, nextMinute, nextSecond);
nextMonth++;
if (nextMonth >= 12) {
return;
}
}
}
printDateTime();
}
}
void loop()
{
testAlarmMinute();
testAlarmHour();
testAlarmDay();
Serial.println("Test done ...");
while (1) {
delay(100);
}
}

View File

@ -0,0 +1,95 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563_ClockOutput.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF8563.hpp"
#ifndef SENSOR_SDA
#define SENSOR_SDA 42
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 41
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
SensorPCF8563::ClockHz clock_array[] = {
SensorPCF8563::CLK_32768HZ,
SensorPCF8563::CLK_1024HZ,
SensorPCF8563::CLK_32HZ,
SensorPCF8563::CLK_1HZ,
SensorPCF8563::CLK_DISABLE,
};
String freq_hz_str[] = {
"32.768KHZ",
"1.024KHZ",
"32HZ",
"1HZ",
"DISABLE",
};
SensorPCF8563 rtc;
uint32_t intervalue;
uint8_t i = 0;
void setup()
{
Serial.begin(115200);
while (!Serial);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
}
void loop()
{
if (millis() - intervalue > 5000) {
intervalue = millis();
Serial.print("Set freq : ");
Serial.println(freq_hz_str[i]);
rtc.setClockOutput(clock_array[i]);
i++;
i %= 5;
}
}

View File

@ -0,0 +1,184 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563_SimpleTime.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include <SensorPCF8563.hpp>
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 7
#endif
SensorPCF8563 rtc;
uint32_t interval = 0;
uint32_t loopCount = 0;
void printInt(int val)
{
if (val < 10) {
Serial.print("0");
}
Serial.print(val);
}
void setup()
{
Serial.begin(115200);
// Wait for the serial port to be ready
while (!Serial);
// Try to initialize the RTC module using I2C with specified SDA and SCL pins
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF85063 - check your wiring!");
// Enter an infinite loop to halt the program
while (1) {
delay(1000);
}
}
uint16_t year = 2023;
uint8_t month = 9;
uint8_t day = 7;
uint8_t hour = 11;
uint8_t minute = 24;
uint8_t second = 30;
// Set the defined date and time on the RTC
rtc.setDateTime(year, month, day, hour, minute, second);
if (!rtc.isClockIntegrityGuaranteed()) {
Serial.println("[ERROR]:Clock integrity is not guaranteed; oscillator has stopped or has been interrupted");
}
}
void loop()
{
// Check if one second has passed since the last update
if (millis() > interval) {
// Update the interval to the current time
interval = millis() + 1000;
// Retrieve the current date and time from the RTC
RTC_DateTime datetime = rtc.getDateTime();
Serial.print("[RTC ]:");
Serial.print(" Year :"); printInt(datetime.getYear());
Serial.print(" Month:"); printInt(datetime.getMonth());
Serial.print(" Day :"); printInt(datetime.getDay());
Serial.print(" Hour:"); printInt(datetime.getHour());
Serial.print(" Minute:"); printInt(datetime.getMinute());
Serial.print(" Sec :"); printInt(datetime.getSecond());
Serial.println();
// Convert the RTC date and time to Unix time
struct tm info = datetime.toUnixTime();
Serial.print("[UNIX]:");
Serial.print(" Year :"); printInt(info.tm_year + 1900); // tm_year starts counting from 1900
Serial.print(" Month:"); printInt(info.tm_mon + 1); // tm_mon range is 0 - 11, 0 means January
Serial.print(" Day :"); printInt(info.tm_mday);
Serial.print(" Hour:"); printInt(info.tm_hour);
Serial.print(" Minute:"); printInt(info.tm_min);
Serial.print(" Sec :"); printInt(info.tm_sec);
Serial.println();
// Set a new Unix time at the 10th loop iteration
if (loopCount == 10) {
Serial.print("Set Unix Time:");
Serial.println();
Serial.println();
struct tm utc_tm;
utc_tm.tm_year = 2025 - 1900; // tm_year starts counting from 1900
utc_tm.tm_mon = 0; // tm_mon range is 0 - 11, 0 means January
utc_tm.tm_mday = 23;
utc_tm.tm_hour = 7;
utc_tm.tm_min = 1;
utc_tm.tm_sec = 28;
rtc.setDateTime(utc_tm);
}
// Set a UTC time with a time zone offset of 8 hours at the 20th loop iteration
if (loopCount == 20) {
Serial.print("Set UTC time to time zone offset 8 hours:");
Serial.println();
Serial.println();
struct tm utc_tm;
utc_tm.tm_year = 2025 - 1900; // tm_year starts counting from 1900
utc_tm.tm_mon = 0; // tm_mon range is 0 - 11, 0 means January
utc_tm.tm_mday = 23;
utc_tm.tm_hour = 7;
utc_tm.tm_min = 1;
utc_tm.tm_sec = 28;
rtc.convertUtcToTimezone(utc_tm, 8 * 3600);
rtc.setDateTime(utc_tm);
}
if (loopCount > 30) {
char buf[64];
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
}
++loopCount;
}
}

View File

@ -0,0 +1,115 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563_TimeLib.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorPCF8563.hpp"
#include <time.h>
#ifndef SENSOR_SDA
#define SENSOR_SDA 42
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 41
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
SensorPCF8563 rtc;
uint32_t intervalue;
char buf[64];
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
// The simplest way to set up
rtc.setDateTime(2024, 1, 17, 4, 21, 30);
// Unix tm structure sets the time
struct tm timeinfo;
timeinfo.tm_yday = 2025 - 1900; //Counting starts from 1900, so subtract 1900 here
timeinfo.tm_mon = 1 - 1; //Months start at 0, so you need to subtract 1.
timeinfo.tm_mday = 17;
timeinfo.tm_hour = 4;
timeinfo.tm_min = 30;
timeinfo.tm_sec = 30;
rtc.setDateTime(timeinfo);
}
void loop()
{
if (millis() - intervalue > 1000) {
intervalue = millis();
struct tm timeinfo;
// Get the time C library structure
rtc.getDateTime(&timeinfo);
// Format the output using the strftime function
// For more formats, please refer to :
// https://man7.org/linux/man-pages/man3/strftime.3.html
size_t written = strftime(buf, 64, "%A, %B %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%b %d %Y %H:%M:%S", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
written = strftime(buf, 64, "%A, %d. %B %Y %I:%M%p", &timeinfo);
if (written != 0) {
Serial.println(buf);
}
}
}

View File

@ -0,0 +1,167 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563_TimeSynchronization.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-12
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP32)
#include <time.h>
#include <WiFi.h>
#include <esp_sntp.h>
#include <SensorPCF8563.hpp>
#ifndef SENSOR_SDA
#define SENSOR_SDA 42
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 41
#endif
#ifndef SENSOR_IRQ
#define SENSOR_IRQ 14
#endif
const char *ssid = "YOUR_SSID";
const char *password = "YOUR_PASS";
const char *ntpServer1 = "pool.ntp.org";
const char *ntpServer2 = "time.nist.gov";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
const char *time_zone = "CST-8"; // TimeZone rule for Europe/Rome including daylight adjustment rules (optional)
SensorPCF8563 rtc;
uint32_t intervalue;
// Callback function (get's called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
Serial.println("Got time adjustment from NTP, Write the hardware clock");
// Write synchronization time to hardware
rtc.hwClockWrite();
}
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(SENSOR_IRQ, INPUT_PULLUP);
if (!rtc.begin(Wire, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find PCF8563 - check your wiring!");
while (1) {
delay(1000);
}
}
// set notification call-back function
sntp_set_time_sync_notification_cb( timeavailable );
/**
* NTP server address could be acquired via DHCP,
*
* NOTE: This call should be made BEFORE esp32 acquires IP address via DHCP,
* otherwise SNTP option 42 would be rejected by default.
* NOTE: configTime() function call if made AFTER DHCP-client run
* will OVERRIDE acquired NTP server address
*/
sntp_servermode_dhcp(1); // (optional)
/**
* This will set configured ntp servers and constant TimeZone/daylightOffset
* should be OK if your time zone does not need to adjust daylightOffset twice a year,
* in such a case time adjustment won't be handled automagically.
*/
// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
/**
* A more convenient approach to handle TimeZones with daylightOffset
* would be to specify a environment variable with TimeZone definition including daylight adjustment rules.
* A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
*/
configTzTime(time_zone, ntpServer1, ntpServer2);
//connect to WiFi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}
void loop()
{
if (millis() - intervalue > 1000) {
intervalue = millis();
// hardware clock
struct tm hwTimeinfo;
rtc.getDateTime(&hwTimeinfo);
Serial.print("Hardware clock :");
Serial.println(&hwTimeinfo, "%A, %B %d %Y %H:%M:%S");
// system clock
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
Serial.print("System clock :");
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.println();
}
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("Examples only ESP32"); delay(1000);
}
#endif

View File

@ -0,0 +1,280 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMC6310_CalibrateExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifdef ARDUINO_T_BEAM_S3_SUPREME
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
#endif
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
SensorQMC6310 qmc;
void beginPower()
{
// T_BEAM_S3_SUPREME The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_BEAM_S3_SUPREME)
XPowersAXP2101 power;
power.begin(Wire1, AXP2101_SLAVE_ADDRESS, 42, 41);
power.disableALDO1();
power.disableALDO2();
delay(250);
power.setALDO1Voltage(3300);
power.enableALDO1();
power.setALDO2Voltage(3300);
power.enableALDO2();
#endif
}
void calibrate()
{
qmc.setDataOutputRate(SensorQMC6310::DATARATE_200HZ);
int32_t x_min = 65535;
int32_t x_max = -65535;
int32_t y_min = 65535;
int32_t y_max = -65535;
int32_t z_min = 65535;
int32_t z_max = -65535;
Serial.println("Place the sensor on the plane and slowly rotate the sensor...");
int32_t range = 1000;
int32_t i = 0;
int32_t x = 0, y = 0, z = 0;;
float a = 0.5 ;
float x_offset = 0;
float y_offset = 0;
float z_offset = 0;
while (i < range) {
i += 1;
if (qmc.isDataReady()) {
qmc.readData();
x = a * qmc.getRawX() + (1 - a) * x;
y = a * qmc.getRawY() + (1 - a) * y;
z = a * qmc.getRawZ() + (1 - a) * z;
if (x < x_min) {
x_min = x;
i = 0;
}
if (x > x_max) {
x_max = x;
i = 0;
}
if (y < y_min) {
y_min = y;
i = 0;
}
if (y > y_max) {
y_max = y;
i = 0;
}
if (z < z_min) {
z_min = z;
i = 0;
}
if (z > z_max) {
z_max = z;
i = 0;
}
int j = round(10 * i / range);
Serial.print("[");
for (int k = 0; k < j; ++k) {
Serial.print("*");
}
Serial.println("]");
}
delay(5);
}
x_offset = (x_max + x_min) / 2;
y_offset = (y_max + y_min) / 2;
z_offset = (z_max + z_min) / 2;
Serial.print("x_min:");
Serial.print(x_min);
Serial.print("x_max:");
Serial.print(x_max);
Serial.print("y_min:");
Serial.print(y_min);
Serial.print("y_max:");
Serial.print(y_max);
Serial.print("z_min:");
Serial.print(z_min);
Serial.print("z_max:");
Serial.println(z_max);
Serial.print("x_offset:");
Serial.print(x_offset);
Serial.print("y_offset:");
Serial.print(y_offset);
Serial.print("z_offset:");
Serial.print(z_offset);
// Set the calibration value and the user calculates the deviation
qmc.setOffset(x_offset, y_offset, z_offset);
}
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
if (!qmc.begin(Wire, QMC6310U_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_CONTINUOUS,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
// Calibration algorithm reference from
// https://github.com/CoreElectronics/CE-PiicoDev-QMC6310-MicroPython-Module
calibrate();
Serial.println("Calibration done .");
delay(5000);
Serial.println("Read data now...");
}
void loop()
{
//Wait data ready
if (qmc.isDataReady()) {
qmc.readData();
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
Serial.print("RAW: ");
Serial.print("X:");
Serial.print(qmc.getRawX());
Serial.print(" Y:");
Serial.print(qmc.getRawY());
Serial.print(" Z:");
Serial.println(qmc.getRawZ());
/*
float x, y, z;
qmc.getMag(x, y, z);
Serial.print("X:");
Serial.print(x);
Serial.print(" Y:");
Serial.print(y);
Serial.print(" Z:");
Serial.println(x);
*/
}
delay(100);
}

View File

@ -0,0 +1,254 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMC6310_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP32)
#include "SensorQMC6310.hpp"
#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306
#ifdef ARDUINO_T_BEAM_S3_SUPREME
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
#endif
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#ifndef OLED_SDA
#define OLED_SDA 22 // Display Wire SDA Pin
#endif
#ifndef OLED_SCL
#define OLED_SCL 21 // Display Wire SCL Pin
#endif
SH1106Wire display(0x3c, OLED_SDA, OLED_SCL);
SensorQMC6310 qmc;
int last_dx, last_dy, dx, dy, angle;
const int centreX = 32;
const int centreY = 30;
const int radius = 22;
//Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED
void arrow(int x2, int y2, int x1, int y1, int alength, int awidth, OLEDDISPLAY_COLOR color)
{
display.setColor(color);
float distance;
int dx, dy, x2o, y2o, x3, y3, x4, y4, k;
distance = sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
dx = x2 + (x1 - x2) * alength / distance;
dy = y2 + (y1 - y2) * alength / distance;
k = awidth / alength;
x2o = x2 - dx;
y2o = dy - y2;
x3 = y2o * k + dx;
y3 = x2o * k + dy;
x4 = dx - y2o * k;
y4 = dy - x2o * k;
display.drawLine(x1, y1, x2, y2);
display.drawLine(x1, y1, dx, dy);
display.drawLine(x3, y3, x4, y4);
display.drawLine(x3, y3, x2, y2);
display.drawLine(x2, y2, x4, y4);
}
void beginPower()
{
// T_BEAM_S3_SUPREME The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_BEAM_S3_SUPREME)
XPowersAXP2101 power;
power.begin(Wire1, AXP2101_SLAVE_ADDRESS, 42, 41);
power.disableALDO1();
power.disableALDO2();
delay(250);
power.setALDO1Voltage(3300);
power.enableALDO1();
power.setALDO2Voltage(3300);
power.enableALDO2();
#endif
}
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
if (!qmc.begin(Wire, QMC6310U_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
display.init();
last_dx = centreX;
last_dy = centreY;
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
int r = qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_NORMAL,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_2G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_100HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
if (r < 0) {
Serial.println("Device config failed!");
while (1)delay(1000);
}
// Print register configuration information
qmc.dumpCtrlRegister();
Serial.println("Read data now...");
}
void loop()
{
//Wait data ready
if (qmc.isDataReady()) {
qmc.readData();
display.drawString(29, 0, "N");
display.drawString( 0, 28, "W");
display.drawString(60, 28, "E");
display.drawString(29, 53, "S");
display.drawLine(1, 1, 7, 7);
display.drawLine(62, 1, 56, 7);
display.drawLine(1, 62, 7, 56);
display.drawLine(56, 56, 62, 62);
//Compass application from https://github.com/G6EJD/ESP8266_micro_compass_HMC5883_OLED
float heading = atan2(qmc.getY(), qmc.getX()); // Result is in radians
// Now add the 'Declination Angle' for you location. Declination is the variation in magnetic field at your location.
// Find your declination here: http://www.magnetic-declination.com/
// At my location it is : -2° 20' W, or -2.33 Degrees, which needs to be in radians so = -2.33 / 180 * PI = -0.041 West is + E is -
// Make declination = 0 if you can't find your Declination value, the error is negible for nearly all locations
float declination = -0.041;
heading = heading + declination;
if (heading < 0) heading += 2 * PI; // Correct for when signs are reversed.
if (heading > 2 * PI) heading -= 2 * PI; // Correct for when heading exceeds 360-degree, especially when declination is included
angle = int(heading * 180 / M_PI); // Convert radians to degrees for more a more usual result
// For the screen -X = up and +X = down and -Y = left and +Y = right, so does not follow coordinate conventions
dx = (0.7 * radius * cos((angle - 90) * 3.14 / 180)) + centreX; // calculate X position for the screen coordinates - can be confusing!
dy = (0.7 * radius * sin((angle - 90) * 3.14 / 180)) + centreY; // calculate Y position for the screen coordinates - can be confusing!
arrow(last_dx, last_dy, centreX, centreY, 2, 2, BLACK); // Erase last arrow
arrow(dx, dy, centreX, centreY, 2, 2, WHITE); // Draw arrow in new position
display.setColor(BLACK);
display.fillRect(80, 50, 25, 48);
display.setColor(WHITE);
display.drawString(80, 50, String(angle) + "°");
display.display();
last_dx = dx;
last_dy = dy;
// for debug.
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
}
delay(100);
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("The graphics library may not be supported on the esp32 platform"); delay(1000);
}
#endif

View File

@ -0,0 +1,170 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMC6310_GetDataExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifdef ARDUINO_T_BEAM_S3_SUPREME
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
#endif
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
SensorQMC6310 qmc;
void beginPower()
{
// T_BEAM_S3_SUPREME The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_BEAM_S3_SUPREME)
XPowersAXP2101 power;
power.begin(Wire1, AXP2101_SLAVE_ADDRESS, 42, 41);
power.disableALDO1();
power.disableALDO2();
delay(250);
power.setALDO1Voltage(3300);
power.enableALDO1();
power.setALDO2Voltage(3300);
power.enableALDO2();
#endif
}
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
if (!qmc.begin(Wire, QMC6310U_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_CONTINUOUS,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_1,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
Serial.println("Read data now...");
}
void loop()
{
//Wiat data ready
if (qmc.isDataReady()) {
qmc.readData();
Serial.print("GYR: ");
Serial.print("X:");
Serial.print(qmc.getX());
Serial.print(" Y:");
Serial.print(qmc.getY());
Serial.print(" Z:");
Serial.print(qmc.getZ());
Serial.println(" uT");
Serial.print("RAW: ");
Serial.print("X:");
Serial.print(qmc.getRawX());
Serial.print(" Y:");
Serial.print(qmc.getRawY());
Serial.print(" Z:");
Serial.println(qmc.getRawZ());
/*
float x, y, z;
qmc.getMag(x, y, z);
Serial.print("X:");
Serial.print(x);
Serial.print(" Y:");
Serial.print(y);
Serial.print(" Z:");
Serial.println(x);
*/
}
delay(100);
}

View File

@ -0,0 +1,148 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMC6310_GetPolarExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "SensorQMC6310.hpp"
#ifdef ARDUINO_T_BEAM_S3_SUPREME
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
#endif
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
SensorQMC6310 qmc;
void beginPower()
{
// T_BEAM_S3_SUPREME The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_BEAM_S3_SUPREME)
XPowersAXP2101 power;
power.begin(Wire1, AXP2101_SLAVE_ADDRESS, 42, 41);
power.disableALDO1();
power.disableALDO2();
delay(250);
power.setALDO1Voltage(3300);
power.enableALDO1();
power.setALDO2Voltage(3300);
power.enableALDO2();
#endif
}
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
if (!qmc.begin(Wire, QMC6310U_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL)) {
Serial.println("Failed to find QMC6310 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get Magnetometer chip id*/
Serial.print("Device ID:");
Serial.println(qmc.getChipID(), HEX);
/* Config Magnetometer */
qmc.configMagnetometer(
/*
* Run Mode
* MODE_SUSPEND
* MODE_NORMAL
* MODE_SINGLE
* MODE_CONTINUOUS
* * */
SensorQMC6310::MODE_NORMAL,
/*
* Full Range
* RANGE_30G
* RANGE_12G
* RANGE_8G
* RANGE_2G
* * */
SensorQMC6310::RANGE_8G,
/*
* Output data rate
* DATARATE_10HZ
* DATARATE_50HZ
* DATARATE_100HZ
* DATARATE_200HZ
* * */
SensorQMC6310::DATARATE_200HZ,
/*
* Over sample Ratio1
* OSR_8
* OSR_4
* OSR_2
* OSR_1
* * * */
SensorQMC6310::OSR_8,
/*
* Down sample Ratio1
* DSR_8
* DSR_4
* DSR_2
* DSR_1
* * */
SensorQMC6310::DSR_1);
qmc.dumpCtrlRegister();
// Declination is the difference between magnetic-north and true-north ("heading") and depends on location
qmc.setDeclination(-2.77); // Found with: https://www.magnetic-declination.com/CHINA/SHENZHEN/475119.html
Serial.println("Read data now...");
}
void loop()
{
Polar data;
// Wait for data ready
if (qmc.readPolar(data)) {
Serial.print(" polar:"); Serial.print(data.polar); Serial.print("°");
Serial.print(" Gauss:"); Serial.print(data.Gauss);
Serial.print(" uT:"); Serial.println(data.uT);
}
delay(100);
}

View File

@ -0,0 +1,289 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMI8658_BlockExample.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#ifdef ARDUINO_ARCH_ESP32
#include "SensorQMI8658.hpp"
#include <MadgwickAHRS.h> //MadgwickAHRS from https://github.com/arduino-libraries/MadgwickAHRS
#include "SH1106Wire.h" //Oled display from https://github.com/ThingPulse/esp8266-oled-ssd1306
#ifdef ARDUINO_T_BEAM_S3_SUPREME
#include <XPowersAXP2101.tpp> //PMU Library https://github.com/lewisxhe/XPowersLib.git
#endif
// #define USE_I2C //Using the I2C interface
#ifdef USE_I2C
#ifndef SENSOR_SDA
#define SENSOR_SDA 17
#endif
#ifndef SENSOR_SCL
#define SENSOR_SCL 18
#endif
#else /* SPI interface*/
#ifndef SPI_MOSI
#define SPI_MOSI (35)
#endif
#ifndef SPI_SCK
#define SPI_SCK (36)
#endif
#ifndef SPI_MISO
#define SPI_MISO (37)
#endif
#endif /* USE_I2C*/
#ifndef IMU_CS
#define IMU_CS 34 // IMU CS PIN
#endif
#ifndef IMU_IRQ
#define IMU_IRQ 33 // IMU INT PIN
#endif
#ifndef OLED_SDA
#define OLED_SDA 22 // Display Wire SDA Pin
#endif
#ifndef OLED_SCL
#define OLED_SCL 21 // Display Wire SCL Pin
#endif
SH1106Wire display(0x3c, OLED_SDA, OLED_SCL);
SensorQMI8658 qmi;
IMUdata acc;
IMUdata gyr;
Madgwick filter;
float posX = 64;
float posY = 32;
float lastPosX = posX;
float lastPosY = posY;
uint32_t microsPerReading, microsPrevious;
const uint8_t rectWidth = 10;
void beginPower()
{
// T_BEAM_S3_SUPREME The PMU voltage needs to be turned on to use the sensor
#if defined(ARDUINO_T_BEAM_S3_SUPREME)
XPowersAXP2101 power;
power.begin(Wire1, AXP2101_SLAVE_ADDRESS, 42, 41);
power.disableALDO1();
power.disableALDO2();
delay(250);
power.setALDO1Voltage(3300);
power.enableALDO1();
power.setALDO2Voltage(3300);
power.enableALDO2();
#endif
}
void setup()
{
Serial.begin(115200);
while (!Serial);
beginPower();
display.init();
bool ret = false;
#ifdef USE_I2C
ret = qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, SENSOR_SDA, SENSOR_SCL);
#else
#if defined(SPI_MOSI) && defined(SPI_SCK) && defined(SPI_MISO)
ret = qmi.begin(SPI, IMU_CS, SPI_MOSI, SPI_MISO, SPI_SCK);
#else
ret = qmi.begin(SPI, IMU_CS);
#endif
#endif
if (!ret) {
Serial.println("Failed to find QMI8658 - check your wiring!");
while (1) {
delay(1000);
}
}
/* Get chip id*/
Serial.print("Device ID:");
Serial.println(qmi.getChipID(), HEX);
display.flipScreenVertically();
qmi.configAccelerometer(
/*
* ACC_RANGE_2G
* ACC_RANGE_4G
* ACC_RANGE_8G
* ACC_RANGE_16G
* */
SensorQMI8658::ACC_RANGE_2G,
/*
* ACC_ODR_1000H
* ACC_ODR_500Hz
* ACC_ODR_250Hz
* ACC_ODR_125Hz
* ACC_ODR_62_5Hz
* ACC_ODR_31_25Hz
* ACC_ODR_LOWPOWER_128Hz
* ACC_ODR_LOWPOWER_21Hz
* ACC_ODR_LOWPOWER_11Hz
* ACC_ODR_LOWPOWER_3H
* */
SensorQMI8658::ACC_ODR_1000Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_0);
qmi.configGyroscope(
/*
* GYR_RANGE_16DPS
* GYR_RANGE_32DPS
* GYR_RANGE_64DPS
* GYR_RANGE_128DPS
* GYR_RANGE_256DPS
* GYR_RANGE_512DPS
* GYR_RANGE_1024DPS
* */
SensorQMI8658::GYR_RANGE_256DPS,
/*
* GYR_ODR_7174_4Hz
* GYR_ODR_3587_2Hz
* GYR_ODR_1793_6Hz
* GYR_ODR_896_8Hz
* GYR_ODR_448_4Hz
* GYR_ODR_224_2Hz
* GYR_ODR_112_1Hz
* GYR_ODR_56_05Hz
* GYR_ODR_28_025H
* */
SensorQMI8658::GYR_ODR_896_8Hz,
/*
* LPF_MODE_0 //2.66% of ODR
* LPF_MODE_1 //3.63% of ODR
* LPF_MODE_2 //5.39% of ODR
* LPF_MODE_3 //13.37% of ODR
* */
SensorQMI8658::LPF_MODE_3);
/*
* If both the accelerometer and gyroscope sensors are turned on at the same time,
* the output frequency will be based on the gyroscope output frequency.
* The example configuration is 896.8HZ output frequency,
* so the acceleration output frequency is also limited to 896.8HZ
* */
qmi.enableGyroscope();
qmi.enableAccelerometer();
// Print register configuration information
qmi.dumpCtrlRegister();
// start filter
filter.begin(25);
// initialize variables to pace updates to correct rate
microsPerReading = 1000000 / 25;
microsPrevious = micros();
Serial.println("Read data now...");
}
void loop()
{
float roll = 0, pitch = 0, heading = 0;
// check if it's time to read data and update the filter
if (micros() - microsPrevious >= microsPerReading) {
// read raw data from IMU
if (qmi.getDataReady()) {
qmi.getAccelerometer(acc.x, acc.y, acc.z);
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
// update the filter, which computes orientation
filter.updateIMU(gyr.x, gyr.y, gyr.z, acc.x, acc.y, acc.z);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
posX -= roll * 2;
posY += pitch;
posX = constrain(posX, 0, display.width() - rectWidth);
posY = constrain(posY, 0, display.height() - rectWidth);
display.setColor(BLACK);
display.fillRect(lastPosX, lastPosY, 10, 10);
display.setColor(WHITE);
display.fillRect(posX, posY, 10, 10);
display.display();
lastPosX = posX;
lastPosY = posY;
}
// increment previous time, so we keep proper pace
microsPrevious = microsPrevious + microsPerReading;
}
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("The graphics library may not be supported on the esp32 platform");
delay(1000);
}
#endif

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