Release 0.8.0
Rewritten RMT Timing Update packet building Internal clean up Cosmetics More pause between frames Fix RX buffer
This commit is contained in:
commit
9e12f163e5
|
|
@ -1,4 +1,5 @@
|
|||
name: ESP32 Build & Quality Check
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
|
@ -8,80 +9,106 @@ on:
|
|||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# Code Quality & Linting
|
||||
# ============================================================================
|
||||
quality-check:
|
||||
name: 'Arduino Lint Check'
|
||||
name: Arduino Lint Check
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Arduino CLI
|
||||
uses: arduino/setup-arduino-cli@v2
|
||||
- uses: arduino/setup-arduino-cli@v2
|
||||
|
||||
- name: Install ESP32 core
|
||||
- name: Cache Arduino Core
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.arduino15/packages
|
||||
~/.arduino15/cache
|
||||
key: arduino-core-${{ runner.os }}-esp32-v1
|
||||
restore-keys: |
|
||||
arduino-core-${{ runner.os }}-
|
||||
|
||||
- name: Install ESP32 Core
|
||||
run: |
|
||||
arduino-cli core update-index > /dev/null
|
||||
arduino-cli core install esp32:esp32 > /dev/null
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core install esp32:esp32
|
||||
|
||||
- name: Arduino Lint
|
||||
uses: arduino/arduino-lint-action@v2
|
||||
- uses: arduino/arduino-lint-action@v2
|
||||
with:
|
||||
path: ${{ github.workspace }}
|
||||
compliance: strict
|
||||
library-manager: update
|
||||
verbose: true
|
||||
|
||||
# ============================================================================
|
||||
# ============================================================================
|
||||
# Compilation Test
|
||||
# ============================================================================
|
||||
compile-test:
|
||||
name: 'Compile Example Sketches'
|
||||
name: Compile Example Sketches
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
examples:
|
||||
- "examples/dshot300/dshot300.ino"
|
||||
- "examples/command_manager/command_manager.ino"
|
||||
- "examples/web_control/web_control.ino"
|
||||
- "examples/web_client/web_client.ino"
|
||||
example:
|
||||
- examples/dshot300/dshot300.ino
|
||||
- examples/command_manager/command_manager.ino
|
||||
- examples/web_control/web_control.ino
|
||||
- examples/web_client/web_client.ino
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Arduino CLI
|
||||
uses: arduino/setup-arduino-cli@v2
|
||||
- uses: arduino/setup-arduino-cli@v2
|
||||
|
||||
- name: Cache Arduino Core & Libraries
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.arduino15/packages
|
||||
~/.arduino15/cache
|
||||
~/Arduino/libraries
|
||||
key: arduino-full-${{ runner.os }}-esp32-v1
|
||||
restore-keys: |
|
||||
arduino-full-${{ runner.os }}-
|
||||
|
||||
- name: Install ESP32 Core and Dependencies
|
||||
run: |
|
||||
arduino-cli core update-index
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core install esp32:esp32
|
||||
|
||||
arduino-cli lib install "ArduinoJson"
|
||||
|
||||
# Workround for ESPAsyncWebServer
|
||||
git clone https://github.com/ESP32Async/ESPAsyncWebServer ~/Arduino/libraries/ESPAsyncWebServer
|
||||
git clone https://github.com/ESP32Async/AsyncTCP ~/Arduino/libraries/AsyncTCP
|
||||
|
||||
mkdir -p ~/Arduino/libraries
|
||||
|
||||
# Cached repository check
|
||||
if [ ! -d ~/Arduino/libraries/ESPAsyncWebServer ]; then
|
||||
git clone --depth=1 https://github.com/ESP32Async/ESPAsyncWebServer ~/Arduino/libraries/ESPAsyncWebServer
|
||||
fi
|
||||
|
||||
if [ ! -d ~/Arduino/libraries/AsyncTCP ]; then
|
||||
git clone --depth=1 https://github.com/ESP32Async/AsyncTCP ~/Arduino/libraries/AsyncTCP
|
||||
fi
|
||||
|
||||
- name: Compile Sketch
|
||||
run: |
|
||||
arduino-cli compile --fqbn esp32:esp32:esp32 --library ${{ github.workspace }} ${{ matrix.examples}}
|
||||
arduino-cli compile \
|
||||
--fqbn esp32:esp32:esp32 \
|
||||
--library ${{ github.workspace }} \
|
||||
${{ matrix.example }}
|
||||
|
||||
# ============================================================================
|
||||
# Build Status Report
|
||||
# ============================================================================
|
||||
build-summary:
|
||||
name: 'Build Summary'
|
||||
name: Build Summary
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
needs: [quality-check, compile-test]
|
||||
|
|
@ -90,32 +117,21 @@ jobs:
|
|||
- name: Create Build Summary
|
||||
run: |
|
||||
echo "# 🔧 DShotRMT Build Report" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Check | Status | Details |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Check | Status | Details |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|-------|--------|---------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Quality Check Status
|
||||
if [[ "${{ needs.quality-check.result }}" == "success" ]]; then
|
||||
echo "| 📋 Quality Check | ✅ Passed | Arduino Lint completed successfully |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| 📋 Quality Check | ❌ Failed | Check Arduino Lint report |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Compile Test Status
|
||||
if [[ "${{ needs.compile-test.result }}" == "success" ]]; then
|
||||
echo "| 🔨 Compilation | ✅ Passed | All examples compiled successfully |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| 🔨 Compilation | ❌ Failed | Compilation errors detected |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
|
||||
[[ "${{ needs.quality-check.result }}" == "success" ]] \
|
||||
&& echo "| 📋 Quality Check | ✅ Passed | Arduino Lint completed successfully |" >> $GITHUB_STEP_SUMMARY \
|
||||
|| echo "| 📋 Quality Check | ❌ Failed | Check Arduino Lint report |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
[[ "${{ needs.compile-test.result }}" == "success" ]] \
|
||||
&& echo "| 🔨 Compilation | ✅ Passed | All examples compiled successfully |" >> $GITHUB_STEP_SUMMARY \
|
||||
|| echo "| 🔨 Compilation | ❌ Failed | Compilation errors detected |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Overall Status
|
||||
if [[ "${{ needs.quality-check.result }}" == "success" &&
|
||||
"${{ needs.compile-test.result }}" == "success" ]]; then
|
||||
echo "## 🎉 All Checks Passed!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Your DShotRMT library is ready for deployment." >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "## ⚠️ Action Required" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Please review the failed checks and address any issues."
|
||||
fi
|
||||
|
||||
[[ "${{ needs.quality-check.result }}" == "success" && "${{ needs.compile-test.result }}" == "success" ]] \
|
||||
&& echo "## 🎉 All Checks Passed!" >> $GITHUB_STEP_SUMMARY \
|
||||
&& echo "Your DShotRMT library is ready for deployment." >> $GITHUB_STEP_SUMMARY \
|
||||
|| echo "## ⚠️ Action Required" >> $GITHUB_STEP_SUMMARY \
|
||||
&& echo "Please review the failed checks and address any issues." >> $GITHUB_STEP_SUMMARY
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
.vs
|
||||
.vscode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"configuration": "JTAGAdapter=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none,EraseFlash=all,ZigbeeMode=default",
|
||||
"board": "esp32:esp32:esp32",
|
||||
"sketch": "examples/dshot300/dshot300.ino",
|
||||
"output": "build",
|
||||
"port": "/dev/ttyUSB0"
|
||||
}
|
||||
|
|
@ -0,0 +1,899 @@
|
|||
{
|
||||
"version": 4,
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ESP32",
|
||||
"compilerPath": "~/.arduino15/packages/esp32/tools/esp-x32/2411/bin/xtensa-esp32-elf-g++",
|
||||
"compilerArgs": [
|
||||
"-MMD",
|
||||
"-w",
|
||||
"-Werror=return-type",
|
||||
"-iprefix"
|
||||
],
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"includePath": [
|
||||
"~/.arduino15/packages/esp32/hardware/esp32/3.3.0/cores/esp32/**",
|
||||
"~/.arduino15/packages/esp32/hardware/esp32/3.3.0/variants/esp32/**",
|
||||
"~/.arduino15/packages/esp32/hardware/esp32/3.3.0/libraries/**",
|
||||
"~/.arduino15/packages/esp32/hardware/esp32/3.3.0/**",
|
||||
"~/.arduino15/packages/esp32/tools/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/xtensa-esp-elf/esp32/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/backward/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include-fixed/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.5-b66b5448-v1/esp32/include/**",
|
||||
"~/.arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.5-b66b5448-v1/esp32/include/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/",
|
||||
"~/Arduino/libraries/**",
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"forcedInclude": [
|
||||
"~/.arduino15/packages/esp32/hardware/esp32/3.3.0/cores/esp32/Arduino.h"
|
||||
],
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20",
|
||||
"defines": [
|
||||
"F_CPU=240000000L",
|
||||
"ESP32",
|
||||
"ARDUINO=10607",
|
||||
"ARDUINO_ESP32_DEV",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
"ARDUINO_BOARD=\"ESP32_DEV\"",
|
||||
"ARDUINO_VARIANT=\"esp32\"",
|
||||
"ARDUINO_PARTITION_default",
|
||||
"ARDUINO_HOST_OS=\"linux\"",
|
||||
"ARDUINO_FQBN=\"esp32:esp32:esp32:JTAGAdapter=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none,EraseFlash=none,ZigbeeMode=default\"",
|
||||
"ESP32=ESP32",
|
||||
"CORE_DEBUG_LEVEL=0",
|
||||
"ARDUINO_RUNNING_CORE=1",
|
||||
"ARDUINO_EVENT_RUNNING_CORE=1",
|
||||
"ARDUINO_USB_CDC_ON_BOOT=0",
|
||||
"__DBL_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_HAVE_FP=1",
|
||||
"__cpp_nontype_template_parameter_auto=201606L",
|
||||
"__UINT_LEAST16_MAX__=0xffff",
|
||||
"__ATOMIC_ACQUIRE=2",
|
||||
"__FLT_MIN__=1.1754943508222875e-38F",
|
||||
"__GCC_IEC_559_COMPLEX=0",
|
||||
"__XCHAL_HAVE_PREDICTED_BRANCHES=0",
|
||||
"__cpp_aggregate_nsdmi=201304L",
|
||||
"__UINT_LEAST8_TYPE__=unsigned char",
|
||||
"__INTMAX_C(c)=c ## LL",
|
||||
"__XCHAL_HAVE_ADDX=1",
|
||||
"__CHAR_BIT__=8",
|
||||
"__XCHAL_DCACHE_LINESIZE=16",
|
||||
"__XTENSA_MARCH_EARLIEST=260003",
|
||||
"__XCHAL_DCACHE_LINEWIDTH=4",
|
||||
"__UINT8_MAX__=0xff",
|
||||
"__WINT_MAX__=0xffffffffU",
|
||||
"__FLT32_MIN_EXP__=(-125)",
|
||||
"__cpp_static_assert=201411L",
|
||||
"__ORDER_LITTLE_ENDIAN__=1234",
|
||||
"__SIZE_MAX__=0xffffffffU",
|
||||
"__WCHAR_MAX__=0xffff",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1",
|
||||
"__DBL_DENORM_MIN__=double(4.9406564584124654e-324L)",
|
||||
"__GCC_ATOMIC_CHAR_LOCK_FREE=2",
|
||||
"__GCC_IEC_559=0",
|
||||
"__FLT32X_DECIMAL_DIG__=17",
|
||||
"__FLT_EVAL_METHOD__=0",
|
||||
"__cpp_binary_literals=201304L",
|
||||
"__FLT64_DECIMAL_DIG__=17",
|
||||
"__cpp_noexcept_function_type=201510L",
|
||||
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2",
|
||||
"__cpp_variadic_templates=200704L",
|
||||
"__UINT_FAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__SIG_ATOMIC_TYPE__=int",
|
||||
"__DBL_MIN_10_EXP__=(-307)",
|
||||
"__FINITE_MATH_ONLY__=0",
|
||||
"__cpp_variable_templates=201304L",
|
||||
"__XCHAL_HAVE_L32R=1",
|
||||
"__FLT32X_MAX_EXP__=1024",
|
||||
"__GNUC_PATCHLEVEL__=0",
|
||||
"__FLT32_HAS_DENORM__=1",
|
||||
"__UINT_FAST8_MAX__=0xffffffffU",
|
||||
"__cpp_rvalue_reference=200610L",
|
||||
"__XCHAL_HAVE_LOOPS=1",
|
||||
"__cpp_nested_namespace_definitions=201411L",
|
||||
"__XCHAL_DEBUGLEVEL=6",
|
||||
"__INT8_C(c)=c",
|
||||
"__XCHAL_HAVE_DFP_RECIP=0",
|
||||
"__INT_LEAST8_WIDTH__=8",
|
||||
"__cpp_variadic_using=201611L",
|
||||
"__UINT_LEAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__INT_LEAST8_MAX__=0x7f",
|
||||
"__cpp_attributes=200809L",
|
||||
"__cpp_capture_star_this=201603L",
|
||||
"__SHRT_MAX__=0x7fff",
|
||||
"__LDBL_MAX__=1.7976931348623157e+308L",
|
||||
"__cpp_if_constexpr=201606L",
|
||||
"__XCHAL_ICACHE_LINESIZE=16",
|
||||
"__LDBL_IS_IEC_60559__=1",
|
||||
"__UINT_LEAST8_MAX__=0xff",
|
||||
"__GCC_ATOMIC_BOOL_LOCK_FREE=2",
|
||||
"__UINTMAX_TYPE__=long long unsigned int",
|
||||
"__cpp_nsdmi=200809L",
|
||||
"__FLT_EVAL_METHOD_TS_18661_3__=0",
|
||||
"__UINT32_MAX__=0xffffffffUL",
|
||||
"__GXX_EXPERIMENTAL_CXX0X__=1",
|
||||
"__LDBL_MAX_EXP__=1024",
|
||||
"__WINT_MIN__=0U",
|
||||
"__FLT32X_IS_IEC_60559__=1",
|
||||
"__XCHAL_HAVE_THREADPTR=1",
|
||||
"__INT_LEAST16_WIDTH__=16",
|
||||
"__SCHAR_MAX__=0x7f",
|
||||
"__WCHAR_MIN__=0",
|
||||
"__XCHAL_ICACHE_LINEWIDTH=4",
|
||||
"__INT64_C(c)=c ## LL",
|
||||
"__GCC_ATOMIC_POINTER_LOCK_FREE=2",
|
||||
"__ATOMIC_SEQ_CST=5",
|
||||
"__SIZEOF_INT__=4",
|
||||
"__FLT32X_MANT_DIG__=53",
|
||||
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2",
|
||||
"__cpp_aligned_new=201606L",
|
||||
"__XCHAL_HAVE_FP_RECIP=1",
|
||||
"__FLT32_MAX_10_EXP__=38",
|
||||
"__STDC_HOSTED__=1",
|
||||
"__XCHAL_HAVE_MUL32=1",
|
||||
"__XTENSA_EL__=1",
|
||||
"__cpp_decltype_auto=201304L",
|
||||
"__DBL_DIG__=15",
|
||||
"__XCHAL_HAVE_MUL16=1",
|
||||
"__FLT_EPSILON__=1.1920928955078125e-7F",
|
||||
"__GXX_WEAK__=1",
|
||||
"__SHRT_WIDTH__=16",
|
||||
"__FLT32_IS_IEC_60559__=1",
|
||||
"__LDBL_MIN__=2.2250738585072014e-308L",
|
||||
"__DBL_IS_IEC_60559__=1",
|
||||
"__cpp_threadsafe_static_init=200806L",
|
||||
"__cpp_enumerator_attributes=201411L",
|
||||
"__XCHAL_HAVE_MMU=0",
|
||||
"__FLT32X_HAS_INFINITY__=1",
|
||||
"__INT32_MAX__=0x7fffffffL",
|
||||
"__XCHAL_HAVE_DIV32=1",
|
||||
"__INT_WIDTH__=32",
|
||||
"__XTENSA_MARCH_LATEST=260003",
|
||||
"__DECIMAL_DIG__=17",
|
||||
"__FLT64_EPSILON__=2.2204460492503131e-16F64",
|
||||
"__INT16_MAX__=0x7fff",
|
||||
"__FLT64_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_DCACHE_SIZE=0",
|
||||
"__LDBL_HAS_QUIET_NAN__=1",
|
||||
"__cpp_return_type_deduction=201304L",
|
||||
"__XCHAL_HAVE_BOOLEANS=1",
|
||||
"__FLT64_MANT_DIG__=53",
|
||||
"__XTHAL_ABI_WINDOWED=0",
|
||||
"__GNUC__=14",
|
||||
"__GXX_RTTI=1",
|
||||
"__FLT_HAS_DENORM__=1",
|
||||
"__SIZEOF_LONG_DOUBLE__=8",
|
||||
"__XCHAL_HAVE_CONST16=0",
|
||||
"__BIGGEST_ALIGNMENT__=16",
|
||||
"__STDC_UTF_16__=1",
|
||||
"__FLT64_MAX_10_EXP__=308",
|
||||
"__cpp_delegating_constructors=200604L",
|
||||
"__DBL_MAX__=double(1.7976931348623157e+308L)",
|
||||
"__cpp_raw_strings=200710L",
|
||||
"__INT_FAST32_MAX__=0x7fffffff",
|
||||
"__DBL_HAS_INFINITY__=1",
|
||||
"__cpp_deduction_guides=201703L",
|
||||
"__HAVE_SPECULATION_SAFE_VALUE=1",
|
||||
"__cpp_fold_expressions=201603L",
|
||||
"__INTPTR_WIDTH__=32",
|
||||
"__UINT_LEAST32_MAX__=0xffffffffUL",
|
||||
"__FLT32X_HAS_DENORM__=1",
|
||||
"__INT_FAST16_TYPE__=int",
|
||||
"__XCHAL_HAVE_RELEASE_SYNC=1",
|
||||
"__LDBL_HAS_DENORM__=1",
|
||||
"__cplusplus=201703L",
|
||||
"__cpp_ref_qualifiers=200710L",
|
||||
"__INT_LEAST32_MAX__=0x7fffffffL",
|
||||
"__DEPRECATED=1",
|
||||
"__cpp_rvalue_references=200610L",
|
||||
"__DBL_MAX_EXP__=1024",
|
||||
"__WCHAR_WIDTH__=16",
|
||||
"__FLT32_MAX__=3.4028234663852886e+38F32",
|
||||
"__GCC_ATOMIC_LONG_LOCK_FREE=2",
|
||||
"__PTRDIFF_MAX__=0x7fffffff",
|
||||
"__FLT32_HAS_QUIET_NAN__=1",
|
||||
"__GNUG__=14",
|
||||
"__LONG_LONG_MAX__=0x7fffffffffffffffLL",
|
||||
"__SIZEOF_SIZE_T__=4",
|
||||
"__SIZEOF_WINT_T__=4",
|
||||
"__FLT32X_DIG__=15",
|
||||
"__LONG_LONG_WIDTH__=64",
|
||||
"__cpp_initializer_lists=200806L",
|
||||
"__FLT32_MAX_EXP__=128",
|
||||
"__XCHAL_HAVE_MINMAX=1",
|
||||
"__cpp_hex_float=201603L",
|
||||
"__XCHAL_NUM_IBREAK=2",
|
||||
"__GXX_ABI_VERSION=1019",
|
||||
"__FLT_MIN_EXP__=(-125)",
|
||||
"__cpp_lambdas=200907L",
|
||||
"__INT_FAST64_TYPE__=long long int",
|
||||
"__FP_FAST_FMAF=1",
|
||||
"__FLT64_DENORM_MIN__=4.9406564584124654e-324F64",
|
||||
"__DBL_MIN__=double(2.2250738585072014e-308L)",
|
||||
"__SIZEOF_POINTER__=4",
|
||||
"__DBL_HAS_QUIET_NAN__=1",
|
||||
"__FLT32X_EPSILON__=2.2204460492503131e-16F32x",
|
||||
"__XSHAL_HAVE_TEXT_SECTION_LITERALS=1",
|
||||
"__FLT64_MIN_10_EXP__=(-307)",
|
||||
"__REGISTER_PREFIX__",
|
||||
"__UINT16_MAX__=0xffff",
|
||||
"__XSHAL_USE_ABSOLUTE_LITERALS=0",
|
||||
"__LDBL_HAS_INFINITY__=1",
|
||||
"__FLT32_MIN__=1.1754943508222875e-38F32",
|
||||
"__UINT8_TYPE__=unsigned char",
|
||||
"__FLT_DIG__=6",
|
||||
"__NO_INLINE__=1",
|
||||
"__DEC_EVAL_METHOD__=2",
|
||||
"__FLT_MANT_DIG__=24",
|
||||
"__LDBL_DECIMAL_DIG__=17",
|
||||
"__VERSION__=\"14.2.0\"",
|
||||
"__UINT64_C(c)=c ## ULL",
|
||||
"__XCHAL_NUM_AREGS=64",
|
||||
"__cpp_unicode_characters=201411L",
|
||||
"__XCHAL_HAVE_XEA3=0",
|
||||
"__GCC_ATOMIC_INT_LOCK_FREE=2",
|
||||
"__XCHAL_HAVE_DENSITY=1",
|
||||
"__FLT32_MANT_DIG__=24",
|
||||
"__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__XCHAL_HAVE_CLAMPS=0",
|
||||
"__XCHAL_HAVE_DFP_RSQRT=0",
|
||||
"__cpp_aggregate_bases=201603L",
|
||||
"__XCHAL_HAVE_NSA=1",
|
||||
"__XCHAL_HAVE_WINDOWED=1",
|
||||
"__SCHAR_WIDTH__=8",
|
||||
"__INT32_C(c)=c ## L",
|
||||
"__ORDER_PDP_ENDIAN__=3412",
|
||||
"__INT_FAST32_TYPE__=int",
|
||||
"__UINT_LEAST16_TYPE__=short unsigned int",
|
||||
"__DBL_HAS_DENORM__=1",
|
||||
"__XCHAL_HAVE_DEBUG=1",
|
||||
"__cpp_rtti=199711L",
|
||||
"__SIZE_TYPE__=unsigned int",
|
||||
"__UINT64_MAX__=0xffffffffffffffffULL",
|
||||
"__FLT_IS_IEC_60559__=1",
|
||||
"__GNUC_WIDE_EXECUTION_CHARSET_NAME=\"UTF-16LE\"",
|
||||
"__INT8_TYPE__=signed char",
|
||||
"__cpp_digit_separators=201309L",
|
||||
"__ELF__=1",
|
||||
"__XSHAL_ABI=0",
|
||||
"__xtensa__=1",
|
||||
"__FLT_RADIX__=2",
|
||||
"__INT_LEAST16_TYPE__=short int",
|
||||
"__LDBL_EPSILON__=2.2204460492503131e-16L",
|
||||
"__UINTMAX_C(c)=c ## ULL",
|
||||
"__FLT32X_MIN__=2.2250738585072014e-308F32x",
|
||||
"__XCHAL_HAVE_DFP_SQRT=0",
|
||||
"__SIG_ATOMIC_MAX__=0x7fffffff",
|
||||
"__XCHAL_HAVE_MAC16=1",
|
||||
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2",
|
||||
"__USER_LABEL_PREFIX__",
|
||||
"__SIZEOF_PTRDIFF_T__=4",
|
||||
"__XCHAL_MMU_MIN_PTE_PAGE_SIZE=1",
|
||||
"__XCHAL_DCACHE_IS_WRITEBACK=0",
|
||||
"__SIZEOF_LONG__=4",
|
||||
"__LDBL_DIG__=15",
|
||||
"__FLT64_IS_IEC_60559__=1",
|
||||
"__XCHAL_MAX_INSTRUCTION_SIZE=3",
|
||||
"__FLT32X_MIN_EXP__=(-1021)",
|
||||
"__INT_FAST16_MAX__=0x7fffffff",
|
||||
"__GCC_CONSTRUCTIVE_SIZE=32",
|
||||
"__FLT64_DIG__=15",
|
||||
"__UINT_FAST32_MAX__=0xffffffffU",
|
||||
"__UINT_LEAST64_TYPE__=long long unsigned int",
|
||||
"__FLT_HAS_QUIET_NAN__=1",
|
||||
"__FLT_MAX_10_EXP__=38",
|
||||
"__FLT_HAS_INFINITY__=1",
|
||||
"__GNUC_EXECUTION_CHARSET_NAME=\"UTF-8\"",
|
||||
"__CHAR_UNSIGNED__=1",
|
||||
"__cpp_unicode_literals=200710L",
|
||||
"__UINT_FAST16_TYPE__=unsigned int",
|
||||
"__INT_FAST32_WIDTH__=32",
|
||||
"__CHAR16_TYPE__=short unsigned int",
|
||||
"__PRAGMA_REDEFINE_EXTNAME=1",
|
||||
"__SIZE_WIDTH__=32",
|
||||
"__INT_LEAST16_MAX__=0x7fff",
|
||||
"__INT64_MAX__=0x7fffffffffffffffLL",
|
||||
"__FLT32_DENORM_MIN__=1.4012984643248171e-45F32",
|
||||
"__SIG_ATOMIC_WIDTH__=32",
|
||||
"__INT_LEAST64_TYPE__=long long int",
|
||||
"__INT16_TYPE__=short int",
|
||||
"__INT_LEAST8_TYPE__=signed char",
|
||||
"__cpp_structured_bindings=201606L",
|
||||
"__INT_FAST8_MAX__=0x7fffffff",
|
||||
"__INTPTR_MAX__=0x7fffffff",
|
||||
"__cpp_sized_deallocation=201309L",
|
||||
"__cpp_guaranteed_copy_elision=201606L",
|
||||
"__FLT64_HAS_QUIET_NAN__=1",
|
||||
"__FLT32_MIN_10_EXP__=(-37)",
|
||||
"__EXCEPTIONS=1",
|
||||
"__UINT16_C(c)=c",
|
||||
"__XCHAL_M_STAGE=3",
|
||||
"__PTRDIFF_WIDTH__=32",
|
||||
"__LDBL_MANT_DIG__=53",
|
||||
"__cpp_range_based_for=201603L",
|
||||
"__FLT64_HAS_INFINITY__=1",
|
||||
"__STDCPP_DEFAULT_NEW_ALIGNMENT__=8",
|
||||
"__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)",
|
||||
"__XCHAL_ICACHE_SIZE=0",
|
||||
"__cpp_nontype_template_args=201411L",
|
||||
"__INTPTR_TYPE__=int",
|
||||
"__UINT16_TYPE__=short unsigned int",
|
||||
"__WCHAR_TYPE__=short unsigned int",
|
||||
"__XCHAL_HAVE_DEPBITS=0",
|
||||
"__SIZEOF_FLOAT__=4",
|
||||
"__UINTPTR_MAX__=0xffffffffU",
|
||||
"__INT_FAST64_WIDTH__=64",
|
||||
"__cpp_decltype=200707L",
|
||||
"__FLT32_DECIMAL_DIG__=9",
|
||||
"__INT_FAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
|
||||
"__FLT_NORM_MAX__=3.4028234663852886e+38F",
|
||||
"__XCHAL_HAVE_DFP=0",
|
||||
"__FLT32_HAS_INFINITY__=1",
|
||||
"__UINT_FAST64_TYPE__=long long unsigned int",
|
||||
"__cpp_inline_variables=201606L",
|
||||
"__INT_MAX__=0x7fffffff",
|
||||
"__XCHAL_HAVE_EXCLUSIVE=0",
|
||||
"__STDCPP_THREADS__=1",
|
||||
"__INT64_TYPE__=long long int",
|
||||
"__XCHAL_HAVE_DFP_DIV=0",
|
||||
"__FLT_MAX_EXP__=128",
|
||||
"__XCHAL_INST_FETCH_WIDTH=4",
|
||||
"__DBL_MANT_DIG__=53",
|
||||
"__cpp_inheriting_constructors=201511L",
|
||||
"__INT_LEAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__FP_FAST_FMAF32=1",
|
||||
"__WINT_TYPE__=unsigned int",
|
||||
"__UINT_LEAST32_TYPE__=long unsigned int",
|
||||
"__SIZEOF_SHORT__=2",
|
||||
"__FLT32_NORM_MAX__=3.4028234663852886e+38F32",
|
||||
"__LDBL_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_HAVE_S32C1I=1",
|
||||
"__FLT64_MAX__=1.7976931348623157e+308F64",
|
||||
"__WINT_WIDTH__=32",
|
||||
"__cpp_template_auto=201606L",
|
||||
"__INT_LEAST64_WIDTH__=64",
|
||||
"__FLT32X_MAX_10_EXP__=308",
|
||||
"__cpp_namespace_attributes=201411L",
|
||||
"__WCHAR_UNSIGNED__=1",
|
||||
"__LDBL_MAX_10_EXP__=308",
|
||||
"__ATOMIC_RELAXED=0",
|
||||
"__DBL_EPSILON__=double(2.2204460492503131e-16L)",
|
||||
"__XCHAL_HAVE_SEXT=1",
|
||||
"__INT_LEAST32_TYPE__=long int",
|
||||
"__XTENSA_WINDOWED_ABI__=1",
|
||||
"__UINT8_C(c)=c",
|
||||
"__FLT64_MAX_EXP__=1024",
|
||||
"__SIZEOF_WCHAR_T__=2",
|
||||
"__XCHAL_HAVE_FP_POSTINC=1",
|
||||
"__FLT64_NORM_MAX__=1.7976931348623157e+308F64",
|
||||
"__INTMAX_MAX__=0x7fffffffffffffffLL",
|
||||
"__INT_FAST8_TYPE__=int",
|
||||
"__XCHAL_HAVE_MUL32_HIGH=1",
|
||||
"__GNUC_STDC_INLINE__=1",
|
||||
"__FLT64_HAS_DENORM__=1",
|
||||
"__FLT32_EPSILON__=1.1920928955078125e-7F32",
|
||||
"__DBL_DECIMAL_DIG__=17",
|
||||
"__STDC_UTF_32__=1",
|
||||
"__XCHAL_HAVE_FP_DIV=1",
|
||||
"__INT_FAST8_WIDTH__=32",
|
||||
"__FLT32X_MAX__=1.7976931348623157e+308F32x",
|
||||
"__DBL_NORM_MAX__=double(1.7976931348623157e+308L)",
|
||||
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__GCC_DESTRUCTIVE_SIZE=32",
|
||||
"__XTENSA__=1",
|
||||
"__INTMAX_WIDTH__=64",
|
||||
"__ORDER_BIG_ENDIAN__=4321",
|
||||
"__XTHAL_ABI_CALL0=1",
|
||||
"__cpp_runtime_arrays=198712L",
|
||||
"__FLT32_DIG__=6",
|
||||
"__UINT64_TYPE__=long long unsigned int",
|
||||
"__UINT32_C(c)=c ## UL",
|
||||
"__cpp_alias_templates=200704L",
|
||||
"__FLT_DENORM_MIN__=1.4012984643248171e-45F",
|
||||
"__INT8_MAX__=0x7f",
|
||||
"__LONG_WIDTH__=32",
|
||||
"__UINT_FAST32_TYPE__=unsigned int",
|
||||
"__FLT32X_NORM_MAX__=1.7976931348623157e+308F32x",
|
||||
"__CHAR32_TYPE__=long unsigned int",
|
||||
"__FLT_MAX__=3.4028234663852886e+38F",
|
||||
"__cpp_constexpr=201603L",
|
||||
"__XCHAL_HAVE_FP_RSQRT=1",
|
||||
"__INT32_TYPE__=long int",
|
||||
"__SIZEOF_DOUBLE__=8",
|
||||
"__cpp_exceptions=199711L",
|
||||
"__FLT_MIN_10_EXP__=(-37)",
|
||||
"__FLT64_MIN__=2.2250738585072014e-308F64",
|
||||
"__INT_LEAST32_WIDTH__=32",
|
||||
"__INTMAX_TYPE__=long long int",
|
||||
"__XCHAL_HAVE_ABS=1",
|
||||
"__FLT32X_HAS_QUIET_NAN__=1",
|
||||
"__ATOMIC_CONSUME=1",
|
||||
"__XCHAL_NUM_DBREAK=2",
|
||||
"__XCHAL_HAVE_WIDE_BRANCHES=0",
|
||||
"__GNUC_MINOR__=2",
|
||||
"__INT_FAST16_WIDTH__=32",
|
||||
"__UINTMAX_MAX__=0xffffffffffffffffULL",
|
||||
"__FLT32X_DENORM_MIN__=4.9406564584124654e-324F32x",
|
||||
"__cpp_template_template_args=201611L",
|
||||
"__DBL_MAX_10_EXP__=308",
|
||||
"__LDBL_DENORM_MIN__=4.9406564584124654e-324L",
|
||||
"__INT16_C(c)=c",
|
||||
"__STDC__=1",
|
||||
"__PTRDIFF_TYPE__=int",
|
||||
"__LONG_MAX__=0x7fffffffL",
|
||||
"__XCHAL_HAVE_FP_SQRT=1",
|
||||
"__UINT32_TYPE__=long unsigned int",
|
||||
"__FLT32X_MIN_10_EXP__=(-307)",
|
||||
"__UINTPTR_TYPE__=unsigned int",
|
||||
"__LDBL_MIN_10_EXP__=(-307)",
|
||||
"__cpp_generic_lambdas=201304L",
|
||||
"__SIZEOF_LONG_LONG__=8",
|
||||
"__cpp_USER_defined_literals=200809L",
|
||||
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
|
||||
"__FLT_DECIMAL_DIG__=9",
|
||||
"__UINT_FAST16_MAX__=0xffffffffU",
|
||||
"__LDBL_NORM_MAX__=1.7976931348623157e+308L",
|
||||
"__GCC_ATOMIC_SHORT_LOCK_FREE=2",
|
||||
"__XCHAL_HAVE_BE=0",
|
||||
"__UINT_FAST8_TYPE__=unsigned int",
|
||||
"__cpp_init_captures=201304L",
|
||||
"__ATOMIC_ACQ_REL=4",
|
||||
"__ATOMIC_RELEASE=3",
|
||||
"RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB",
|
||||
"USBCON"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Arduino",
|
||||
"compilerPath": "/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/bin/xtensa-esp32-elf-g++",
|
||||
"compilerArgs": [
|
||||
"-MMD",
|
||||
"-w",
|
||||
"-Werror=return-type",
|
||||
"-iprefix"
|
||||
],
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"includePath": [
|
||||
"/home/derdoktor667/Github/DShotRMT/examples/dshot300",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.5-b66b5448-v1/esp32/qio_qspi/include",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/hardware/esp32/3.3.0/cores/esp32",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/hardware/esp32/3.3.0/variants/esp32",
|
||||
"/home/derdoktor667/Arduino/libraries/DShotRMT/src",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/xtensa-esp-elf/esp32",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/backward",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include-fixed",
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include"
|
||||
],
|
||||
"forcedInclude": [
|
||||
"/home/derdoktor667/.arduino15/packages/esp32/hardware/esp32/3.3.0/cores/esp32/Arduino.h"
|
||||
],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"defines": [
|
||||
"F_CPU=240000000L",
|
||||
"ARDUINO=10607",
|
||||
"ARDUINO_ESP32_DEV",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
"ARDUINO_BOARD=\"ESP32_DEV\"",
|
||||
"ARDUINO_VARIANT=\"esp32\"",
|
||||
"ARDUINO_PARTITION_default",
|
||||
"ARDUINO_HOST_OS=\"linux\"",
|
||||
"ARDUINO_FQBN=\"esp32:esp32:esp32:JTAGAdapter=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none,EraseFlash=all,ZigbeeMode=default\"",
|
||||
"ESP32=ESP32",
|
||||
"CORE_DEBUG_LEVEL=0",
|
||||
"ARDUINO_RUNNING_CORE=1",
|
||||
"ARDUINO_EVENT_RUNNING_CORE=1",
|
||||
"ARDUINO_USB_CDC_ON_BOOT=0",
|
||||
"__DBL_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_HAVE_FP=1",
|
||||
"__cpp_nontype_template_parameter_auto=201606L",
|
||||
"__UINT_LEAST16_MAX__=0xffff",
|
||||
"__ATOMIC_ACQUIRE=2",
|
||||
"__FLT_MIN__=1.1754943508222875e-38F",
|
||||
"__GCC_IEC_559_COMPLEX=0",
|
||||
"__XCHAL_HAVE_PREDICTED_BRANCHES=0",
|
||||
"__cpp_aggregate_nsdmi=201304L",
|
||||
"__UINT_LEAST8_TYPE__=unsigned char",
|
||||
"__INTMAX_C(c)=c ## LL",
|
||||
"__XCHAL_HAVE_ADDX=1",
|
||||
"__CHAR_BIT__=8",
|
||||
"__XCHAL_DCACHE_LINESIZE=16",
|
||||
"__XTENSA_MARCH_EARLIEST=260003",
|
||||
"__XCHAL_DCACHE_LINEWIDTH=4",
|
||||
"__UINT8_MAX__=0xff",
|
||||
"__WINT_MAX__=0xffffffffU",
|
||||
"__FLT32_MIN_EXP__=(-125)",
|
||||
"__cpp_static_assert=201411L",
|
||||
"__ORDER_LITTLE_ENDIAN__=1234",
|
||||
"__SIZE_MAX__=0xffffffffU",
|
||||
"__WCHAR_MAX__=0xffff",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1",
|
||||
"__DBL_DENORM_MIN__=double(4.9406564584124654e-324L)",
|
||||
"__GCC_ATOMIC_CHAR_LOCK_FREE=2",
|
||||
"__GCC_IEC_559=0",
|
||||
"__FLT32X_DECIMAL_DIG__=17",
|
||||
"__FLT_EVAL_METHOD__=0",
|
||||
"__cpp_binary_literals=201304L",
|
||||
"__FLT64_DECIMAL_DIG__=17",
|
||||
"__cpp_noexcept_function_type=201510L",
|
||||
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2",
|
||||
"__cpp_variadic_templates=200704L",
|
||||
"__UINT_FAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__SIG_ATOMIC_TYPE__=int",
|
||||
"__DBL_MIN_10_EXP__=(-307)",
|
||||
"__FINITE_MATH_ONLY__=0",
|
||||
"__cpp_variable_templates=201304L",
|
||||
"__XCHAL_HAVE_L32R=1",
|
||||
"__FLT32X_MAX_EXP__=1024",
|
||||
"__GNUC_PATCHLEVEL__=0",
|
||||
"__FLT32_HAS_DENORM__=1",
|
||||
"__UINT_FAST8_MAX__=0xffffffffU",
|
||||
"__cpp_rvalue_reference=200610L",
|
||||
"__XCHAL_HAVE_LOOPS=1",
|
||||
"__cpp_nested_namespace_definitions=201411L",
|
||||
"__XCHAL_DEBUGLEVEL=6",
|
||||
"__INT8_C(c)=c",
|
||||
"__XCHAL_HAVE_DFP_RECIP=0",
|
||||
"__INT_LEAST8_WIDTH__=8",
|
||||
"__cpp_variadic_using=201611L",
|
||||
"__UINT_LEAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__INT_LEAST8_MAX__=0x7f",
|
||||
"__cpp_attributes=200809L",
|
||||
"__cpp_capture_star_this=201603L",
|
||||
"__SHRT_MAX__=0x7fff",
|
||||
"__LDBL_MAX__=1.7976931348623157e+308L",
|
||||
"__cpp_if_constexpr=201606L",
|
||||
"__XCHAL_ICACHE_LINESIZE=16",
|
||||
"__LDBL_IS_IEC_60559__=1",
|
||||
"__UINT_LEAST8_MAX__=0xff",
|
||||
"__GCC_ATOMIC_BOOL_LOCK_FREE=2",
|
||||
"__UINTMAX_TYPE__=long long unsigned int",
|
||||
"__cpp_nsdmi=200809L",
|
||||
"__FLT_EVAL_METHOD_TS_18661_3__=0",
|
||||
"__UINT32_MAX__=0xffffffffUL",
|
||||
"__GXX_EXPERIMENTAL_CXX0X__=1",
|
||||
"__LDBL_MAX_EXP__=1024",
|
||||
"__WINT_MIN__=0U",
|
||||
"__FLT32X_IS_IEC_60559__=1",
|
||||
"__XCHAL_HAVE_THREADPTR=1",
|
||||
"__INT_LEAST16_WIDTH__=16",
|
||||
"__SCHAR_MAX__=0x7f",
|
||||
"__WCHAR_MIN__=0",
|
||||
"__XCHAL_ICACHE_LINEWIDTH=4",
|
||||
"__INT64_C(c)=c ## LL",
|
||||
"__GCC_ATOMIC_POINTER_LOCK_FREE=2",
|
||||
"__ATOMIC_SEQ_CST=5",
|
||||
"__SIZEOF_INT__=4",
|
||||
"__FLT32X_MANT_DIG__=53",
|
||||
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2",
|
||||
"__cpp_aligned_new=201606L",
|
||||
"__XCHAL_HAVE_FP_RECIP=1",
|
||||
"__FLT32_MAX_10_EXP__=38",
|
||||
"__STDC_HOSTED__=1",
|
||||
"__XCHAL_HAVE_MUL32=1",
|
||||
"__XTENSA_EL__=1",
|
||||
"__cpp_decltype_auto=201304L",
|
||||
"__DBL_DIG__=15",
|
||||
"__XCHAL_HAVE_MUL16=1",
|
||||
"__FLT_EPSILON__=1.1920928955078125e-7F",
|
||||
"__GXX_WEAK__=1",
|
||||
"__SHRT_WIDTH__=16",
|
||||
"__FLT32_IS_IEC_60559__=1",
|
||||
"__LDBL_MIN__=2.2250738585072014e-308L",
|
||||
"__DBL_IS_IEC_60559__=1",
|
||||
"__cpp_threadsafe_static_init=200806L",
|
||||
"__cpp_enumerator_attributes=201411L",
|
||||
"__XCHAL_HAVE_MMU=0",
|
||||
"__FLT32X_HAS_INFINITY__=1",
|
||||
"__INT32_MAX__=0x7fffffffL",
|
||||
"__XCHAL_HAVE_DIV32=1",
|
||||
"__INT_WIDTH__=32",
|
||||
"__XTENSA_MARCH_LATEST=260003",
|
||||
"__DECIMAL_DIG__=17",
|
||||
"__FLT64_EPSILON__=2.2204460492503131e-16F64",
|
||||
"__INT16_MAX__=0x7fff",
|
||||
"__FLT64_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_DCACHE_SIZE=0",
|
||||
"__LDBL_HAS_QUIET_NAN__=1",
|
||||
"__cpp_return_type_deduction=201304L",
|
||||
"__XCHAL_HAVE_BOOLEANS=1",
|
||||
"__FLT64_MANT_DIG__=53",
|
||||
"__XTHAL_ABI_WINDOWED=0",
|
||||
"__GNUC__=14",
|
||||
"__GXX_RTTI=1",
|
||||
"__FLT_HAS_DENORM__=1",
|
||||
"__SIZEOF_LONG_DOUBLE__=8",
|
||||
"__XCHAL_HAVE_CONST16=0",
|
||||
"__BIGGEST_ALIGNMENT__=16",
|
||||
"__STDC_UTF_16__=1",
|
||||
"__FLT64_MAX_10_EXP__=308",
|
||||
"__cpp_delegating_constructors=200604L",
|
||||
"__DBL_MAX__=double(1.7976931348623157e+308L)",
|
||||
"__cpp_raw_strings=200710L",
|
||||
"__INT_FAST32_MAX__=0x7fffffff",
|
||||
"__DBL_HAS_INFINITY__=1",
|
||||
"__cpp_deduction_guides=201703L",
|
||||
"__HAVE_SPECULATION_SAFE_VALUE=1",
|
||||
"__cpp_fold_expressions=201603L",
|
||||
"__INTPTR_WIDTH__=32",
|
||||
"__UINT_LEAST32_MAX__=0xffffffffUL",
|
||||
"__FLT32X_HAS_DENORM__=1",
|
||||
"__INT_FAST16_TYPE__=int",
|
||||
"__XCHAL_HAVE_RELEASE_SYNC=1",
|
||||
"__LDBL_HAS_DENORM__=1",
|
||||
"__cplusplus=201703L",
|
||||
"__cpp_ref_qualifiers=200710L",
|
||||
"__INT_LEAST32_MAX__=0x7fffffffL",
|
||||
"__DEPRECATED=1",
|
||||
"__cpp_rvalue_references=200610L",
|
||||
"__DBL_MAX_EXP__=1024",
|
||||
"__WCHAR_WIDTH__=16",
|
||||
"__FLT32_MAX__=3.4028234663852886e+38F32",
|
||||
"__GCC_ATOMIC_LONG_LOCK_FREE=2",
|
||||
"__PTRDIFF_MAX__=0x7fffffff",
|
||||
"__FLT32_HAS_QUIET_NAN__=1",
|
||||
"__GNUG__=14",
|
||||
"__LONG_LONG_MAX__=0x7fffffffffffffffLL",
|
||||
"__SIZEOF_SIZE_T__=4",
|
||||
"__SIZEOF_WINT_T__=4",
|
||||
"__FLT32X_DIG__=15",
|
||||
"__LONG_LONG_WIDTH__=64",
|
||||
"__cpp_initializer_lists=200806L",
|
||||
"__FLT32_MAX_EXP__=128",
|
||||
"__XCHAL_HAVE_MINMAX=1",
|
||||
"__cpp_hex_float=201603L",
|
||||
"__XCHAL_NUM_IBREAK=2",
|
||||
"__GXX_ABI_VERSION=1019",
|
||||
"__FLT_MIN_EXP__=(-125)",
|
||||
"__cpp_lambdas=200907L",
|
||||
"__INT_FAST64_TYPE__=long long int",
|
||||
"__FP_FAST_FMAF=1",
|
||||
"__FLT64_DENORM_MIN__=4.9406564584124654e-324F64",
|
||||
"__DBL_MIN__=double(2.2250738585072014e-308L)",
|
||||
"__SIZEOF_POINTER__=4",
|
||||
"__DBL_HAS_QUIET_NAN__=1",
|
||||
"__FLT32X_EPSILON__=2.2204460492503131e-16F32x",
|
||||
"__XSHAL_HAVE_TEXT_SECTION_LITERALS=1",
|
||||
"__FLT64_MIN_10_EXP__=(-307)",
|
||||
"__REGISTER_PREFIX__",
|
||||
"__UINT16_MAX__=0xffff",
|
||||
"__XSHAL_USE_ABSOLUTE_LITERALS=0",
|
||||
"__LDBL_HAS_INFINITY__=1",
|
||||
"__FLT32_MIN__=1.1754943508222875e-38F32",
|
||||
"__UINT8_TYPE__=unsigned char",
|
||||
"__FLT_DIG__=6",
|
||||
"__NO_INLINE__=1",
|
||||
"__DEC_EVAL_METHOD__=2",
|
||||
"__FLT_MANT_DIG__=24",
|
||||
"__LDBL_DECIMAL_DIG__=17",
|
||||
"__VERSION__=\"14.2.0\"",
|
||||
"__UINT64_C(c)=c ## ULL",
|
||||
"__XCHAL_NUM_AREGS=64",
|
||||
"__cpp_unicode_characters=201411L",
|
||||
"__XCHAL_HAVE_XEA3=0",
|
||||
"__GCC_ATOMIC_INT_LOCK_FREE=2",
|
||||
"__XCHAL_HAVE_DENSITY=1",
|
||||
"__FLT32_MANT_DIG__=24",
|
||||
"__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__XCHAL_HAVE_CLAMPS=0",
|
||||
"__XCHAL_HAVE_DFP_RSQRT=0",
|
||||
"__cpp_aggregate_bases=201603L",
|
||||
"__XCHAL_HAVE_NSA=1",
|
||||
"__XCHAL_HAVE_WINDOWED=1",
|
||||
"__SCHAR_WIDTH__=8",
|
||||
"__INT32_C(c)=c ## L",
|
||||
"__ORDER_PDP_ENDIAN__=3412",
|
||||
"__INT_FAST32_TYPE__=int",
|
||||
"__UINT_LEAST16_TYPE__=short unsigned int",
|
||||
"__DBL_HAS_DENORM__=1",
|
||||
"__XCHAL_HAVE_DEBUG=1",
|
||||
"__cpp_rtti=199711L",
|
||||
"__SIZE_TYPE__=unsigned int",
|
||||
"__UINT64_MAX__=0xffffffffffffffffULL",
|
||||
"__FLT_IS_IEC_60559__=1",
|
||||
"__GNUC_WIDE_EXECUTION_CHARSET_NAME=\"UTF-16LE\"",
|
||||
"__INT8_TYPE__=signed char",
|
||||
"__cpp_digit_separators=201309L",
|
||||
"__ELF__=1",
|
||||
"__XSHAL_ABI=0",
|
||||
"__xtensa__=1",
|
||||
"__FLT_RADIX__=2",
|
||||
"__INT_LEAST16_TYPE__=short int",
|
||||
"__LDBL_EPSILON__=2.2204460492503131e-16L",
|
||||
"__UINTMAX_C(c)=c ## ULL",
|
||||
"__FLT32X_MIN__=2.2250738585072014e-308F32x",
|
||||
"__XCHAL_HAVE_DFP_SQRT=0",
|
||||
"__SIG_ATOMIC_MAX__=0x7fffffff",
|
||||
"__XCHAL_HAVE_MAC16=1",
|
||||
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2",
|
||||
"__USER_LABEL_PREFIX__",
|
||||
"__SIZEOF_PTRDIFF_T__=4",
|
||||
"__XCHAL_MMU_MIN_PTE_PAGE_SIZE=1",
|
||||
"__XCHAL_DCACHE_IS_WRITEBACK=0",
|
||||
"__SIZEOF_LONG__=4",
|
||||
"__LDBL_DIG__=15",
|
||||
"__FLT64_IS_IEC_60559__=1",
|
||||
"__XCHAL_MAX_INSTRUCTION_SIZE=3",
|
||||
"__FLT32X_MIN_EXP__=(-1021)",
|
||||
"__INT_FAST16_MAX__=0x7fffffff",
|
||||
"__GCC_CONSTRUCTIVE_SIZE=32",
|
||||
"__FLT64_DIG__=15",
|
||||
"__UINT_FAST32_MAX__=0xffffffffU",
|
||||
"__UINT_LEAST64_TYPE__=long long unsigned int",
|
||||
"__FLT_HAS_QUIET_NAN__=1",
|
||||
"__FLT_MAX_10_EXP__=38",
|
||||
"__FLT_HAS_INFINITY__=1",
|
||||
"__GNUC_EXECUTION_CHARSET_NAME=\"UTF-8\"",
|
||||
"__CHAR_UNSIGNED__=1",
|
||||
"__cpp_unicode_literals=200710L",
|
||||
"__UINT_FAST16_TYPE__=unsigned int",
|
||||
"__INT_FAST32_WIDTH__=32",
|
||||
"__CHAR16_TYPE__=short unsigned int",
|
||||
"__PRAGMA_REDEFINE_EXTNAME=1",
|
||||
"__SIZE_WIDTH__=32",
|
||||
"__INT_LEAST16_MAX__=0x7fff",
|
||||
"__INT64_MAX__=0x7fffffffffffffffLL",
|
||||
"__FLT32_DENORM_MIN__=1.4012984643248171e-45F32",
|
||||
"__SIG_ATOMIC_WIDTH__=32",
|
||||
"__INT_LEAST64_TYPE__=long long int",
|
||||
"__INT16_TYPE__=short int",
|
||||
"__INT_LEAST8_TYPE__=signed char",
|
||||
"__cpp_structured_bindings=201606L",
|
||||
"__INT_FAST8_MAX__=0x7fffffff",
|
||||
"__INTPTR_MAX__=0x7fffffff",
|
||||
"__cpp_sized_deallocation=201309L",
|
||||
"__cpp_guaranteed_copy_elision=201606L",
|
||||
"__FLT64_HAS_QUIET_NAN__=1",
|
||||
"__FLT32_MIN_10_EXP__=(-37)",
|
||||
"__EXCEPTIONS=1",
|
||||
"__UINT16_C(c)=c",
|
||||
"__XCHAL_M_STAGE=3",
|
||||
"__PTRDIFF_WIDTH__=32",
|
||||
"__LDBL_MANT_DIG__=53",
|
||||
"__cpp_range_based_for=201603L",
|
||||
"__FLT64_HAS_INFINITY__=1",
|
||||
"__STDCPP_DEFAULT_NEW_ALIGNMENT__=8",
|
||||
"__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)",
|
||||
"__XCHAL_ICACHE_SIZE=0",
|
||||
"__cpp_nontype_template_args=201411L",
|
||||
"__INTPTR_TYPE__=int",
|
||||
"__UINT16_TYPE__=short unsigned int",
|
||||
"__WCHAR_TYPE__=short unsigned int",
|
||||
"__XCHAL_HAVE_DEPBITS=0",
|
||||
"__SIZEOF_FLOAT__=4",
|
||||
"__UINTPTR_MAX__=0xffffffffU",
|
||||
"__INT_FAST64_WIDTH__=64",
|
||||
"__cpp_decltype=200707L",
|
||||
"__FLT32_DECIMAL_DIG__=9",
|
||||
"__INT_FAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
|
||||
"__FLT_NORM_MAX__=3.4028234663852886e+38F",
|
||||
"__XCHAL_HAVE_DFP=0",
|
||||
"__FLT32_HAS_INFINITY__=1",
|
||||
"__UINT_FAST64_TYPE__=long long unsigned int",
|
||||
"__cpp_inline_variables=201606L",
|
||||
"__INT_MAX__=0x7fffffff",
|
||||
"__XCHAL_HAVE_EXCLUSIVE=0",
|
||||
"__STDCPP_THREADS__=1",
|
||||
"__INT64_TYPE__=long long int",
|
||||
"__XCHAL_HAVE_DFP_DIV=0",
|
||||
"__FLT_MAX_EXP__=128",
|
||||
"__XCHAL_INST_FETCH_WIDTH=4",
|
||||
"__DBL_MANT_DIG__=53",
|
||||
"__cpp_inheriting_constructors=201511L",
|
||||
"__INT_LEAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__FP_FAST_FMAF32=1",
|
||||
"__WINT_TYPE__=unsigned int",
|
||||
"__UINT_LEAST32_TYPE__=long unsigned int",
|
||||
"__SIZEOF_SHORT__=2",
|
||||
"__FLT32_NORM_MAX__=3.4028234663852886e+38F32",
|
||||
"__LDBL_MIN_EXP__=(-1021)",
|
||||
"__XCHAL_HAVE_S32C1I=1",
|
||||
"__FLT64_MAX__=1.7976931348623157e+308F64",
|
||||
"__WINT_WIDTH__=32",
|
||||
"__cpp_template_auto=201606L",
|
||||
"__INT_LEAST64_WIDTH__=64",
|
||||
"__FLT32X_MAX_10_EXP__=308",
|
||||
"__cpp_namespace_attributes=201411L",
|
||||
"__WCHAR_UNSIGNED__=1",
|
||||
"__LDBL_MAX_10_EXP__=308",
|
||||
"__ATOMIC_RELAXED=0",
|
||||
"__DBL_EPSILON__=double(2.2204460492503131e-16L)",
|
||||
"__XCHAL_HAVE_SEXT=1",
|
||||
"__INT_LEAST32_TYPE__=long int",
|
||||
"__XTENSA_WINDOWED_ABI__=1",
|
||||
"__UINT8_C(c)=c",
|
||||
"__FLT64_MAX_EXP__=1024",
|
||||
"__SIZEOF_WCHAR_T__=2",
|
||||
"__XCHAL_HAVE_FP_POSTINC=1",
|
||||
"__FLT64_NORM_MAX__=1.7976931348623157e+308F64",
|
||||
"__INTMAX_MAX__=0x7fffffffffffffffLL",
|
||||
"__INT_FAST8_TYPE__=int",
|
||||
"__XCHAL_HAVE_MUL32_HIGH=1",
|
||||
"__GNUC_STDC_INLINE__=1",
|
||||
"__FLT64_HAS_DENORM__=1",
|
||||
"__FLT32_EPSILON__=1.1920928955078125e-7F32",
|
||||
"__DBL_DECIMAL_DIG__=17",
|
||||
"__STDC_UTF_32__=1",
|
||||
"__XCHAL_HAVE_FP_DIV=1",
|
||||
"__INT_FAST8_WIDTH__=32",
|
||||
"__FLT32X_MAX__=1.7976931348623157e+308F32x",
|
||||
"__DBL_NORM_MAX__=double(1.7976931348623157e+308L)",
|
||||
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__GCC_DESTRUCTIVE_SIZE=32",
|
||||
"__XTENSA__=1",
|
||||
"__INTMAX_WIDTH__=64",
|
||||
"__ORDER_BIG_ENDIAN__=4321",
|
||||
"__XTHAL_ABI_CALL0=1",
|
||||
"__cpp_runtime_arrays=198712L",
|
||||
"__FLT32_DIG__=6",
|
||||
"__UINT64_TYPE__=long long unsigned int",
|
||||
"__UINT32_C(c)=c ## UL",
|
||||
"__cpp_alias_templates=200704L",
|
||||
"__FLT_DENORM_MIN__=1.4012984643248171e-45F",
|
||||
"__INT8_MAX__=0x7f",
|
||||
"__LONG_WIDTH__=32",
|
||||
"__UINT_FAST32_TYPE__=unsigned int",
|
||||
"__FLT32X_NORM_MAX__=1.7976931348623157e+308F32x",
|
||||
"__CHAR32_TYPE__=long unsigned int",
|
||||
"__FLT_MAX__=3.4028234663852886e+38F",
|
||||
"__cpp_constexpr=201603L",
|
||||
"__XCHAL_HAVE_FP_RSQRT=1",
|
||||
"__INT32_TYPE__=long int",
|
||||
"__SIZEOF_DOUBLE__=8",
|
||||
"__cpp_exceptions=199711L",
|
||||
"__FLT_MIN_10_EXP__=(-37)",
|
||||
"__FLT64_MIN__=2.2250738585072014e-308F64",
|
||||
"__INT_LEAST32_WIDTH__=32",
|
||||
"__INTMAX_TYPE__=long long int",
|
||||
"__XCHAL_HAVE_ABS=1",
|
||||
"__FLT32X_HAS_QUIET_NAN__=1",
|
||||
"__ATOMIC_CONSUME=1",
|
||||
"__XCHAL_NUM_DBREAK=2",
|
||||
"__XCHAL_HAVE_WIDE_BRANCHES=0",
|
||||
"__GNUC_MINOR__=2",
|
||||
"__INT_FAST16_WIDTH__=32",
|
||||
"__UINTMAX_MAX__=0xffffffffffffffffULL",
|
||||
"__FLT32X_DENORM_MIN__=4.9406564584124654e-324F32x",
|
||||
"__cpp_template_template_args=201611L",
|
||||
"__DBL_MAX_10_EXP__=308",
|
||||
"__LDBL_DENORM_MIN__=4.9406564584124654e-324L",
|
||||
"__INT16_C(c)=c",
|
||||
"__STDC__=1",
|
||||
"__PTRDIFF_TYPE__=int",
|
||||
"__LONG_MAX__=0x7fffffffL",
|
||||
"__XCHAL_HAVE_FP_SQRT=1",
|
||||
"__UINT32_TYPE__=long unsigned int",
|
||||
"__FLT32X_MIN_10_EXP__=(-307)",
|
||||
"__UINTPTR_TYPE__=unsigned int",
|
||||
"__LDBL_MIN_10_EXP__=(-307)",
|
||||
"__cpp_generic_lambdas=201304L",
|
||||
"__SIZEOF_LONG_LONG__=8",
|
||||
"__cpp_user_defined_literals=200809L",
|
||||
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
|
||||
"__FLT_DECIMAL_DIG__=9",
|
||||
"__UINT_FAST16_MAX__=0xffffffffU",
|
||||
"__LDBL_NORM_MAX__=1.7976931348623157e+308L",
|
||||
"__GCC_ATOMIC_SHORT_LOCK_FREE=2",
|
||||
"__XCHAL_HAVE_BE=0",
|
||||
"__UINT_FAST8_TYPE__=unsigned int",
|
||||
"__cpp_init_captures=201304L",
|
||||
"__ATOMIC_ACQ_REL=4",
|
||||
"__ATOMIC_RELEASE=3",
|
||||
"USBCON"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"C_Cpp.default.compilerPath": "~/.arduino15/packages/esp32/tools/esp-x32/2411/bin/xtensa-esp32-elf-g++",
|
||||
"files.associations": {
|
||||
".fantomasignore": "ignore",
|
||||
"string_view": "cpp"
|
||||
}
|
||||
}
|
||||
102
README.md
102
README.md
|
|
@ -57,7 +57,7 @@ The library requires these additional libraries for full functionality:
|
|||
**Core DShotRMT (always required):**
|
||||
- ESP32 Arduino Core
|
||||
|
||||
**Web Interface Example (dshot300.ino):**
|
||||
**Web Interface Example (web_control.ino / web_client.ino):**
|
||||
```ini
|
||||
lib_deps =
|
||||
https://github.com/derdoktor667/DShotRMT
|
||||
|
|
@ -101,92 +101,6 @@ void loop() {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Web Control Interface
|
||||
|
||||
```cpp
|
||||
#include <DShotRMT.h>
|
||||
#include <WiFi.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
DShotRMT motor(17, DSHOT300, false);
|
||||
AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
|
||||
void setup() {
|
||||
// Initialize motor
|
||||
motor.begin();
|
||||
|
||||
// Create WiFi Access Point
|
||||
WiFi.softAP("DShotRMT Control", "12345678");
|
||||
|
||||
// Setup web interface
|
||||
ws.onEvent(onWsEvent);
|
||||
server.addHandler(&ws);
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
request->send_P(200, "text/html", index_html);
|
||||
});
|
||||
server.begin();
|
||||
|
||||
// Access at http://10.10.10.1
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Handle WebSocket communication and motor control
|
||||
ws.cleanupClients();
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Command Management
|
||||
|
||||
```cpp
|
||||
#include <DShotRMT.h>
|
||||
#include <DShotCommandManager.h>
|
||||
|
||||
DShotRMT motor(17, DSHOT300, false);
|
||||
DShotCommandManager cmdManager(motor);
|
||||
|
||||
void setup() {
|
||||
motor.begin();
|
||||
cmdManager.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// High-level ESC control
|
||||
cmdManager.stopMotor();
|
||||
cmdManager.activateBeacon(1);
|
||||
cmdManager.setSpinDirection(false);
|
||||
cmdManager.executeInitSequence();
|
||||
}
|
||||
```
|
||||
|
||||
### Bidirectional DShot (RPM Telemetry)
|
||||
|
||||
```cpp
|
||||
#include <DShotRMT.h>
|
||||
|
||||
// Enable bidirectional mode for telemetry
|
||||
DShotRMT motor(17, DSHOT300, true);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
motor.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Send throttle
|
||||
motor.sendThrottle(1000);
|
||||
|
||||
// Get telemetry data
|
||||
dshot_telemetry_result_t telemetry = motor.getTelemetry(14); // 14 magnets
|
||||
if (telemetry.success) {
|
||||
Serial.printf("eRPM: %u, Motor RPM: %u\n",
|
||||
telemetry.erpm,
|
||||
telemetry.motor_rpm);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Web Control Interface
|
||||
|
|
@ -228,7 +142,7 @@ Make sure you are using these libraries for [ESPAsyncWebServer](https://github.c
|
|||
|
||||
The library includes comprehensive examples:
|
||||
|
||||
### 1. Basic DShot Control with Web Interface (`dshot300.ino`)
|
||||
### 1. Basic DShot Control with Web Interface (`web_control.ino`)
|
||||
- **Web Control Interface:** Modern responsive web UI accessible at `http://10.10.10.1`
|
||||
- **WiFi Access Point:** Creates hotspot "DShotRMT Control" for wireless control
|
||||
- **Safety Features:** Arming/disarming system with motor safety lockout
|
||||
|
|
@ -257,8 +171,8 @@ Interactive ESC control with full menu system:
|
|||
0 - Emergency Stop
|
||||
|
||||
Advanced Commands:
|
||||
cmd <number> - Send DShot command (0-47)
|
||||
throttle <value> - Set throttle (48-2047)
|
||||
cmd <number> - Send DShot command (0 - 47)
|
||||
throttle <value> - Set throttle (48 - 2047)
|
||||
repeat cmd <num> count <count> - Repeat command
|
||||
```
|
||||
|
||||
|
|
@ -274,6 +188,8 @@ Advanced Commands:
|
|||
| 300 | 300 kbit/s | 2.50 | 1.25 | 3.33 | ~53.28 |
|
||||
| 600 | 600 kbit/s | 1.25 | 0.625 | 1.67 | ~26.72 |
|
||||
|
||||
For DShot, T1H length is always double T0H length.
|
||||
|
||||
### GPIO Configuration
|
||||
```cpp
|
||||
// Using GPIO number
|
||||
|
|
@ -294,14 +210,14 @@ DShotRMT motor(17, DSHOT300, true);
|
|||
| Command | Value | Description | Usage |
|
||||
|---------|-------|-------------|-------|
|
||||
| MOTOR_STOP | 0 | Stop motor | Always available |
|
||||
| BEACON1 - 5 | 1 - 5 | Motor beeping | Motor identification |
|
||||
| BEACON 1 - 5 | 1 - 5 | Motor beeping | Motor identification |
|
||||
| ESC_INFO | 6 | Request ESC info | Get ESC version/settings |
|
||||
| SPIN_DIRECTION_1/2 | 7 - 8 | Set spin direction | Motor configuration |
|
||||
| 3D_MODE_OFF/ON | 9 - 10 | 3D mode control | Bidirectional flight |
|
||||
| SAVE_SETTINGS | 12 | Save to EEPROM | Permanent configuration |
|
||||
| EXTENDED_TELEMETRY_ENABLE/DISABLE | 13 - 14 | Telemetry control | Data transmission |
|
||||
| SPIN_DIRECTION_NORMAL/REVERSED | 20 - 21 | Spin direction | Alias commands |
|
||||
| LED0-3_ON/OFF | 22 - 29 | LED control | BLHeli32 only |
|
||||
| LED 0-3_ON/OFF | 22 - 29 | LED control | BLHeli32 only |
|
||||
| AUDIO_STREAM_MODE | 30 | Audio mode toggle | KISS ESCs |
|
||||
| SILENT_MODE | 31 | Silent mode toggle | KISS ESCs |
|
||||
|
||||
|
|
@ -341,7 +257,7 @@ The library utilizes the ESP32's RMT (Remote Control) peripheral for precise sig
|
|||
### Advantages
|
||||
- **Hardware Timing:** No CPU intervention during transmission
|
||||
- **Concurrent Operation:** Multiple channels can run simultaneously
|
||||
- **DMA Support:** Efficient memory-to-peripheral transfers
|
||||
- **DMA Support:** Efficient, automatic memory-to-peripheral transfers
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -308,13 +308,6 @@ void printSystemStatus()
|
|||
USB_SERIAL.println("\n=== System Status ===");
|
||||
USB_SERIAL.printf("Current throttle: %u\n", throttle_now);
|
||||
USB_SERIAL.printf("Continuous mode: %s\n", throttle_now > 0 ? "ACTIVE" : "INACTIVE");
|
||||
USB_SERIAL.printf("GPIO Pin: %d\n", motor01.getGPIO());
|
||||
USB_SERIAL.printf("DShot Mode: DSHOT%d\n",
|
||||
motor01.getMode() == DSHOT150 ? 150 : motor01.getMode() == DSHOT300 ? 300
|
||||
: motor01.getMode() == DSHOT600 ? 600
|
||||
: motor01.getMode() == DSHOT1200 ? 1200
|
||||
: 0);
|
||||
USB_SERIAL.printf("Bidirectional: %s\n", motor01.is_bidirectional() ? "YES" : "NO");
|
||||
USB_SERIAL.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
|
||||
USB_SERIAL.printf("Uptime: %lu seconds\n", millis() / 1000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <WiFi.h>
|
||||
|
||||
#include <DShotRMT.h>
|
||||
#include <web_content.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncTCP.h>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <WiFi.h>
|
||||
|
||||
#include <DShotRMT.h>
|
||||
#include <web_content.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncTCP.h>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
name=DShotRMT
|
||||
version=0.7.6
|
||||
version=0.8.0
|
||||
author=Wastl Kraus <wir-sind-die-matrix.de>
|
||||
maintainer=Wastl Kraus <wir-sind-die-matrix.de>
|
||||
license=MIT
|
||||
|
|
@ -8,5 +8,5 @@ paragraph=This library can control a BlHeli_S by using encoded DShot commands. F
|
|||
category=Signal Input/Output
|
||||
url=https://github.com/derdoktor667/DShotRMT
|
||||
architectures=esp32
|
||||
provides_includes=DShotRMT.h, DShotCommandManager.h, dshot_commands.h, web_content.h
|
||||
provides_includes=DShotRMT.h, DShotCommandManager.h, dshot_commands.h
|
||||
depends=ArduinoJson
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <DShotRMT.h>
|
||||
#include <dshot_commands.h>
|
||||
|
||||
// Command item
|
||||
typedef struct
|
||||
|
|
|
|||
733
src/DShotRMT.cpp
733
src/DShotRMT.cpp
|
|
@ -8,27 +8,41 @@
|
|||
|
||||
#include "DShotRMT.h"
|
||||
|
||||
// Static Data & Helper Functions
|
||||
// Timing parameters for each DShot mode
|
||||
// Format: {frame_length_us, ticks_per_bit, ticks_one_high, ticks_one_low, ticks_zero_high, ticks_zero_low}
|
||||
static constexpr dshot_timing_t DSHOT_TIMINGS[] = {
|
||||
{0, 0, 0, 0, 0, 0}, // DSHOT_OFF
|
||||
{128, 64, 48, 16, 24, 40}, // DSHOT150
|
||||
{64, 32, 24, 8, 12, 20}, // DSHOT300
|
||||
{32, 16, 12, 4, 6, 10}, // DSHOT600
|
||||
{16, 8, 6, 2, 3, 5} // DSHOT1200
|
||||
};
|
||||
// Format: {bit_length_us, t1h_length_us}
|
||||
static constexpr dshot_timing_us_t DSHOT_TIMING_US[] = {
|
||||
{0.00, 0.00},
|
||||
{6.67, 5.00},
|
||||
{3.33, 2.50},
|
||||
{1.67, 1.25},
|
||||
{0.83, 0.67}};
|
||||
|
||||
// Helper function to print DShot results and telemetry
|
||||
void printDShotResult(dshot_result_t &result, Stream &output)
|
||||
{
|
||||
output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", result.msg);
|
||||
|
||||
// Print telemetry data if available
|
||||
if (result.success && (result.erpm > 0 || result.motor_rpm > 0))
|
||||
{
|
||||
output.printf(" | eRPM: %u, Motor RPM: %u", result.erpm, result.motor_rpm);
|
||||
}
|
||||
|
||||
output.println();
|
||||
}
|
||||
|
||||
// Constructors & Destructor
|
||||
// Constructor with GPIO number
|
||||
DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional)
|
||||
: _gpio(gpio),
|
||||
_mode(mode),
|
||||
_is_bidirectional(is_bidirectional),
|
||||
_last_erpm_atomic(0),
|
||||
_telemetry_ready_flag(false),
|
||||
_dshot_timing(DSHOT_TIMING_US[mode]),
|
||||
_frame_timer_us(0),
|
||||
_timing_config(DSHOT_TIMINGS[mode]),
|
||||
_rmt_ticks{0},
|
||||
_last_throttle(DSHOT_CMD_MOTOR_STOP),
|
||||
_last_transmission_time(0),
|
||||
_last_transmission_time_us(0),
|
||||
_parsed_packet(0),
|
||||
_packet{0},
|
||||
_bitPositions{0},
|
||||
|
|
@ -39,30 +53,27 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional)
|
|||
_dshot_encoder(nullptr),
|
||||
_tx_channel_config{},
|
||||
_rx_channel_config{},
|
||||
_transmit_config{},
|
||||
_receive_config{}
|
||||
_rmt_tx_config{},
|
||||
_rmt_rx_config{},
|
||||
_rx_event_callbacks{},
|
||||
_last_erpm_atomic(0),
|
||||
_telemetry_ready_flag_atomic(false)
|
||||
{
|
||||
// Calculate frame timing including switch/pause time
|
||||
_frame_timer_us = _timing_config.frame_length_us + DSHOT_PAUSE_US;
|
||||
|
||||
// Double frame time for bidirectional mode (includes response time)
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
_frame_timer_us = (_frame_timer_us << 1);
|
||||
}
|
||||
// Configure RMT ticks for DShot timings
|
||||
_preCalculateRMTTicks();
|
||||
}
|
||||
|
||||
// Constructor using pin number
|
||||
DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional)
|
||||
: DShotRMT((gpio_num_t)pin_nr, mode, is_bidirectional)
|
||||
: DShotRMT(static_cast<gpio_num_t>(pin_nr), mode, is_bidirectional)
|
||||
{
|
||||
// Delegates to primary constructor with type cast
|
||||
}
|
||||
|
||||
// Destructor for "better" code
|
||||
// Destructor
|
||||
DShotRMT::~DShotRMT()
|
||||
{
|
||||
// ...TX
|
||||
// Cleanup TX channel
|
||||
if (_rmt_tx_channel)
|
||||
{
|
||||
if (rmt_disable(_rmt_tx_channel) == DSHOT_OK)
|
||||
|
|
@ -72,7 +83,7 @@ DShotRMT::~DShotRMT()
|
|||
}
|
||||
}
|
||||
|
||||
// ...RX
|
||||
// Cleanup RX channel
|
||||
if (_rmt_rx_channel)
|
||||
{
|
||||
if (rmt_disable(_rmt_rx_channel) == DSHOT_OK)
|
||||
|
|
@ -82,7 +93,7 @@ DShotRMT::~DShotRMT()
|
|||
}
|
||||
}
|
||||
|
||||
// ...Encoder
|
||||
// Cleanup encoder
|
||||
if (_dshot_encoder)
|
||||
{
|
||||
rmt_del_encoder(_dshot_encoder);
|
||||
|
|
@ -90,10 +101,12 @@ DShotRMT::~DShotRMT()
|
|||
}
|
||||
}
|
||||
|
||||
// Init DShotRMT
|
||||
|
||||
// Public Core Functions
|
||||
// Initialize DShotRMT
|
||||
dshot_result_t DShotRMT::begin()
|
||||
{
|
||||
// Init RX channel first
|
||||
// Init RX channel first (for bidirectional mode)
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
if (!_initRXChannel().success)
|
||||
|
|
@ -120,105 +133,6 @@ dshot_result_t DShotRMT::begin()
|
|||
return {true, INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Init RMT TX channel
|
||||
dshot_result_t DShotRMT::_initTXChannel()
|
||||
{
|
||||
// Configure TX channel
|
||||
_tx_channel_config.gpio_num = _gpio;
|
||||
_tx_channel_config.clk_src = DSHOT_CLOCK_SRC_DEFAULT;
|
||||
_tx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION;
|
||||
_tx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS;
|
||||
_tx_channel_config.trans_queue_depth = RMT_QUEUE_DEPTH;
|
||||
|
||||
// Config RMT TX
|
||||
_transmit_config.loop_count = 0; // No automatic loops - real-time calculation
|
||||
_transmit_config.flags.eot_level = _is_bidirectional ? 1 : 0; // Telemetric Bit used as bidir flag
|
||||
|
||||
// Create RMT TX channel
|
||||
if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, TX_INIT_FAILED};
|
||||
}
|
||||
|
||||
//
|
||||
if (rmt_enable(_rmt_tx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, TX_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, TX_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Init RMT RX channel
|
||||
dshot_result_t DShotRMT::_initRXChannel()
|
||||
{
|
||||
|
||||
// Direct RMT symbol processing - Performance optimized
|
||||
_rx_event_callbacks.on_recv_done = _rmt_rx_done_callback;
|
||||
|
||||
// Config RMT RX
|
||||
_rx_channel_config.gpio_num = _gpio;
|
||||
_rx_channel_config.clk_src = DSHOT_CLOCK_SRC_DEFAULT;
|
||||
_rx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION;
|
||||
_rx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS;
|
||||
|
||||
// Config RMT RX parameters
|
||||
_receive_config.signal_range_min_ns = DSHOT_PULSE_MIN;
|
||||
_receive_config.signal_range_max_ns = DSHOT_PULSE_MAX;
|
||||
|
||||
// Create RMT RX channel
|
||||
if (rmt_new_rx_channel(&_rx_channel_config, &_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RX_INIT_FAILED};
|
||||
}
|
||||
|
||||
//
|
||||
if (rmt_enable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RX_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, RX_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Callback for RMT RX
|
||||
bool DShotRMT::_rmt_rx_done_callback(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data)
|
||||
{
|
||||
DShotRMT *instance = static_cast<DShotRMT *>(user_data);
|
||||
|
||||
// ISR check for valid data
|
||||
if (edata && edata->num_symbols >= GCR_BITS_PER_FRAME && edata->num_symbols <= GCR_BITS_PER_FRAME)
|
||||
{
|
||||
|
||||
// Direct decoding
|
||||
uint16_t erpm = instance->_decodeDShotFrame(edata->received_symbols);
|
||||
|
||||
if (erpm != DSHOT_NULL_PACKET)
|
||||
{
|
||||
// Atomic writes - thread-safe
|
||||
instance->_last_erpm_atomic = erpm;
|
||||
instance->_telemetry_ready_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize DShot encoder
|
||||
dshot_result_t DShotRMT::_initDShotEncoder()
|
||||
{
|
||||
// Create copy encoder configuration
|
||||
rmt_copy_encoder_config_t encoder_config = {};
|
||||
|
||||
// Create encoder instance
|
||||
if (rmt_new_copy_encoder(&encoder_config, &_dshot_encoder) != DSHOT_OK)
|
||||
{
|
||||
return {false, ENCODER_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, TX_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Send throttle value
|
||||
dshot_result_t DShotRMT::sendThrottle(uint16_t throttle)
|
||||
{
|
||||
|
|
@ -258,7 +172,7 @@ dshot_result_t DShotRMT::sendCommand(uint16_t command)
|
|||
dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count)
|
||||
{
|
||||
// Result container with unified structure
|
||||
dshot_result_t result = {false, TELEMETRY_FAILED, NO_DSHOT_ERPM, NO_DSHOT_RPM};
|
||||
dshot_result_t result = {false, TELEMETRY_FAILED, NO_DSHOT_TELEMETRY, NO_DSHOT_TELEMETRY};
|
||||
|
||||
// Check if bidirectional mode is enabled
|
||||
if (!_is_bidirectional)
|
||||
|
|
@ -267,17 +181,17 @@ dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count)
|
|||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
if (_telemetry_ready_flag)
|
||||
// Check for new telemetry data
|
||||
if (_telemetry_ready_flag_atomic)
|
||||
{
|
||||
_telemetry_ready_flag = false;
|
||||
_telemetry_ready_flag_atomic = false;
|
||||
|
||||
uint16_t erpm = _last_erpm_atomic;
|
||||
|
||||
//
|
||||
// Calculate motor RPM from eRPM
|
||||
if (erpm != DSHOT_NULL_PACKET && magnet_count >= 1)
|
||||
{
|
||||
uint8_t pole_pairs = max(MIN_POLE_PAIRS, (magnet_count / MAGNETS_PER_POLE_PAIR));
|
||||
uint8_t pole_pairs = max(POLE_PAIRS_MIN, (magnet_count / MAGNETS_PER_POLE_PAIR));
|
||||
uint32_t motor_rpm = (erpm / pole_pairs);
|
||||
|
||||
result.success = true;
|
||||
|
|
@ -290,216 +204,7 @@ dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Build a complete DShot packet
|
||||
dshot_packet_t DShotRMT::_buildDShotPacket(const uint16_t value)
|
||||
{
|
||||
// Init packet structure
|
||||
dshot_packet_t packet = {};
|
||||
|
||||
// Re-check for valid value
|
||||
if (value > DSHOT_THROTTLE_MAX)
|
||||
{
|
||||
// Something is really wrong
|
||||
return packet;
|
||||
}
|
||||
|
||||
// Build packet
|
||||
packet.throttle_value = value & 0b0000011111111111;
|
||||
packet.telemetric_request = _is_bidirectional ? 1 : 0;
|
||||
|
||||
// CRC is calculated over 11bit
|
||||
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
|
||||
packet.checksum = _calculateCRC(data);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
// Parse DShot packet into 16-bit format
|
||||
uint16_t DShotRMT::_parseDShotPacket(const dshot_packet_t &packet)
|
||||
{
|
||||
// Parse DShot frame into "raw" 16 bit value
|
||||
uint16_t data_and_telemetry = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
uint16_t parsed_packet = (data_and_telemetry << 4) | packet.checksum;
|
||||
|
||||
return parsed_packet;
|
||||
}
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t DShotRMT::_calculateCRC(const uint16_t data)
|
||||
{
|
||||
// DShot CRC
|
||||
uint16_t crc = (data ^ (data >> 4) ^ (data >> 8)) & DSHOT_CRC_MASK;
|
||||
|
||||
// Invert CRC for bidirectional DShot mode
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
crc = (~crc) & DSHOT_CRC_MASK;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
// Per calculate bits - Performance optimized
|
||||
void DShotRMT::_preCalculateBitPositions()
|
||||
{
|
||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
_bitPositions[i] = DSHOT_BITS_PER_FRAME - 1 - i;
|
||||
}
|
||||
}
|
||||
|
||||
// Transmit DShot packet via RMT
|
||||
dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet)
|
||||
{
|
||||
// Check timing requirements
|
||||
if (!_timer_signal())
|
||||
{
|
||||
return {false, TIMING_CORRECTION};
|
||||
}
|
||||
|
||||
// Enable RMT RX before RMT TX
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
// Calculate transmission data size
|
||||
size_t rx_size_bytes = GCR_BITS_PER_FRAME * sizeof(rmt_symbol_word_t);
|
||||
|
||||
// Performance reasons
|
||||
rmt_symbol_word_t rx_symbols[DSHOT_BITS_PER_FRAME];
|
||||
|
||||
if (rmt_receive(_rmt_rx_channel, rx_symbols, rx_size_bytes, &_receive_config) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Local for performance
|
||||
rmt_symbol_word_t tx_symbols[DSHOT_BITS_PER_FRAME];
|
||||
|
||||
// Encode DShot packet into RMT symbols
|
||||
_encodeDShotFrame(packet, tx_symbols);
|
||||
|
||||
// Calculate transmission data size
|
||||
size_t tx_size_bytes = DSHOT_BITS_PER_FRAME * sizeof(rmt_symbol_word_t);
|
||||
|
||||
// TODO: Find out, why this is needed
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
// Disable RMT RX for sending
|
||||
if (rmt_disable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Perform RMT transmission
|
||||
if (rmt_transmit(_rmt_tx_channel, _dshot_encoder, tx_symbols, tx_size_bytes, &_transmit_config) != DSHOT_OK)
|
||||
{
|
||||
return {false, TRANSMISSION_FAILED};
|
||||
}
|
||||
|
||||
// Re-enable RMT RX
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
if (rmt_enable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Update timestamp and calculate execution time
|
||||
_timer_reset();
|
||||
|
||||
return {true, TRANSMISSION_SUCCESS};
|
||||
}
|
||||
|
||||
// Encode DShot packet into RMT symbol format (placed in IRAM for performance)
|
||||
bool DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols)
|
||||
{
|
||||
_parsed_packet = _parseDShotPacket(packet);
|
||||
|
||||
// Decode MSB
|
||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
// Use precalculated bit positions - Performace optimized
|
||||
int bit_position = _bitPositions[i];
|
||||
|
||||
bool bit = (_parsed_packet >> bit_position) & 0b0000000000000001;
|
||||
symbols[i].level0 = _level0;
|
||||
symbols[i].duration0 = bit ? _timing_config.ticks_one_high : _timing_config.ticks_zero_high;
|
||||
symbols[i].level1 = _level1;
|
||||
symbols[i].duration1 = bit ? _timing_config.ticks_one_low : _timing_config.ticks_zero_low;
|
||||
}
|
||||
|
||||
return DSHOT_OK;
|
||||
}
|
||||
|
||||
// Decodes a DShot telemetry frame from received RMT symbols.
|
||||
uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols)
|
||||
{
|
||||
uint32_t gcr_value = 0;
|
||||
|
||||
// Decode GCR symbols into a 21-bit value.
|
||||
// '1' has a longer low pulse (duration0 > duration1).
|
||||
// '0' has a longer high pulse (duration1 > duration0).
|
||||
for (size_t i = 0; i < GCR_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
bool bit_is_one = symbols[i].duration0 > symbols[i].duration1;
|
||||
gcr_value = (gcr_value << 1) | bit_is_one;
|
||||
}
|
||||
|
||||
// Perform GCR decoding: data = gcr ^ (gcr >> 1).
|
||||
uint32_t decoded_frame = gcr_value ^ (gcr_value >> 1);
|
||||
|
||||
// Extract 16 data bits and 4 CRC bits from 20-bit frame.
|
||||
// The first bit of the GCR frame is a start bit and is discarded.
|
||||
uint16_t data_and_crc = (decoded_frame & DSHOT_FULL_PACKET);
|
||||
|
||||
// Cutting 4 bits?
|
||||
uint16_t received_data = data_and_crc >> 4;
|
||||
|
||||
// Masking CRC
|
||||
uint16_t received_crc = data_and_crc & DSHOT_CRC_MASK;
|
||||
|
||||
// Telemetry request bit has to be 1
|
||||
if (!(received_data & (1 << 11)))
|
||||
{
|
||||
return DSHOT_NULL_PACKET;
|
||||
}
|
||||
|
||||
// Calculate expected CRC
|
||||
uint16_t data_for_crc = received_data;
|
||||
uint16_t calculated_crc = _calculateCRC(data_for_crc);
|
||||
|
||||
// Validate CRC
|
||||
if (received_crc != calculated_crc)
|
||||
{
|
||||
return DSHOT_NULL_PACKET;
|
||||
}
|
||||
|
||||
// Return the eRPM value (first 11 bits of received data).
|
||||
return received_data & DSHOT_THROTTLE_MAX;
|
||||
}
|
||||
|
||||
// Check if enough time has passed for next transmission
|
||||
bool DShotRMT::_timer_signal()
|
||||
{
|
||||
uint64_t current_time = esp_timer_get_time();
|
||||
|
||||
// Handle potential overflow
|
||||
uint64_t elapsed = current_time - _last_transmission_time;
|
||||
|
||||
return elapsed >= _frame_timer_us;
|
||||
}
|
||||
|
||||
// Reset transmission timer to current time
|
||||
bool DShotRMT::_timer_reset()
|
||||
{
|
||||
_last_transmission_time = esp_timer_get_time();
|
||||
|
||||
return DSHOT_OK;
|
||||
}
|
||||
|
||||
// Public Info & Debug Functions
|
||||
// Print timing diagnostic information to specified stream
|
||||
void DShotRMT::printDShotInfo(Stream &output) const
|
||||
{
|
||||
|
|
@ -507,11 +212,11 @@ void DShotRMT::printDShotInfo(Stream &output) const
|
|||
output.println(" === DShot Signal Info === ");
|
||||
|
||||
// Current DShot mode
|
||||
output.printf("Current Mode: DSHOT%d\n",
|
||||
_mode == DSHOT150 ? 150 :
|
||||
_mode == DSHOT300 ? 300 :
|
||||
_mode == DSHOT600 ? 600 :
|
||||
_mode == DSHOT1200 ? 1200 : 0);
|
||||
output.printf("Current Mode: DSHOT%d\n",
|
||||
_mode == DSHOT150 ? 150 :
|
||||
_mode == DSHOT300 ? 300 :
|
||||
_mode == DSHOT600 ? 600 :
|
||||
_mode == DSHOT1200 ? 1200 : 0);
|
||||
|
||||
output.printf("Bidirectional: %s\n", _is_bidirectional ? "YES" : "NO");
|
||||
|
||||
|
|
@ -521,7 +226,7 @@ void DShotRMT::printDShotInfo(Stream &output) const
|
|||
// Print bit by bit
|
||||
for (int i = DSHOT_BITS_PER_FRAME - 1; i >= 0; --i)
|
||||
{
|
||||
if ((_parsed_packet >> i) & 1)
|
||||
if ((_parsed_packet >> i) & 0b0000000000000001)
|
||||
{
|
||||
output.print("1");
|
||||
}
|
||||
|
|
@ -547,16 +252,330 @@ void DShotRMT::printCpuInfo(Stream &output) const
|
|||
output.printf("APB Freq = %lu Hz\n", getApbFrequency());
|
||||
}
|
||||
|
||||
// --- HELPERS ---
|
||||
void printDShotResult(dshot_result_t &result, Stream &output)
|
||||
// Private Initialization Functions
|
||||
// Initialize RMT TX channel
|
||||
dshot_result_t DShotRMT::_initTXChannel()
|
||||
{
|
||||
output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", result.msg);
|
||||
// Configure TX channel
|
||||
_tx_channel_config.gpio_num = _gpio;
|
||||
_tx_channel_config.clk_src = DSHOT_CLOCK_SRC_DEFAULT;
|
||||
_tx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION;
|
||||
_tx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS;
|
||||
_tx_channel_config.trans_queue_depth = RMT_QUEUE_DEPTH;
|
||||
|
||||
// Print telemetry data if available
|
||||
if (result.success && (result.erpm > 0 || result.motor_rpm > 0))
|
||||
// Config RMT TX
|
||||
_rmt_tx_config.loop_count = 0; // No automatic loops - real-time calculation
|
||||
_rmt_tx_config.flags.eot_level = _is_bidirectional ? 1 : 0; // Telemetric Bit used as bidir flag
|
||||
|
||||
// Create RMT TX channel
|
||||
if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK)
|
||||
{
|
||||
output.printf(" | eRPM: %u, Motor RPM: %u", result.erpm, result.motor_rpm);
|
||||
return {false, TX_INIT_FAILED};
|
||||
}
|
||||
|
||||
output.println();
|
||||
// Enable TX channel
|
||||
if (rmt_enable(_rmt_tx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, TX_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, TX_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Initialize RMT RX channel
|
||||
dshot_result_t DShotRMT::_initRXChannel()
|
||||
{
|
||||
// Direct RMT symbol processing - Performance optimized
|
||||
_rx_event_callbacks.on_recv_done = _on_rx_done;
|
||||
|
||||
// Config RMT RX
|
||||
_rx_channel_config.gpio_num = _gpio;
|
||||
_rx_channel_config.clk_src = DSHOT_CLOCK_SRC_DEFAULT;
|
||||
_rx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION;
|
||||
_rx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS;
|
||||
|
||||
// Config RMT RX parameters
|
||||
_rmt_rx_config.signal_range_min_ns = DSHOT_PULSE_MIN;
|
||||
_rmt_rx_config.signal_range_max_ns = DSHOT_PULSE_MAX;
|
||||
|
||||
// Create RMT RX channel
|
||||
if (rmt_new_rx_channel(&_rx_channel_config, &_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RX_INIT_FAILED};
|
||||
}
|
||||
|
||||
// Enable RX channel
|
||||
if (rmt_enable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RX_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, RX_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Initialize DShot encoder
|
||||
dshot_result_t DShotRMT::_initDShotEncoder()
|
||||
{
|
||||
// Create copy encoder configuration
|
||||
rmt_copy_encoder_config_t encoder_config = {};
|
||||
|
||||
// Create encoder instance
|
||||
if (rmt_new_copy_encoder(&encoder_config, &_dshot_encoder) != DSHOT_OK)
|
||||
{
|
||||
return {false, ENCODER_INIT_FAILED};
|
||||
}
|
||||
|
||||
return {true, ENCODER_INIT_SUCCESS};
|
||||
}
|
||||
|
||||
// Private Packet Management Functions
|
||||
// Build a complete DShot packet from a valid value
|
||||
dshot_packet_t DShotRMT::_buildDShotPacket(const uint16_t &value)
|
||||
{
|
||||
// Init packet structure
|
||||
dshot_packet_t packet = {};
|
||||
|
||||
// Re-check for valid value
|
||||
if (value > DSHOT_THROTTLE_MAX)
|
||||
{
|
||||
// Something is really wrong
|
||||
return packet;
|
||||
}
|
||||
|
||||
// Build packet
|
||||
packet.throttle_value = value & DSHOT_THROTTLE_MAX;
|
||||
packet.telemetric_request = _is_bidirectional ? 1 : 0;
|
||||
|
||||
// CRC is calculated over 12bit
|
||||
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
|
||||
packet.checksum = _calculateCRC(data);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
// Parse DShot packet into 16-bit format
|
||||
uint16_t DShotRMT::_parseDShotPacket(const dshot_packet_t &packet)
|
||||
{
|
||||
// Parse DShot frame into "raw" 16 bit value
|
||||
uint16_t data_and_telemetry = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
return (data_and_telemetry << 4) | packet.checksum;
|
||||
}
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t DShotRMT::_calculateCRC(const uint16_t &data)
|
||||
{
|
||||
// DShot CRC
|
||||
uint16_t crc = (data ^ (data >> 4) ^ (data >> 8)) & DSHOT_CRC_MASK;
|
||||
|
||||
// Invert CRC for bidirectional DShot mode
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
crc = (~crc) & DSHOT_CRC_MASK;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
// Configure RMT ticks for DShot timings
|
||||
void DShotRMT::_preCalculateRMTTicks()
|
||||
{
|
||||
// Convert DShot timings (us) to RMT ticks
|
||||
_rmt_ticks.bit_length_ticks = static_cast<uint16_t>(_dshot_timing.bit_length_us * RMT_TICKS_PER_US);
|
||||
_rmt_ticks.t1h_ticks = static_cast<uint16_t>(_dshot_timing.t1h_lenght_us * RMT_TICKS_PER_US);
|
||||
_rmt_ticks.t0h_ticks = _rmt_ticks.t1h_ticks >> 1; // High time for a 1 is always double that of a 0
|
||||
_rmt_ticks.t1l_ticks = _rmt_ticks.bit_length_ticks - _rmt_ticks.t1h_ticks;
|
||||
_rmt_ticks.t0l_ticks = _rmt_ticks.bit_length_ticks - _rmt_ticks.t0h_ticks;
|
||||
|
||||
// Pause between frames is frame time in us, some padding and about 30 us is added by hardware
|
||||
_frame_timer_us = (static_cast<uint64_t>(_dshot_timing.bit_length_us * DSHOT_BITS_PER_FRAME) << 1) + DSHOT_PADDING_US;
|
||||
|
||||
// Double frame time for bidirectional mode (includes response time)
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
_frame_timer_us = (_frame_timer_us << 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Precalculate bit positions for performance optimization
|
||||
void DShotRMT::_preCalculateBitPositions()
|
||||
{
|
||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
_bitPositions[i] = DSHOT_BITS_PER_FRAME - 1 - i;
|
||||
}
|
||||
}
|
||||
|
||||
// Private Frame Processing Functions
|
||||
// Transmit DShot packet via RMT
|
||||
dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet)
|
||||
{
|
||||
// Check timing requirements
|
||||
if (!_timer_signal())
|
||||
{
|
||||
return {false, TIMING_CORRECTION};
|
||||
}
|
||||
|
||||
// Enable RMT RX before RMT TX (bidirectional mode)
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
// Calculate transmission data size
|
||||
size_t rx_size_bytes = GCR_BITS_PER_FRAME * sizeof(rmt_symbol_word_t);
|
||||
|
||||
// Performance reasons
|
||||
rmt_symbol_word_t rx_symbols[GCR_BITS_PER_FRAME];
|
||||
|
||||
if (rmt_receive(_rmt_rx_channel, rx_symbols, rx_size_bytes, &_rmt_rx_config) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Local for performance
|
||||
rmt_symbol_word_t tx_symbols[DSHOT_BITS_PER_FRAME];
|
||||
|
||||
// Encode DShot packet into RMT symbols
|
||||
_encodeDShotFrame(packet, tx_symbols);
|
||||
|
||||
// Calculate transmission data size
|
||||
size_t tx_size_bytes = DSHOT_BITS_PER_FRAME * sizeof(rmt_symbol_word_t);
|
||||
|
||||
// TODO: Find out, why this is needed
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
// Disable RMT RX for sending
|
||||
if (rmt_disable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Perform RMT transmission
|
||||
if (rmt_transmit(_rmt_tx_channel, _dshot_encoder, tx_symbols, tx_size_bytes, &_rmt_tx_config) != DSHOT_OK)
|
||||
{
|
||||
return {false, TRANSMISSION_FAILED};
|
||||
}
|
||||
|
||||
// Re-enable RMT RX
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
if (rmt_enable(_rmt_rx_channel) != DSHOT_OK)
|
||||
{
|
||||
return {false, RECEIVER_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Update timestamp and calculate execution time
|
||||
_timer_reset();
|
||||
|
||||
return {true, TRANSMISSION_SUCCESS};
|
||||
}
|
||||
|
||||
// Encode DShot packet into RMT symbol format (placed in IRAM for performance)
|
||||
dshot_result_t IRAM_ATTR DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols)
|
||||
{
|
||||
_parsed_packet = _parseDShotPacket(packet);
|
||||
|
||||
// Decode MSB
|
||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
// Use precalculated bit positions - Performance optimized
|
||||
int bit_position = _bitPositions[i];
|
||||
|
||||
bool bit = (_parsed_packet >> bit_position) & 0b0000000000000001;
|
||||
symbols[i].level0 = _level0;
|
||||
symbols[i].duration0 = bit ? _rmt_ticks.t1h_ticks : _rmt_ticks.t0h_ticks;
|
||||
symbols[i].level1 = _level1;
|
||||
symbols[i].duration1 = bit ? _rmt_ticks.t1l_ticks : _rmt_ticks.t0l_ticks;
|
||||
}
|
||||
|
||||
return {true, ENCODING_SUCCESS};
|
||||
}
|
||||
|
||||
// Decode DShot telemetry frame from received RMT symbols
|
||||
uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols)
|
||||
{
|
||||
uint32_t gcr_value = 0;
|
||||
|
||||
// Decode GCR symbols into a 21-bit value.
|
||||
// '1' has a longer low pulse (duration0 > duration1).
|
||||
// '0' has a longer high pulse (duration1 > duration0).
|
||||
for (size_t i = 0; i < GCR_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
bool bit_is_one = symbols[i].duration0 > symbols[i].duration1;
|
||||
gcr_value = (gcr_value << 1) | bit_is_one;
|
||||
}
|
||||
|
||||
// Perform GCR decoding: data = gcr ^ (gcr >> 1).
|
||||
uint32_t decoded_frame = gcr_value ^ (gcr_value >> 1);
|
||||
|
||||
// Extract 16 data bits and 4 CRC bits from 20-bit frame.
|
||||
// The first bit of the GCR frame is a start bit and is discarded.
|
||||
uint16_t data_and_crc = (decoded_frame & DSHOT_FULL_PACKET);
|
||||
|
||||
// Extract data (first 12 bits) and CRC (last 4 bits)
|
||||
uint16_t received_data = data_and_crc >> 4;
|
||||
uint16_t received_crc = data_and_crc & DSHOT_CRC_MASK;
|
||||
|
||||
// Telemetry request bit has to be 1
|
||||
if (!(received_data & (1 << 11)))
|
||||
{
|
||||
return DSHOT_NULL_PACKET;
|
||||
}
|
||||
|
||||
// Calculate expected CRC
|
||||
uint16_t data_for_crc = received_data;
|
||||
uint16_t calculated_crc = _calculateCRC(data_for_crc);
|
||||
|
||||
// Validate CRC
|
||||
if (received_crc != calculated_crc)
|
||||
{
|
||||
return DSHOT_NULL_PACKET;
|
||||
}
|
||||
|
||||
// Return the eRPM value (first 11 bits of received data).
|
||||
return received_data & DSHOT_THROTTLE_MAX;
|
||||
}
|
||||
|
||||
// Private Timing Control Functions
|
||||
// Check if enough time has passed for next transmission
|
||||
bool IRAM_ATTR DShotRMT::_timer_signal()
|
||||
{
|
||||
uint64_t current_time = esp_timer_get_time();
|
||||
|
||||
// Handle potential overflow
|
||||
uint64_t elapsed = current_time - _last_transmission_time_us;
|
||||
|
||||
return elapsed >= _frame_timer_us;
|
||||
}
|
||||
|
||||
// Reset transmission timer to current time
|
||||
bool DShotRMT::_timer_reset()
|
||||
{
|
||||
_last_transmission_time_us = esp_timer_get_time();
|
||||
|
||||
return DSHOT_OK;
|
||||
}
|
||||
|
||||
// Static Callback Functions
|
||||
// Callback for RMT RX
|
||||
bool IRAM_ATTR DShotRMT::_on_rx_done(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data)
|
||||
{
|
||||
DShotRMT *instance = static_cast<DShotRMT *>(user_data);
|
||||
|
||||
// ISR check for valid data
|
||||
if (edata && edata->num_symbols >= GCR_BITS_PER_FRAME && edata->num_symbols <= GCR_BITS_PER_FRAME)
|
||||
{
|
||||
// Direct decoding
|
||||
uint16_t erpm = instance->_decodeDShotFrame(edata->received_symbols);
|
||||
|
||||
if (erpm != DSHOT_NULL_PACKET)
|
||||
{
|
||||
// Atomic writes - thread-safe
|
||||
instance->_last_erpm_atomic = erpm;
|
||||
instance->_telemetry_ready_flag_atomic = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
233
src/DShotRMT.h
233
src/DShotRMT.h
|
|
@ -10,42 +10,20 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <dshot_commands.h>
|
||||
#include <web_content.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/rmt_tx.h>
|
||||
#include <driver/rmt_rx.h>
|
||||
#include <atomic>
|
||||
|
||||
// DShot Protocol Constants
|
||||
// DShot Protocol Constants & Types
|
||||
static constexpr auto DSHOT_THROTTLE_FAILSAFE = 0;
|
||||
static constexpr auto DSHOT_THROTTLE_MIN = 48;
|
||||
static constexpr auto DSHOT_THROTTLE_MAX = 2047;
|
||||
static constexpr auto DSHOT_BITS_PER_FRAME = 16;
|
||||
static constexpr auto DSHOT_PAUSE_US = 30; // Additional frame pause time
|
||||
static constexpr auto DSHOT_NULL_PACKET = 0b0000000000000000;
|
||||
static constexpr auto DSHOT_FULL_PACKET = 0b1111111111111111;
|
||||
static constexpr auto DSHOT_CRC_MASK = 0b0000000000001111;
|
||||
static constexpr auto DSHOT_RX_TIMEOUT_MS = 2; // Never reached, just a timeeout
|
||||
static constexpr auto GCR_BITS_PER_FRAME = 21; // Number of GCR bits in a DShot answer frame (1 start + 16 data + 4 CRC)
|
||||
static constexpr auto DEFAULT_MOTOR_MAGNET_COUNT = 14;
|
||||
static constexpr auto MAGNETS_PER_POLE_PAIR = 2;
|
||||
static constexpr auto MIN_POLE_PAIRS = 1;
|
||||
static constexpr auto NO_DSHOT_ERPM = 0;
|
||||
static constexpr auto NO_DSHOT_RPM = 0;
|
||||
|
||||
// RMT Configuration Constants
|
||||
constexpr auto DSHOT_CLOCK_SRC_DEFAULT = RMT_CLK_SRC_DEFAULT;
|
||||
constexpr auto DSHOT_RMT_RESOLUTION = 10 * 1000 * 1000; // 10 MHz resolution
|
||||
constexpr auto RMT_BUFFER_SIZE = DSHOT_BITS_PER_FRAME;
|
||||
constexpr auto RMT_BUFFER_SYMBOLS = 64;
|
||||
constexpr auto RMT_QUEUE_DEPTH = 1;
|
||||
|
||||
// Smallest pulse for DShot1200 is 2us. Largest for DShot150 is 40us.
|
||||
// The range is set from 3us (3000ns) to 60us (60000ns) to be safe across all modes.
|
||||
constexpr uint32_t DSHOT_PULSE_MIN = 3000;
|
||||
constexpr uint32_t DSHOT_PULSE_MAX = 60000;
|
||||
|
||||
// DShot Modes
|
||||
typedef enum
|
||||
typedef enum dshot_mode
|
||||
{
|
||||
DSHOT_OFF,
|
||||
DSHOT150,
|
||||
|
|
@ -54,8 +32,8 @@ typedef enum
|
|||
DSHOT1200
|
||||
} dshot_mode_t;
|
||||
|
||||
// DShot Packet
|
||||
typedef struct
|
||||
// DShot Packet Structure
|
||||
typedef struct dshot_packet
|
||||
{
|
||||
uint16_t throttle_value : 11;
|
||||
bool telemetric_request : 1;
|
||||
|
|
@ -63,18 +41,24 @@ typedef struct
|
|||
} dshot_packet_t;
|
||||
|
||||
// DShot Timing Configuration
|
||||
typedef struct
|
||||
typedef struct dshot_timing
|
||||
{
|
||||
uint32_t frame_length_us;
|
||||
uint16_t ticks_per_bit;
|
||||
uint16_t ticks_one_high;
|
||||
uint16_t ticks_one_low;
|
||||
uint16_t ticks_zero_high;
|
||||
uint16_t ticks_zero_low;
|
||||
} dshot_timing_t;
|
||||
double bit_length_us;
|
||||
double t1h_lenght_us;
|
||||
} dshot_timing_us_t;
|
||||
|
||||
// Unified DShot result structure
|
||||
typedef struct
|
||||
// RMT Timing Configuration
|
||||
typedef struct rmt_ticks
|
||||
{
|
||||
uint16_t bit_length_ticks;
|
||||
uint16_t t1h_ticks;
|
||||
uint16_t t1l_ticks;
|
||||
uint16_t t0h_ticks;
|
||||
uint16_t t0l_ticks;
|
||||
} rmt_ticks_t;
|
||||
|
||||
// Unified DShot Result Structure
|
||||
typedef struct dshot_result
|
||||
{
|
||||
bool success;
|
||||
const char *msg;
|
||||
|
|
@ -82,46 +66,41 @@ typedef struct
|
|||
uint16_t motor_rpm;
|
||||
} dshot_result_t;
|
||||
|
||||
// Naming convention
|
||||
// Command Type Alias
|
||||
typedef dshotCommands_e dshot_commands_t;
|
||||
|
||||
// --- HELPERS ---
|
||||
// Helper Functions
|
||||
void printDShotResult(dshot_result_t &result, Stream &output = Serial);
|
||||
|
||||
//
|
||||
// DShotRMT Main Class
|
||||
class DShotRMT
|
||||
{
|
||||
public:
|
||||
// Constructor with GPIO enum
|
||||
// Constructors & Destructor
|
||||
explicit DShotRMT(gpio_num_t gpio = GPIO_NUM_16, dshot_mode_t mode = DSHOT300, bool is_bidirectional = false);
|
||||
|
||||
// Constructor with pin number
|
||||
DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional);
|
||||
|
||||
// Destructor for "better" code
|
||||
|
||||
~DShotRMT();
|
||||
|
||||
// Public Core Functions
|
||||
// Initialize the RMT module and DShot config
|
||||
dshot_result_t begin();
|
||||
|
||||
// Send throttle value (48-2047)
|
||||
|
||||
// Send throttle value (48 - 2047)
|
||||
dshot_result_t sendThrottle(uint16_t throttle);
|
||||
|
||||
// Send DShot command (0-47)
|
||||
|
||||
// Send DShot command (0 - 47)
|
||||
dshot_result_t sendCommand(uint16_t command);
|
||||
|
||||
// --- GETTERS ---
|
||||
gpio_num_t getGPIO() const { return _gpio; }
|
||||
uint16_t getDShotPacket() const { return _parsed_packet; }
|
||||
bool is_bidirectional() const { return _is_bidirectional; }
|
||||
dshot_mode_t getMode() const { return _mode; }
|
||||
|
||||
// Get telemetry data (bidirectional mode only)
|
||||
dshot_result_t getTelemetry(uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT);
|
||||
|
||||
// --- INFO ---
|
||||
|
||||
// Public Info & Debug Functions
|
||||
void printDShotInfo(Stream &output = Serial) const;
|
||||
void printCpuInfo(Stream &output = Serial) const;
|
||||
|
||||
// --- DEPRECATED METHODS ---
|
||||
|
||||
// Deprecated Methods
|
||||
[[deprecated("Use sendThrottle() instead")]]
|
||||
bool setThrottle(uint16_t throttle)
|
||||
{
|
||||
|
|
@ -144,67 +123,30 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
// --- CONFIG ---
|
||||
gpio_num_t _gpio;
|
||||
dshot_mode_t _mode;
|
||||
bool _is_bidirectional;
|
||||
uint32_t _frame_timer_us;
|
||||
const dshot_timing_t &_timing_config;
|
||||
uint16_t _last_throttle;
|
||||
|
||||
// --- TIMING & PACKET VARIABLES ---
|
||||
uint64_t _last_transmission_time;
|
||||
uint16_t _parsed_packet;
|
||||
dshot_packet_t _packet;
|
||||
uint8_t _bitPositions[DSHOT_BITS_PER_FRAME];
|
||||
uint16_t _level0;
|
||||
uint16_t _level1;
|
||||
|
||||
// --- RMT HARDWARE HANDLES ---
|
||||
rmt_channel_handle_t _rmt_tx_channel;
|
||||
rmt_channel_handle_t _rmt_rx_channel;
|
||||
rmt_encoder_handle_t _dshot_encoder;
|
||||
|
||||
// --- RMT CONFIG STRUCTURES ---
|
||||
rmt_tx_channel_config_t _tx_channel_config;
|
||||
rmt_rx_channel_config_t _rx_channel_config;
|
||||
rmt_transmit_config_t _transmit_config;
|
||||
rmt_receive_config_t _receive_config;
|
||||
|
||||
// --- INITS ---
|
||||
dshot_result_t _initTXChannel();
|
||||
dshot_result_t _initRXChannel();
|
||||
dshot_result_t _initDShotEncoder();
|
||||
|
||||
// --- PACKET MANAGEMENT ---
|
||||
dshot_packet_t _buildDShotPacket(const uint16_t value);
|
||||
uint16_t _parseDShotPacket(const dshot_packet_t &packet);
|
||||
uint16_t _calculateCRC(const uint16_t data);
|
||||
void _preCalculateBitPositions();
|
||||
|
||||
// --- FRAME PROCESSING ---
|
||||
dshot_result_t _sendDShotFrame(const dshot_packet_t &packet);
|
||||
bool IRAM_ATTR _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols);
|
||||
uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols);
|
||||
|
||||
// --- TIMING CONTROL ---
|
||||
bool IRAM_ATTR _timer_signal();
|
||||
bool _timer_reset();
|
||||
|
||||
// -- CALLBACKS ---
|
||||
rmt_rx_event_callbacks_t _rx_event_callbacks;
|
||||
volatile rmt_symbol_word_t _rx_symbols_direct[GCR_BITS_PER_FRAME];
|
||||
volatile uint16_t _last_erpm_atomic;
|
||||
volatile bool _telemetry_ready_flag;
|
||||
static bool IRAM_ATTR _rmt_rx_done_callback(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
|
||||
// --- DSHOT DEFAULTS ---
|
||||
static constexpr auto const DSHOT_TELEMETRY_INVALID = (0xffff);
|
||||
|
||||
// --- CONSTANTS & ERROR MESSAGES ---
|
||||
// Configuration Constants
|
||||
static constexpr bool DSHOT_OK = 0;
|
||||
static constexpr bool DSHOT_ERROR = 1;
|
||||
|
||||
static constexpr auto const DSHOT_NULL_PACKET = 0b0000000000000000;
|
||||
static constexpr auto const DSHOT_FULL_PACKET = 0b1111111111111111;
|
||||
static constexpr auto const DSHOT_CRC_MASK = 0b0000000000001111;
|
||||
static constexpr auto const DSHOT_CLOCK_SRC_DEFAULT = RMT_CLK_SRC_DEFAULT;
|
||||
static constexpr auto const DSHOT_RMT_RESOLUTION = 8 * 1000 * 1000; // 8 MHz resolution
|
||||
static constexpr auto const RMT_TICKS_PER_US = DSHOT_RMT_RESOLUTION / (1 * 1000 * 1000); // RMT Ticks per microsecond
|
||||
static constexpr auto const RMT_BUFFER_SIZE = DSHOT_BITS_PER_FRAME;
|
||||
static constexpr auto const DSHOT_RX_TIMEOUT_MS = 2;
|
||||
static constexpr auto const DSHOT_PADDING_US = 20; // Add to pause between frames for compatibility
|
||||
static constexpr auto const RMT_BUFFER_SYMBOLS = 64;
|
||||
static constexpr auto const RMT_QUEUE_DEPTH = 1;
|
||||
static constexpr auto const GCR_BITS_PER_FRAME = 21; // Number of GCR bits in a DShot answer frame
|
||||
static constexpr auto const POLE_PAIRS_MIN = 1;
|
||||
static constexpr auto const MAGNETS_PER_POLE_PAIR = 2;
|
||||
static constexpr auto const NO_DSHOT_TELEMETRY = 0;
|
||||
static constexpr auto const DSHOT_PULSE_MIN = 3000; // 3us minimum pulse
|
||||
static constexpr auto const DSHOT_PULSE_MAX = 60000; // 60us maximum pulse
|
||||
static constexpr auto const DSHOT_TELEMETRY_INVALID = DSHOT_THROTTLE_MAX;
|
||||
|
||||
// Error Messages
|
||||
static constexpr char const *NONE = "";
|
||||
static constexpr char const *UNKNOWN_ERROR = "Unknown Error!";
|
||||
static constexpr char const *INIT_SUCCESS = "SignalGeneratorRMT initialized successfully";
|
||||
|
|
@ -213,9 +155,9 @@ private:
|
|||
static constexpr char const *TX_INIT_FAILED = "TX RMT channel init failed!";
|
||||
static constexpr char const *RX_INIT_SUCCESS = "RX RMT channel initialized successfully";
|
||||
static constexpr char const *RX_INIT_FAILED = "RX RMT channel init failed!";
|
||||
static constexpr char const *RX_BUFFER_FAILED = "RX RMT buffer init failed!";
|
||||
static constexpr char const *ENCODER_INIT_SUCCESS = "RMT encoder initialized successfully";
|
||||
static constexpr char const *ENCODER_INIT_FAILED = "RMT encoder init failed!";
|
||||
static constexpr char const *ENCODING_SUCCESS = "Packet encoded successfully";
|
||||
static constexpr char const *TRANSMISSION_SUCCESS = "Transmission successfully";
|
||||
static constexpr char const *TRANSMISSION_FAILED = "Transmission failed!";
|
||||
static constexpr char const *RECEIVER_FAILED = "RMT receiver failed!";
|
||||
|
|
@ -226,4 +168,61 @@ private:
|
|||
static constexpr char const *TELEMETRY_FAILED = "No valid Telemetric Frame received!";
|
||||
static constexpr char const *INVALID_MAGNET_COUNT = "Invalid motor magnet count!";
|
||||
static constexpr char const *TIMING_CORRECTION = "Timing correction!";
|
||||
|
||||
// Core Configuration Variables
|
||||
gpio_num_t _gpio;
|
||||
dshot_mode_t _mode;
|
||||
bool _is_bidirectional;
|
||||
const dshot_timing_us_t &_dshot_timing;
|
||||
uint64_t _frame_timer_us;
|
||||
|
||||
// Timing & Packet Variables
|
||||
rmt_ticks_t _rmt_ticks;
|
||||
uint16_t _last_throttle;
|
||||
uint64_t _last_transmission_time_us;
|
||||
uint16_t _parsed_packet;
|
||||
dshot_packet_t _packet;
|
||||
uint8_t _bitPositions[DSHOT_BITS_PER_FRAME];
|
||||
uint16_t _level0;
|
||||
uint16_t _level1;
|
||||
|
||||
// RMT Hardware Handles
|
||||
rmt_channel_handle_t _rmt_tx_channel;
|
||||
rmt_channel_handle_t _rmt_rx_channel;
|
||||
rmt_encoder_handle_t _dshot_encoder;
|
||||
|
||||
// RMT Configuration Structures
|
||||
rmt_tx_channel_config_t _tx_channel_config;
|
||||
rmt_rx_channel_config_t _rx_channel_config;
|
||||
rmt_transmit_config_t _rmt_tx_config;
|
||||
rmt_receive_config_t _rmt_rx_config;
|
||||
|
||||
// Bidirectional / Telemetry Variables
|
||||
rmt_rx_event_callbacks_t _rx_event_callbacks;
|
||||
std::atomic<uint16_t> _last_erpm_atomic;
|
||||
std::atomic<bool> _telemetry_ready_flag_atomic;
|
||||
|
||||
// Private Initialization Functions
|
||||
dshot_result_t _initTXChannel();
|
||||
dshot_result_t _initRXChannel();
|
||||
dshot_result_t _initDShotEncoder();
|
||||
|
||||
// Private Packet Management Functions
|
||||
dshot_packet_t _buildDShotPacket(const uint16_t &value);
|
||||
uint16_t _parseDShotPacket(const dshot_packet_t &packet);
|
||||
uint16_t _calculateCRC(const uint16_t &data);
|
||||
void _preCalculateRMTTicks();
|
||||
void _preCalculateBitPositions();
|
||||
|
||||
// Private Frame Processing Functions
|
||||
dshot_result_t _sendDShotFrame(const dshot_packet_t &packet);
|
||||
dshot_result_t _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols);
|
||||
uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols);
|
||||
|
||||
// Private Timing Control Functions
|
||||
bool _timer_signal();
|
||||
bool _timer_reset();
|
||||
|
||||
// Static Callback Functions
|
||||
static bool _on_rx_done(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
/**
|
||||
* @file web_content.h
|
||||
* @brief DShotRMT_Control Website content with Arming Switch
|
||||
* @brief DShot signal generation using ESP32 RMT with bidirectional support
|
||||
* @author Wastl Kraus
|
||||
* @date 2025-09-09
|
||||
* @date 2025-09-13
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Web Site Content
|
||||
const char index_html[] PROGMEM = R"rawliteral(
|
||||
static constexpr char index_html[] = R"rawliteral(
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
|
|
@ -357,5 +357,4 @@ const char index_html[] PROGMEM = R"rawliteral(
|
|||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
)rawliteral";
|
||||
)rawliteral";
|
||||
|
|
|
|||
Loading…
Reference in New Issue