diff --git a/.gitignore b/.gitignore index c9a9ea1..430a8fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,24 @@ +.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/ # Built Visual Studio Code Extensions *.vsix -# Builds -*.code-workspace +# Caching ESP32 Builds buildCache build examples/dshot300/debug.cfg examples/dshot300/esp32.svd examples/dshot300/debug_custom.json examples/dshot300/debug.svd -.vscode/ +/build .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 7fe2417..fa01868 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -450,6 +450,450 @@ "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" + ] } ] } \ No newline at end of file diff --git a/README.md b/README.md index d01cda4..f1cc72b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ Supports all standard DShot modes (150, 300, 600, 1200) and features signal gene - **All DShot Modes:** DSHOT150, DSHOT300 (default), DSHOT600, DSHOT1200 - **BiDirectional DShot:** Full support for RPM telemetry feedback - **Web Control Interface:** Modern responsive web UI with WiFi access point -- **Advanced Command Manager:** High-level API for ESC configuration and control - **Safety Features:** Arming/disarming system with motor lockout protection - **Dual Control Options:** Web interface and serial console control - **Real-time Telemetry:** Live RPM monitoring and data display @@ -118,11 +117,9 @@ Make sure you are using these libraries for [ESPAsyncWebServer](https://github.c --- -## 📚 Examples +## 📚 Extras -The library includes comprehensive examples: - -### 1. Basic DShot Control with Web Interface (`web_control.ino`) +### 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 @@ -137,25 +134,6 @@ The library includes comprehensive examples: - Live RPM monitoring display - Automatic reconnection on connection loss -### 2. Advanced Command Management (`command_manager.ino`) -Interactive ESC control with full menu system: -``` -=== DShot Command Manager Menu === - 1 - Stop Motor - 2 - Activate Beacon 1 - 3 - Set Normal Spin Direction - 4 - Set Reversed Spin Direction - 5 - Get ESC Info - 6 - Turn LED 0 ON - 7 - Turn LED 0 OFF - 0 - Emergency Stop - -Advanced Commands: - cmd - Send DShot command (0 - 47) - throttle - Set throttle (48 - 2047) - repeat cmd count - Repeat command -``` - --- ## 🔧 Hardware Configuration diff --git a/examples/command_manager/command_manager.ino b/examples/command_manager/command_manager.ino deleted file mode 100644 index 4bc7bdd..0000000 --- a/examples/command_manager/command_manager.ino +++ /dev/null @@ -1,345 +0,0 @@ -/* - * command_manager.ino - * Example sketch for DShotCommandManager - * Author: Wastl Kraus - * Date: 2025-09-04 - * License: MIT - */ - -#include -#include -#include - -// USB serial port settings -static constexpr auto &USB_SERIAL = Serial0; -static constexpr auto USB_SERIAL_BAUD = 115200; - -// Motor configuration -static constexpr auto MOTOR01_PIN = 17; -static constexpr auto IS_BIDIRECTIONAL = false; - -// Motor magnet count for RPM calculation -static constexpr auto MOTOR01_MAGNET_COUNT = 14; - -// Create motor and command manager instances -DShotRMT motor01(MOTOR01_PIN, DSHOT300, IS_BIDIRECTIONAL); -DShotCommandManager commandManager(motor01); - -// Global variable to store the desired continuous throttle value -static volatile uint16_t throttle_now = 0; - -// Helper function to print telemetry results -void printTelemetryResult(const dshot_result_t &result) -{ - if (result.success && (result.erpm > 0 || result.motor_rpm > 0)) - { - USB_SERIAL.printf("Telemetry: eRPM=%u, Motor RPM=%u\n", result.erpm, result.motor_rpm); - } - else - { - USB_SERIAL.printf("Telemetry: FAILED - %s\n", result.msg); - } -} - -// -void setup() -{ - // Start USB Serial Port - USB_SERIAL.begin(USB_SERIAL_BAUD); - - // Initialize DShot - motor01.begin(); - - // Init Command Manager - commandManager.begin(); - - // Print Menu - printMenu(); -} - -// -void loop() -{ - // Time Measurement - static uint64_t last_stats_print = 0; - - // Check for serial input - if (USB_SERIAL.available() > 0) - { - String input = USB_SERIAL.readStringUntil('\n'); - input.trim(); - handleUserInput(input); - } - - // Continuously send the stored throttle value - if (throttle_now != 0) - { - dshot_result_t result = motor01.sendThrottle(throttle_now); - - // Only print errors to avoid spam - if (!result.success) - { - printResult(result); - } - - // Print motor stats every 2 seconds - if (esp_timer_get_time() - last_stats_print >= 2000000) - { - motor01.printDShotInfo(); - - // Get Motor RPM - if (IS_BIDIRECTIONAL) - { - dshot_result_t telem_result = motor01.getTelemetry(MOTOR01_MAGNET_COUNT); - printTelemetryResult(telem_result); - } - - // Time Stamp - last_stats_print = esp_timer_get_time(); - } - } -} - -// -void handleUserInput(const String &input) -{ - dshot_result_t cmd_result; - - if (input == "1") - { - // Stop motor command should also reset the continuous throttle value - throttle_now = 0; - USB_SERIAL.print("Stopping motor... "); - cmd_result = commandManager.stopMotor(); - printResult(cmd_result); - return; - } - - if (input == "2") - { - USB_SERIAL.print("Activating beacon 1... "); - cmd_result = commandManager.activateBeacon(1); - printResult(cmd_result); - return; - } - - if (input == "3") - { - USB_SERIAL.print("Setting normal spin direction... "); - cmd_result = commandManager.setSpinDirection(false); - printResult(cmd_result); - return; - } - - if (input == "4") - { - USB_SERIAL.print("Setting reversed spin direction... "); - cmd_result = commandManager.setSpinDirection(true); - printResult(cmd_result); - return; - } - - if (input == "5") - { - USB_SERIAL.print("Getting ESC Info... "); - cmd_result = commandManager.requestESCInfo(); - printResult(cmd_result); - return; - } - - if (input == "6") - { - USB_SERIAL.print("Turning LED 0 ON... "); - cmd_result = commandManager.setLED(0, true); - printResult(cmd_result); - return; - } - - if (input == "7") - { - USB_SERIAL.print("Turning LED 0 OFF... "); - cmd_result = commandManager.setLED(0, false); - printResult(cmd_result); - return; - } - - if (input == "h" || input == "help") - { - printMenu(); - return; - } - - if (input == "info") - { - motor01.printDShotInfo(); - return; - } - - if (input == "rpm" && IS_BIDIRECTIONAL) - { - dshot_result_t result = motor01.getTelemetry(MOTOR01_MAGNET_COUNT); - printTelemetryResult(result); - return; - } - - if (input.startsWith("cmd ")) - { - // Direct command execution: "cmd 5" sends command 5 - int cmd_num = input.substring(4).toInt(); - - if (DShotCommandManager::isValidCommand(static_cast(cmd_num))) - { - USB_SERIAL.printf("Sending command %d (%s)... ", cmd_num, - DShotCommandManager::getCommandName(static_cast(cmd_num))); - cmd_result = commandManager.sendCommand(static_cast(cmd_num)); - printResult(cmd_result); - } - else - { - USB_SERIAL.printf("Invalid command number: %d (valid range: 0 - %d)\n", cmd_num, DSHOT_CMD_MAX); - } - return; - } - - if (input.startsWith("throttle ")) - { - // Throttle control: "throttle 1000" sets throttle to 1000 - int throttle_value = input.substring(9).toInt(); - - if (throttle_value >= DSHOT_THROTTLE_MIN && throttle_value <= DSHOT_THROTTLE_MAX) - { - throttle_now = throttle_value; - USB_SERIAL.printf("Setting continuous throttle to %d\n", throttle_now); - - // Send first throttle command and show result - dshot_result_t result = motor01.sendThrottle(throttle_now); - printResult(result); - - if (result.success) - { - USB_SERIAL.println("Continuous throttle mode enabled. Send '0' or 'throttle 0' to stop."); - } - return; - } - - if (throttle_value == 0) - { - throttle_now = 0; - USB_SERIAL.println("Continuous throttle stopped."); - - // Send stop command - dshot_result_t result = motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); - printResult(result); - return; - } - - USB_SERIAL.printf("Invalid throttle value: %d (valid range: %d-%d, use 0 to stop)\n", - throttle_value, DSHOT_THROTTLE_MIN, DSHOT_THROTTLE_MAX); - return; - } - - if (input == "0") - { - // Quick stop - throttle_now = 0; - USB_SERIAL.print("Emergency stop... "); - dshot_result_t result = motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); - printResult(result); - return; - } - - if (input.startsWith("repeat ")) - { - // Repeat command: "repeat cmd 5 count 10" - sends command 5 ten times - String params = input.substring(7); - - if (!params.startsWith("cmd ")) - { - USB_SERIAL.println("Usage: repeat cmd count "); - return; - } - - int space_pos = params.indexOf(' ', 4); - - if (space_pos <= 0 || !params.substring(space_pos + 1).startsWith("count ")) - { - USB_SERIAL.println("Usage: repeat cmd count "); - return; - } - - int cmd_num = params.substring(4, space_pos).toInt(); - int repeat_count = params.substring(space_pos + 7).toInt(); - - if (!DShotCommandManager::isValidCommand(static_cast(cmd_num)) || - repeat_count <= 0 || repeat_count > 100) - { - USB_SERIAL.println("Invalid command or repeat count (1-100)"); - return; - } - - USB_SERIAL.printf("Sending command %d (%s) %d times... ", cmd_num, - DShotCommandManager::getCommandName(static_cast(cmd_num)), - repeat_count); - cmd_result = commandManager.sendCommand(static_cast(cmd_num), repeat_count); - printResult(cmd_result); - return; - } - - // Unknown command - USB_SERIAL.printf("Unknown command: '%s'. Type 'h' or 'help' for help.\n", input.c_str()); -} - -// -void printResult(const dshot_result_t &result) -{ - if (result.success) - { - USB_SERIAL.printf("SUCCESS\n"); - } - else - { - USB_SERIAL.printf("FAILED - %s \n", result.msg); - } -} - -// -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("Free heap: %u bytes\n", ESP.getFreeHeap()); - USB_SERIAL.printf("Uptime: %lu seconds\n", millis() / 1000); -} - -// -void printMenu() -{ - USB_SERIAL.println("**********************************************"); - USB_SERIAL.println(" DShot Command Manager Menu "); - USB_SERIAL.println("**********************************************"); - USB_SERIAL.println(" 1 - Stop Motor"); - USB_SERIAL.println(" 2 - Activate Beacon 1"); - USB_SERIAL.println(" 3 - Set Normal Spin"); - USB_SERIAL.println(" 4 - Set Reversed Spin"); - USB_SERIAL.println(" 5 - Get ESC Info"); - USB_SERIAL.println(" 6 - Turn LED 0 ON"); - USB_SERIAL.println(" 7 - Turn LED 0 OFF"); - USB_SERIAL.println(" 0 - Emergency Stop"); - USB_SERIAL.println("**********************************************"); - USB_SERIAL.println(" cmd - Send Command (0 - 47)"); - USB_SERIAL.println(" throttle - Set throttle (48 - 2047)"); - USB_SERIAL.println("**********************************************"); - USB_SERIAL.println(" info - Show DShot signal info"); - USB_SERIAL.println(" status - Show system status"); - if (IS_BIDIRECTIONAL) - { - USB_SERIAL.println(" rpm - Get telemetry data"); - } - USB_SERIAL.println(" h / help - Show this Menu"); - USB_SERIAL.println("**********************************************"); - USB_SERIAL.println("EXAMPLE INPUT:"); - USB_SERIAL.println(" cmd 5 - Get ESC Info"); - USB_SERIAL.println(" throttle 1000 - Set throttle to 1000"); - USB_SERIAL.println("**********************************************"); -} diff --git a/library.properties b/library.properties index 4687915..8dc6841 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ 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, ota_update.h \ No newline at end of file +provides_includes=DShotRMT.h, dshot_commands.h, web_content.h, ota_update.h \ No newline at end of file diff --git a/src/DShotCommandManager.cpp b/src/DShotCommandManager.cpp deleted file mode 100644 index ac5cb17..0000000 --- a/src/DShotCommandManager.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - * DShotCommandManager.cpp - * Advanced DShot command management for DShotRMT library - * Author: Wastl Kraus - * Date: 2025-09-04 - * License: MIT - */ - -#include - -// Constructor -DShotCommandManager::DShotCommandManager(DShotRMT &dshot_instance) - : _dshot(dshot_instance), - _total_commands_sent(0), - _failed_commands(0), - _last_command_timestamp(0) -{ -} - -// Init command manager -dshot_result_t DShotCommandManager::begin() -{ - dshot_result_t result; - result.success = true; - result.msg = "Success"; - return result; -} - -// --- BASIC COMMAND METHODS --- -dshot_result_t DShotCommandManager::sendCommand(dshot_commands_t command, uint16_t repeat_count) -{ - return sendCommandWithDelay(command, repeat_count, DEFAULT_COMMAND_DELAY_MS); -} - -// -dshot_result_t DShotCommandManager::sendCommandWithDelay(dshot_commands_t command, uint16_t repeat_count, uint32_t delay_ms) -{ - dshot_result_t result = {false, "Unknown error"}; - - if (!isValidCommand(command)) - { - result.msg = "Invalid command"; - return result; - } - - bool all_successful = true; - - // Send command multiple times with delay - for (uint16_t i = 0; i < repeat_count; i++) - { - dshot_result_t single_result = _executeCommand(command); - - if (!single_result.success) - { - all_successful = false; - result.msg = single_result.msg; - break; - } - - // Add delay between repetitions (except for last repetition) - if (i < repeat_count - 1) - { - _delay_ms(delay_ms); - } - } - - // - result.success = all_successful; - - if (result.success) - { - result.msg = "Success"; - } - - return result; -} - -// --- MOTOR CONTROL COMMANDS --- -dshot_result_t DShotCommandManager::stopMotor() -{ - return sendCommand(DSHOT_CMD_MOTOR_STOP); -} - -// -dshot_result_t DShotCommandManager::set3DMode(bool enable) -{ - dshot_commands_t command = enable ? DSHOT_CMD_3D_MODE_ON : DSHOT_CMD_3D_MODE_OFF; - return sendCommandWithDelay(command, SETTINGS_COMMAND_REPEATS, SETTINGS_COMMAND_DELAY_MS); -} - -// -dshot_result_t DShotCommandManager::setSpinDirection(bool reversed) -{ - dshot_commands_t command = reversed ? DSHOT_CMD_SPIN_DIRECTION_REVERSED : DSHOT_CMD_SPIN_DIRECTION_NORMAL; - return sendCommandWithDelay(command, SETTINGS_COMMAND_REPEATS, SETTINGS_COMMAND_DELAY_MS); -} - -// -dshot_result_t DShotCommandManager::saveSettings() -{ - return sendCommandWithDelay(DSHOT_CMD_SAVE_SETTINGS, SETTINGS_COMMAND_REPEATS, SETTINGS_COMMAND_DELAY_MS); -} - -// --- TELEMETRY COMMANDS --- -dshot_result_t DShotCommandManager::setExtendedTelemetry(bool enable) -{ - dshot_commands_t command = enable ? DSHOT_CMD_EXTENDED_TELEMETRY_ENABLE : DSHOT_CMD_EXTENDED_TELEMETRY_DISABLE; - return sendCommand(command); -} - -// -dshot_result_t DShotCommandManager::requestESCInfo() -{ - return sendCommand(DSHOT_CMD_ESC_INFO); -} - -// --- LED CONTROL COMMANDS --- -dshot_result_t DShotCommandManager::setLED(uint8_t led_number, bool state) -{ - if (led_number > 3) - { - dshot_result_t result = {false, "Invalid LED number (0-3)"}; - return result; - } - - dshot_commands_t command; - if (state) - { - // LED ON commands - switch (led_number) - { - case 0: - command = DSHOT_CMD_LED0_ON; - break; - case 1: - command = DSHOT_CMD_LED1_ON; - break; - case 2: - command = DSHOT_CMD_LED2_ON; - break; - case 3: - command = DSHOT_CMD_LED3_ON; - break; - } - } - else - { - // LED OFF commands - switch (led_number) - { - case 0: - command = DSHOT_CMD_LED0_OFF; - break; - case 1: - command = DSHOT_CMD_LED1_OFF; - break; - case 2: - command = DSHOT_CMD_LED2_OFF; - break; - case 3: - command = DSHOT_CMD_LED3_OFF; - break; - } - } - - return sendCommand(command); -} - -// --- BEACON COMMANDS --- -dshot_result_t DShotCommandManager::activateBeacon(uint8_t beacon_number) -{ - if (beacon_number < 1 || beacon_number > 5) - { - dshot_result_t result = {false, "Invalid beacon number (1-5)"}; - return result; - } - - dshot_commands_t command = static_cast(DSHOT_CMD_BEACON1 + beacon_number - 1); - return sendCommand(command); -} - -// --- KISS ESC SPECIFIC COMMANDS --- -dshot_result_t DShotCommandManager::setAudioStreamMode(bool enable) -{ - // KISS audio stream mode is a toggle command - return sendCommand(DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF); -} - -// -dshot_result_t DShotCommandManager::setSilentMode(bool enable) -{ - // KISS silent mode is a toggle command - return sendCommand(DSHOT_CMD_SILENT_MODE_ON_OFF); -} - -// --- SEQUENCE COMMANDS --- -dshot_result_t DShotCommandManager::executeSequence(const dshot_commandmanager_item_t *sequence, size_t sequence_length) -{ - dshot_result_t result = {true, "Success"}; - uint64_t total_start_time = esp_timer_get_time(); - - for (size_t i = 0; i < sequence_length; i++) - { - dshot_result_t item_result = sendCommandWithDelay( - sequence[i].command, - sequence[i].repeat_count, - DEFAULT_COMMAND_DELAY_MS); - - if (!item_result.success) - { - result.success = false; - result.msg = item_result.msg; - break; - } - - // Add delay after command if specified - if (sequence[i].delay_ms > 0) - { - _delay_ms(sequence[i].delay_ms); - } - } - - uint64_t total_end_time = esp_timer_get_time(); - - return result; -} - -// -dshot_result_t DShotCommandManager::executeInitSequence() -{ - // Basic ESC initialization sequence - dshot_commandmanager_item_t init_sequence[] = { - {DSHOT_CMD_MOTOR_STOP, 5, 100}, // Stop motor, repeat 5 times, wait 100ms - {DSHOT_CMD_EXTENDED_TELEMETRY_ENABLE, 1, 50}, // Enable telemetry, wait 50ms - {DSHOT_CMD_ESC_INFO, 1, 100} // Request ESC info, wait 100ms - }; - - return executeSequence(init_sequence, sizeof(init_sequence) / sizeof(init_sequence[0])); -} - -// -dshot_result_t DShotCommandManager::executeCalibrationSequence() -{ - // Basic ESC calibration sequence - dshot_commandmanager_item_t calibration_sequence[] = { - {DSHOT_CMD_MOTOR_STOP, 10, 500}, // Ensure motor is stopped - {DSHOT_CMD_SPIN_DIRECTION_NORMAL, 10, 100}, // Set normal spin direction - {DSHOT_CMD_3D_MODE_OFF, 10, 100}, // Disable 3D mode - {DSHOT_CMD_SAVE_SETTINGS, 10, 1000}, // Save settings - {DSHOT_CMD_MOTOR_STOP, 5, 100} // Final stop - }; - - return executeSequence(calibration_sequence, sizeof(calibration_sequence) / sizeof(calibration_sequence[0])); -} - -// --- UTILITY METHODS --- -const char *DShotCommandManager::getCommandName(dshot_commands_t command) -{ - switch (command) - { - case DSHOT_CMD_MOTOR_STOP: - return "MOTOR_STOP"; - case DSHOT_CMD_BEACON1: - return "BEACON1"; - case DSHOT_CMD_BEACON2: - return "BEACON2"; - case DSHOT_CMD_BEACON3: - return "BEACON3"; - case DSHOT_CMD_BEACON4: - return "BEACON4"; - case DSHOT_CMD_BEACON5: - return "BEACON5"; - case DSHOT_CMD_ESC_INFO: - return "ESC_INFO"; - case DSHOT_CMD_SPIN_DIRECTION_1: - return "SPIN_DIRECTION_1"; - case DSHOT_CMD_SPIN_DIRECTION_2: - return "SPIN_DIRECTION_2"; - case DSHOT_CMD_3D_MODE_OFF: - return "3D_MODE_OFF"; - case DSHOT_CMD_3D_MODE_ON: - return "3D_MODE_ON"; - case DSHOT_CMD_SETTINGS_REQUEST: - return "SETTINGS_REQUEST"; - case DSHOT_CMD_SAVE_SETTINGS: - return "SAVE_SETTINGS"; - case DSHOT_CMD_EXTENDED_TELEMETRY_ENABLE: - return "EXTENDED_TELEMETRY_ENABLE"; - case DSHOT_CMD_EXTENDED_TELEMETRY_DISABLE: - return "EXTENDED_TELEMETRY_DISABLE"; - case DSHOT_CMD_SPIN_DIRECTION_NORMAL: - return "SPIN_DIRECTION_NORMAL"; - case DSHOT_CMD_SPIN_DIRECTION_REVERSED: - return "SPIN_DIRECTION_REVERSED"; - case DSHOT_CMD_LED0_ON: - return "LED0_ON"; - case DSHOT_CMD_LED1_ON: - return "LED1_ON"; - case DSHOT_CMD_LED2_ON: - return "LED2_ON"; - case DSHOT_CMD_LED3_ON: - return "LED3_ON"; - case DSHOT_CMD_LED0_OFF: - return "LED0_OFF"; - case DSHOT_CMD_LED1_OFF: - return "LED1_OFF"; - case DSHOT_CMD_LED2_OFF: - return "LED2_OFF"; - case DSHOT_CMD_LED3_OFF: - return "LED3_OFF"; - case DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF: - return "AUDIO_STREAM_MODE_ON_OFF"; - case DSHOT_CMD_SILENT_MODE_ON_OFF: - return "SILENT_MODE_ON_OFF"; - default: - return "UNKNOWN"; - } -} - -// -bool DShotCommandManager::isValidCommand(dshot_commands_t command) -{ - return (command >= DSHOT_CMD_MOTOR_STOP && command <= DSHOT_CMD_MAX); -} - -// --- PRIVATE METHODS --- -dshot_result_t DShotCommandManager::_executeCommand(dshot_commands_t command) -{ - uint64_t start_time = esp_timer_get_time(); - - // Execute the command using the DShotRMT instance - dshot_result_t result = _dshot.sendCommand(static_cast(command)); - - uint64_t end_time = esp_timer_get_time(); - _last_command_timestamp = end_time; - - return result; -} - -// -void DShotCommandManager::_delay_ms(uint32_t delay_ms) -{ - if (delay_ms > 0) - { - delay(delay_ms); - } -} diff --git a/src/DShotCommandManager.h b/src/DShotCommandManager.h deleted file mode 100644 index 9b05fc3..0000000 --- a/src/DShotCommandManager.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * DShotCommandManager.h - * Advanced DShot command management for DShotRMT library - * Author: Wastl Kraus - * Date: 2025-09-04 - * License: MIT - */ - -#pragma once - -#include -#include - -// Command item -typedef struct -{ - dshot_commands_t command; - uint16_t repeat_count; - uint32_t delay_ms; -} dshot_commandmanager_item_t; - -// Advanced DShot command manager class -class DShotCommandManager -{ -public: - // Constructor - explicit DShotCommandManager(DShotRMT &dshot_instance); - - // Initialize command manager - dshot_result_t begin(); - - void handleMenuInput(const String &input, Stream &output = Serial); - - // Send a single DShot command - dshot_result_t sendCommand(dshot_commands_t command, uint16_t repeat_count = 1); - - // Send command with specified delay between repetitions - dshot_result_t sendCommandWithDelay(dshot_commands_t command, uint16_t repeat_count, uint32_t delay_ms); - - // --- MOTOR CONTROL COMMANDS --- - // Stop motor (send MOTOR_STOP command) - dshot_result_t stopMotor(); - - // Enable/disable 3D mode - dshot_result_t set3DMode(bool enable); - - // Set motor spin direction - dshot_result_t setSpinDirection(bool reversed); - - // Save current settings to ESC - dshot_result_t saveSettings(); - - // --- TELEMETRY COMMANDS --- - // Enable/disable extended telemetry - dshot_result_t setExtendedTelemetry(bool enable); - - // Request ESC information - dshot_result_t requestESCInfo(); - - // --- LED CONTROL COMMANDS (BLHeli32 only) --- - - // Control ESC LEDs (BLHeli32 only) - dshot_result_t setLED(uint8_t led_number, bool state); - - // --- BEACON COMMANDS --- - // Activate beacon (motor beeping) - dshot_result_t activateBeacon(uint8_t beacon_number); - - // --- KISS ESC SPECIFIC COMMANDS --- - // Enable/disable audio stream mode (KISS ESCs) - dshot_result_t setAudioStreamMode(bool enable); - - // Enable/disable silent mode (KISS ESCs) - dshot_result_t setSilentMode(bool enable); - - // --- SEQUENCE COMMANDS --- - // Execute a sequence of DShot commands - dshot_result_t executeSequence(const dshot_commandmanager_item_t *sequence, size_t sequence_length); - - // Execute ESC initialization sequence - dshot_result_t executeInitSequence(); - - // Execute ESC calibration sequence - dshot_result_t executeCalibrationSequence(); - - // --- UTILITY METHODS --- - // Get command name as string - static const char *getCommandName(dshot_commands_t command); - - // Check if command is valid - static bool isValidCommand(dshot_commands_t command); - - // --- GETTERS --- - // Get total number of commands sent - uint32_t getTotalCommandCount() const { return _total_commands_sent; } - - // Get number of failed commands - uint32_t getFailedCommandCount() const { return _failed_commands; } - - // Get reference to underlying DShotRMT instance - DShotRMT &getDShotRMT() { return _dshot; } - const DShotRMT &getDShotRMT() const { return _dshot; } - -private: - // --- PRIVATE MEMBERS --- - DShotRMT &_dshot; // Reference to DShotRMT instance - uint32_t _total_commands_sent; // Total commands sent counter - uint32_t _failed_commands; // Failed commands counter - uint64_t _last_command_timestamp; // Timestamp of last command - - // --- PRIVATE METHODS --- - // Execute single command with timing - dshot_result_t _executeCommand(dshot_commands_t command); - - // Wait for specified delay - void _delay_ms(uint32_t delay_ms); - - // --- CONSTANTS --- - static constexpr uint32_t DEFAULT_COMMAND_DELAY_MS = 10; - static constexpr uint16_t DEFAULT_REPEAT_COUNT = 1; - static constexpr uint16_t SETTINGS_COMMAND_REPEATS = 10; // Settings commands need 10 repeats - static constexpr uint32_t SETTINGS_COMMAND_DELAY_MS = 5; -}; diff --git a/src/DShotRMT.cpp b/src/DShotRMT.cpp index 29a591a..240cf90 100644 --- a/src/DShotRMT.cpp +++ b/src/DShotRMT.cpp @@ -42,6 +42,7 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional) _rmt_ticks{0}, _last_throttle(DSHOT_CMD_MOTOR_STOP), _last_transmission_time_us(0), + _last_command_timestamp(0), _parsed_packet(0), _packet{0}, _bitPositions{0}, @@ -154,6 +155,49 @@ dshot_result_t DShotRMT::sendCommand(uint16_t command) return _sendDShotFrame(_packet); } +// Send full DShot commands for setup etc +dshot_result_t DShotRMT::sendCommand(dshot_commands_t dshot_command, uint16_t repeat_count, uint16_t delay_us) +{ + dshot_result_t result = {false, UNKNOWN_ERROR}; + + if (!_isValidCommand(dshot_command)) + { + result.msg = INVALID_COMMAND; + return result; + } + + bool all_successful = true; + + // Send command multiple times with delay + for (uint16_t i = 0; i < repeat_count; i++) + { + dshot_result_t single_result = _executeCommand(dshot_command); + + if (!single_result.success) + { + all_successful = false; + result.msg = single_result.msg; + break; + } + + // Add delay between repetitions (except for last repetition) + if (i < repeat_count - 1) + { + delayMicroseconds(delay_us); + } + } + + // + result.success = all_successful; + + if (result.success) + { + result.msg = COMMAND_SUCCESS; + } + + return result; +} + // Get telemetry data dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count) { @@ -187,6 +231,26 @@ dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count) return result; } +// Reverse motor direction directly +dshot_result_t DShotRMT::setMotorSpinDirection(bool reversed) +{ + // Use command as a yes / no switch + dshot_commands_t command = reversed ? DSHOT_CMD_SPIN_DIRECTION_REVERSED : DSHOT_CMD_SPIN_DIRECTION_NORMAL; + + return sendCommand(command, SETTINGS_COMMAND_REPEATS, SETTINGS_COMMAND_DELAY_US); +} + +dshot_result_t DShotRMT::getESCInfo() +{ + return sendCommand(DSHOT_CMD_ESC_INFO); +} + +// Use with caution +dshot_result_t DShotRMT::saveESCSettings() +{ + return sendCommand(DSHOT_CMD_SAVE_SETTINGS, SETTINGS_COMMAND_REPEATS, SETTINGS_COMMAND_DELAY_US); +} + // Public Info & Debug Functions void DShotRMT::printDShotInfo(Stream &output) const { @@ -218,6 +282,26 @@ void DShotRMT::printCpuInfo(Stream &output) const output.printf("APB Freq = %lu Hz\n", getApbFrequency()); } +// Simple check +bool DShotRMT::_isValidCommand(dshot_commands_t command) +{ + return (command >= DSHOT_CMD_MOTOR_STOP && command <= DSHOT_CMD_MAX); +} + +// +dshot_result_t DShotRMT::_executeCommand(dshot_commands_t command) +{ + uint64_t start_time = esp_timer_get_time(); + + // Execute the command using the DShotRMT instance + dshot_result_t result = sendCommand(static_cast(command)); + + uint64_t end_time = esp_timer_get_time(); + _last_command_timestamp = end_time; + + return result; +} + // Private Initialization Functions dshot_result_t DShotRMT::_initTXChannel() { @@ -371,7 +455,7 @@ dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet) // Ensure enough time has passed since the last transmission if (!_timer_signal()) { - return {false, TIMING_CORRECTION}; + return {true, NONE}; } rmt_symbol_word_t tx_symbols[DSHOT_BITS_PER_FRAME]; diff --git a/src/DShotRMT.h b/src/DShotRMT.h index 0403808..457d648 100644 --- a/src/DShotRMT.h +++ b/src/DShotRMT.h @@ -91,9 +91,13 @@ public: dshot_result_t begin(); dshot_result_t sendThrottle(uint16_t throttle); dshot_result_t sendCommand(uint16_t command); + dshot_result_t sendCommand(dshot_commands_t dshot_command, uint16_t repeat_count = DEFAULT_CMD_REPEAT_COUNT, uint16_t delay_us = DEFAULT_CMD_DELAY_US); dshot_result_t getTelemetry(uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT); + dshot_result_t getESCInfo(); + dshot_result_t setMotorSpinDirection(bool reversed); + dshot_result_t saveESCSettings(); - // Public Info & Debug Functions + // Public Utility & Info Functions void printDShotInfo(Stream &output = Serial) const; void printCpuInfo(Stream &output = Serial) const; @@ -129,14 +133,14 @@ private: static constexpr auto const RMT_TICKS_PER_US = DSHOT_RMT_RESOLUTION / (1 * 1000 * 1000); // RMT Ticks per microsecond 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 = 192; - static constexpr auto const RMT_QUEUE_DEPTH = 4; + static constexpr auto const RMT_BUFFER_SYMBOLS = 128; + 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 = 1000; // 1.0us minimum pulse - static constexpr auto const DSHOT_PULSE_MAX = 8000; // 10.0us maximum pulse + static constexpr auto const DSHOT_PULSE_MIN = 800; // 0.8us minimum pulse + static constexpr auto const DSHOT_PULSE_MAX = 8000; // 8.0us maximum pulse static constexpr auto const DSHOT_TELEMETRY_INVALID = DSHOT_THROTTLE_MAX; // Error Messages @@ -162,6 +166,12 @@ private: static constexpr char const *INVALID_MAGNET_COUNT = "Invalid motor magnet count!"; static constexpr char const *TIMING_CORRECTION = "Timing correction!"; static constexpr char const *CALLBACK_REGISTERING_FAILED = "RMT RX Callback registering failed!"; + static constexpr char const *INVALID_COMMAND = "Invalid command!"; + static constexpr char const *COMMAND_SUCCESS = "DShot command sent successfully"; + + // --- UTILITY METHODS --- + bool _isValidCommand(dshot_commands_t command); + dshot_result_t _executeCommand(dshot_commands_t command); // Core Configuration Variables gpio_num_t _gpio; @@ -174,6 +184,7 @@ private: rmt_ticks_t _rmt_ticks; uint16_t _last_throttle; uint64_t _last_transmission_time_us; + uint64_t _last_command_timestamp; uint16_t _parsed_packet; dshot_packet_t _packet; uint8_t _bitPositions[DSHOT_BITS_PER_FRAME]; @@ -219,4 +230,10 @@ private: // 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); + + // Command Constants + static constexpr auto DEFAULT_CMD_DELAY_US = 10; + static constexpr auto DEFAULT_CMD_REPEAT_COUNT = 1; + static constexpr auto SETTINGS_COMMAND_REPEATS = 10; // Settings commands need 10 repeats + static constexpr auto SETTINGS_COMMAND_DELAY_US = 5; };