From b0373190bbbd3b290235e8cacfbbb7158cc88eb0 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Wed, 6 Aug 2025 23:57:26 +0200 Subject: [PATCH 1/8] ...more simplifications --- DShotRMT.cpp | 47 +++++++++++++----- DShotRMT.h | 13 +++-- examples/dshot300/dshot300.ino | 91 ++++++++++++++++------------------ 3 files changed, 87 insertions(+), 64 deletions(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index e460863..e6ce32f 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -18,7 +18,7 @@ constexpr dshot_timing_t DSHOT_TIMINGS[] = { {16, 8, 6, 3, 5, 2} // DSHOT1200 }; -// +// --- DShot Config --- DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): _gpio(gpio), _mode(mode), @@ -28,8 +28,9 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): _rmt_rx_channel(nullptr), _dshot_encoder(nullptr), _last_erpm(0), - _last_transmission_time(0), - _current_packet(0) + _current_packet(0), + _packet{0}, + _last_transmission_time(0) { // Double up frame time for bidirectional mode if (_is_bidirectional) @@ -41,6 +42,14 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): _frame_time_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME; } +// Easy Constructor +DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional): + DShotRMT((gpio_num_t)pin_nr, + mode, + is_bidirectional) +{ +} + // Init DShotRMT bool DShotRMT::begin() { @@ -69,36 +78,50 @@ bool DShotRMT::begin() return DSHOT_OK; } -// +// Deprecated, use "sendThrottle() instead" bool DShotRMT::setThrottle(uint16_t throttle) { + return sendThrottle(throttle); +} + +// Sends a valid throttle value +bool DShotRMT::sendThrottle(uint16_t throttle) +{ + static uint16_t last_throttle = DSHOT_THROTTLE_MIN; + // Precheck throttle value if (throttle < DSHOT_THROTTLE_MIN || throttle > DSHOT_THROTTLE_MAX) { Serial.println(DSHOT_MSG_06); return DSHOT_ERROR; + } else { + last_throttle = throttle; } - // - dshot_packet_t packet = _buildDShotPacket(throttle); + // Converts throttle value to dshot packet + _packet = _buildDShotPacket(last_throttle); - return (_sendDShotFrame(packet)); + return (_sendDShotFrame(_packet)); } -// +// Deprecated, use "sendCommand() instead" bool DShotRMT::sendDShotCommand(uint16_t command) { - // Precheck command value + return sendCommand(command); +} + +bool DShotRMT::sendCommand(uint16_t command) +{ + // Check for valid command if (command < DSHOT_CMD_MOTOR_STOP || command > DSHOT_CMD_MAX) { Serial.println(DSHOT_MSG_07); return DSHOT_ERROR; } - // - dshot_packet_t packet = _buildDShotPacket(command); + _packet = _buildDShotPacket(command); - return (_sendDShotFrame(packet)); + return (_sendDShotFrame(_packet)); } // diff --git a/DShotRMT.h b/DShotRMT.h index 6fb1290..84482b6 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -59,24 +59,26 @@ typedef struct dshot_timing_s uint16_t ticks_one_low; } dshot_timing_t; -// --- DShot Timing Config --- extern const dshot_timing_t DSHOT_TIMINGS[]; -// +// --- DShotRMT Class --- class DShotRMT { public: - // + // --- DShot Config --- DShotRMT(gpio_num_t gpio, dshot_mode_t mode = DSHOT300, bool is_bidirectional = false); + DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional); // --- Init RMT Module --- bool begin(); // Sets the throttle value and transmits - bool setThrottle(uint16_t throttle); + bool setThrottle(uint16_t throttle); // deprecated + bool sendThrottle(uint16_t throttle); // Sends a DShot Command - bool sendDShotCommand(uint16_t command); + bool sendDShotCommand(uint16_t command); // deprecated + bool sendCommand(uint16_t command); // Gets eRPM from ESC telemetry uint16_t getERPM(); @@ -117,6 +119,7 @@ private: // --- Buffers --- uint16_t _last_erpm; uint16_t _current_packet; + dshot_packet_t _packet; unsigned long _last_transmission_time; // diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index c11ce22..bcda260 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -14,7 +14,8 @@ static constexpr HardwareSerial &USB_SERIAL = Serial0; static constexpr uint32_t USB_SERIAL_BAUD = 115200; // Motor configuration -static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17; +// static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17; +static constexpr uint16_t MOTOR01_PIN = 17; static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; // BiDirectional DShot Support (default: false) @@ -26,14 +27,14 @@ static constexpr uint8_t MOTOR01_MAGNET_COUNT = 14; // Setup Motor Pin, DShot Mode and optional BiDirectional Support DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL); -// Prints RPM and throttle every 2 seconds if BiDirectional is enabled -void printRPMPeriodically(uint16_t throttle); +// Prints RPM if BiDirectional is enabled every ms +void printRPMPeriodically(uint16_t timer_ms); // Reads throttle value from serial input -uint16_t readSerialThrottle(); +uint16_t readSerialThrottle(HardwareSerial &serial); -// Prints out the dshot packet bitwise (Debug) -void printPacket(); +// Prints out the dshot packet bitwise every ms (Debug) +void printTXPacket(uint16_t timer_ms); // void setup() @@ -45,10 +46,10 @@ void setup() motor01.begin(); // Arm ESC with minimum throttle - motor01.setThrottle(DSHOT_THROTTLE_MIN); + // motor01.sendThrottle(DSHOT_THROTTLE_MIN); - USB_SERIAL.println("**********************"); - USB_SERIAL.println("DShotRMT Demo started."); + USB_SERIAL.println("***********************************"); + USB_SERIAL.println(" === DShotRMT Demo started. === "); USB_SERIAL.println("Enter a throttle value (48 – 2047):"); } @@ -56,78 +57,74 @@ void setup() void loop() { // Read value input from Serial - uint16_t throttle_input = readSerialThrottle(); + uint16_t throttle_input = readSerialThrottle(USB_SERIAL); // Send the value to the ESC - motor01.setThrottle(throttle_input); + motor01.sendThrottle(throttle_input); - // Print RPM if BiDirectional DShot is enabled - if (IS_BIDIRECTIONAL) - { - printRPMPeriodically(throttle_input); - } + // Prints RPM every 2 if BiDirectional DShot is enabled + printRPMPeriodically(2000); - // Prints out "raw" DShot packet - // printPacket(); + // Prints out "raw" DShot packet every 2 seconds + // printTXPacket(2000); } // Reads throttle value from serial input -uint16_t readSerialThrottle() +uint16_t readSerialThrottle(HardwareSerial &serial) { static uint16_t last_throttle = DSHOT_THROTTLE_MIN; - if (USB_SERIAL.available() > 0) + if (serial.available() > NULL) { - String input = USB_SERIAL.readStringUntil('\n'); - int throttle_input = input.toInt(); + // Reads a value + uint16_t throttle = (serial.readStringUntil('\n').toInt()); - if (throttle_input < DSHOT_THROTTLE_MIN || throttle_input > DSHOT_THROTTLE_MAX) + // Check for valid throttle value + if (throttle < DSHOT_THROTTLE_MIN || throttle > DSHOT_THROTTLE_MAX) { - USB_SERIAL.println("Invalid input. Please enter a value between 48 and 2047."); + USB_SERIAL.println("Throttle value not in range (48 - 2047)!"); return last_throttle; } - else - { - last_throttle = throttle_input; - USB_SERIAL.print("Throttle set to: "); - USB_SERIAL.println(last_throttle); - } - USB_SERIAL.println("*********************************"); - USB_SERIAL.println("Enter a throttle value (48 – 2047):"); + last_throttle = throttle; + + USB_SERIAL.println("*********************"); + USB_SERIAL.print("Throttle set to: "); + USB_SERIAL.println(last_throttle); } return last_throttle; } -// Prints RPM and throttle every 2 seconds -void printRPMPeriodically(uint16_t throttle) +// Prints RPM every ms +void printRPMPeriodically(uint16_t timer_ms) { - static unsigned long last_print_time = 0; - - if (millis() - last_print_time >= 2000) + if (IS_BIDIRECTIONAL) { - uint32_t rpm = motor01.getMotorRPM(MOTOR01_MAGNET_COUNT); + static unsigned long last_print_time = 0; - USB_SERIAL.print("Throttle: "); - USB_SERIAL.print(throttle); - USB_SERIAL.print(" | RPM: "); - USB_SERIAL.println(rpm); + if (millis() - last_print_time >= timer_ms) + { + uint32_t rpm = motor01.getMotorRPM(MOTOR01_MAGNET_COUNT); - last_print_time = millis(); + USB_SERIAL.print("RPM: "); + USB_SERIAL.println(rpm); + + last_print_time = millis(); + } } } -// -void printPacket() +// Prints "raw" packet every ms +void printTXPacket(uint16_t timer_ms) { static unsigned long last_print_time = 0; - if (millis() - last_print_time >= 2000) + if (millis() - last_print_time >= timer_ms) { - // Prints out actual DShot Packet bitwise uint16_t packet = motor01.getDShotPacket(); + // Print bit by bit for (int i = 15; i >= 0; --i) { if ((packet >> i) & 1) From 395437dd309307ac10b1946320f49d4ed55a0988 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Thu, 7 Aug 2025 18:03:05 +0200 Subject: [PATCH 2/8] ...strolling through the code --- DShotRMT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DShotRMT.h b/DShotRMT.h index 84482b6..76a5060 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -90,7 +90,7 @@ public: uint16_t getGPIO() const { return _gpio; } // Returns "raw" Dshot packet sent by RMT - uint16_t getDShotPacket() { return _current_packet; } + uint16_t getDShotPacket() const { return _current_packet; } // bool is_bidirectional() const { return _is_bidirectional; } From 392d8c64d23f4036f11934498ce6cd71fa065cf7 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Fri, 8 Aug 2025 14:43:26 +0200 Subject: [PATCH 3/8] ...something --- DShotRMT.cpp | 24 ++++++++++++------------ DShotRMT.h | 5 +++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index e6ce32f..ae6186f 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -141,7 +141,7 @@ uint16_t DShotRMT::getERPM() return _last_erpm; } - // Decode the response + // Decodes the response uint16_t new_erpm = _decodeDShotFrame(_rx_symbols); if (new_erpm != 0) { @@ -168,7 +168,7 @@ bool DShotRMT::_initTXChannel() _tx_channel_config.mem_block_symbols = DSHOT_SYMBOLS_SIZE; _tx_channel_config.trans_queue_depth = TX_BUFFER_SIZE; - // + // No loops, real time calculation for each frame _transmit_config.loop_count = 0; // ...it's a trap @@ -215,14 +215,14 @@ bool DShotRMT::_initDShotEncoder() // Use RMT to transmit a prepared DShot packet and returns it bool DShotRMT::_sendDShotFrame(const dshot_packet_t &packet) { - // Exclude calculation from timing is more stable + // Excludes calculation from timing is more stable rmt_symbol_word_t tx_symbols[DSHOT_BITS_PER_FRAME]; _encodeDShotFrame(packet, tx_symbols); // Checking timer signal if (_timer_signal()) { - // Trigger RMT Transmit + // Triggers RMT Transmit rmt_transmit(_rmt_tx_channel, _dshot_encoder, tx_symbols, DSHOT_SYMBOLS_SIZE, &_transmit_config); // Time Stamp @@ -238,7 +238,7 @@ uint16_t DShotRMT::_calculateCRC(const dshot_packet_t &packet) uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request; uint16_t crc = (data ^ (data >> 4) ^ (data >> 8)) & 0b0000000000001111; - // Invert CRC for bidirectional DShot + // Inverts CRC for bidirectional DShot if (_is_bidirectional) { crc = (~crc) & 0b0000000000001111; @@ -260,7 +260,7 @@ dshot_packet_t DShotRMT::_buildDShotPacket(const uint16_t value) // DShot Frame Container dshot_packet_t packet = {}; - // Create DShot packet + // Creates DShot packet packet.throttle_value = value; packet.telemetric_request = 0; packet.checksum = _calculateCRC(packet); @@ -275,10 +275,10 @@ bool IRAM_ATTR DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_sym // Parse actual packet into buffer _current_packet = _parseDShotPacket(packet); - // Convert the parsed dshot frame to rmt_tx data + // Converts the parsed dshot frame to rmt_tx data for (int i = 0; i < DSHOT_BITS_PER_FRAME; i++) { - // Encode RMT symbols bitwise (MSB first) - tricky + // Encoded RMT symbols bitwise (MSB first) - tricky bool bit = (_current_packet >> (DSHOT_BITS_PER_FRAME - 1 - i)) & 0b0000000000000001; if (_is_bidirectional) { @@ -303,25 +303,25 @@ uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols) { uint16_t received_frame = 0; - // Decode each symbol to reconstruct the frame + // Decodes each symbol to reconstruct the frame for (size_t i = 0; i < DSHOT_BITS_PER_FRAME; ++i) { bool bit = symbols[i].duration0 < symbols[i].duration1; received_frame = (received_frame << 1) | bit; } - // Extract payload and CRC + // Extracts payload and CRC uint16_t data = received_frame >> 4; uint16_t received_crc = received_frame & 0b0000000000001111; - // Calculate CRC for received frame + // Calculates CRC for received frame uint16_t calculated_crc = (data ^ (data >> 4) ^ (data >> 8)) & 0b0000000000001111; if (_is_bidirectional) { calculated_crc = (~calculated_crc) & 0b0000000000001111; } - // Compare CRC + // Compares CRC if (received_crc != calculated_crc) { Serial.println(DSHOT_MSG_04); diff --git a/DShotRMT.h b/DShotRMT.h index 76a5060..babce1a 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -122,7 +122,7 @@ private: dshot_packet_t _packet; unsigned long _last_transmission_time; - // + // ---Helpers --- bool _initTXChannel(); bool _initRXChannel(); bool _initDShotEncoder(); @@ -134,10 +134,11 @@ private: bool IRAM_ATTR _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols); uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols); + // --- Simple Timer --- bool _timer_signal(); bool _timer_reset(); - // Error Handling + // --- Error Handling --- static constexpr bool DSHOT_OK = 0; static constexpr bool DSHOT_ERROR = 1; static constexpr char *DSHOT_MSG_01 = "Failed to initialize TX channel!"; From 7bd10ebc484dadc2d3c577c72cee53b86d790385 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Fri, 8 Aug 2025 15:44:19 +0200 Subject: [PATCH 4/8] ...update public stuff --- README.md | 35 ++++++------------------ examples/dshot300/dshot300.ino | 17 +++++------- keywords.txt | 49 ++++++++++++++++++++++++++++++++++ library.properties | 2 +- 4 files changed, 64 insertions(+), 39 deletions(-) create mode 100644 keywords.txt diff --git a/README.md b/README.md index 1fd1186..d7c1a5b 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Supports all standard DShot modes (150, 300, 600) and features continuous frame ## 🚀 Features -- **All DShot Modes:** DSHOT150, DSHOT300 (default), DSHOT600 -- **BiDirectional DShot:** Experimental support for telemetry and RPM feedback -- **Continuous Frames:** Hardware-timed, CPU-independent signal generation +- **All DShot Modes:** DSHOT150, DSHOT300 (default), DSHOT600, (DSHOT1200) +- **BiDirectional DShot:** Experimental support for RPM feedback +- **Continuous Frames:** Independent timed, Hardware signal generation - **Configurable Pause:** Ensures ESCs can reliably detect frame boundaries - **Simple API:** Easy integration into your Arduino or ESP-IDF project @@ -33,25 +33,7 @@ git clone https://github.com/derdoktor667/DShotRMT.git ## ⚡ Quick Start ```cpp -#include - -constexpr gpio_num_t MOTOR_PIN = GPIO_NUM_17; -constexpr dshot_mode_t MODE = DSHOT300; -constexpr bool BIDIRECTIONAL = true; - -DShotRMT motor(MOTOR_PIN, MODE, BIDIRECTIONAL); - -void setup() { - Serial.begin(115200); - motor.begin(); - motor.setThrottle(1000); // Set throttle value (48–2047) -} - -void loop() { - // Optionally read RPM if bidirectional mode is enabled - uint32_t rpm = motor.getMotorRPM(14); // 14 magnets - Serial.println(rpm); -} +Use "dshot300.ino" example sketch ``` --- @@ -104,7 +86,8 @@ crc = (~(value ^ (value >> 4) ^ (value >> 8))) & 0x0F; ## 🛠️ ESP32 RMT Peripheral The RMT (Remote Control) peripheral generates accurate, hardware-timed signals for controlling external devices. -Perfect for DShot: +Perfect for DShot: +- Utilizes latest ESP-IDF APIs - Hardware-timed pulses - CPU-independent - Loop mode with inter-frame pause @@ -116,11 +99,9 @@ Perfect for DShot: - `DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool isBidirectional)` - `void begin()` -- `void setThrottle(uint16_t throttle)` -- `uint32_t getERPM()` -- `uint32_t getMotorRPM(uint8_t magnet_count)` +- `void sendThrottle(uint16_t throttle)` -See [examples/dshot300/dshot300.ino](examples/dshot300/dshot300.ino) for a full demo. +See [examples/dshot300/dshot300.ino](examples/dshot300/dshot300.ino) for a more informations. --- diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index bcda260..163661e 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -14,8 +14,11 @@ static constexpr HardwareSerial &USB_SERIAL = Serial0; static constexpr uint32_t USB_SERIAL_BAUD = 115200; // Motor configuration +// Pin number or GPIO_PIN // static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17; static constexpr uint16_t MOTOR01_PIN = 17; + +// Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200) static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; // BiDirectional DShot Support (default: false) @@ -24,18 +27,10 @@ static constexpr bool IS_BIDIRECTIONAL = false; // Motor magnet count for RPM calculation static constexpr uint8_t MOTOR01_MAGNET_COUNT = 14; -// Setup Motor Pin, DShot Mode and optional BiDirectional Support +// +// DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL); -// Prints RPM if BiDirectional is enabled every ms -void printRPMPeriodically(uint16_t timer_ms); - -// Reads throttle value from serial input -uint16_t readSerialThrottle(HardwareSerial &serial); - -// Prints out the dshot packet bitwise every ms (Debug) -void printTXPacket(uint16_t timer_ms); - // void setup() { @@ -62,7 +57,7 @@ void loop() // Send the value to the ESC motor01.sendThrottle(throttle_input); - // Prints RPM every 2 if BiDirectional DShot is enabled + // Prints out RPM if BiDirectional DShot is enabled every 2 seconds printRPMPeriodically(2000); // Prints out "raw" DShot packet every 2 seconds diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..67b4d0f --- /dev/null +++ b/keywords.txt @@ -0,0 +1,49 @@ +####################################### +# Syntax Coloring Map For DShotRMT +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +DShotRMT KEYWORD1 +dshot_mode_t KEYWORD1 +dshot_packet_t KEYWORD1 +dshot_timing_t KEYWORD1 +dshotCommands_e KEYWORD1 +dshotCommandType_e KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +setThrottle KEYWORD2 +sendThrottle KEYWORD2 +sendDShotCommand KEYWORD2 +sendCommand KEYWORD2 +getERPM KEYWORD2 +getMotorRPM KEYWORD2 +getGPIO KEYWORD2 +getDShotPacket KEYWORD2 +is_bidirectional KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +DSHOT_OFF LITERAL1 +DSHOT150 LITERAL1 +DSHOT300 LITERAL1 +DSHOT600 LITERAL1 +DSHOT1200 LITERAL1 + +DSHOT_THROTTLE_FAILSAFE LITERAL1 +DSHOT_THROTTLE_MIN LITERAL1 +DSHOT_THROTTLE_MAX LITERAL1 + +DSHOT_CMD_MOTOR_STOP LITERAL1 +DSHOT_CMD_MAX LITERAL1 + +DSHOT_CMD_TYPE_INLINE LITERAL1 +DSHOT_CMD_TYPE_BLOCKING LITERAL1 \ No newline at end of file diff --git a/library.properties b/library.properties index 4238997..e526f8f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=DShotRMT -version=0.5.0 +version=0.6.0 author=derdoktor667 maintainer=derdoktor667 sentence=DShotRMT Library supporting all DShot Types and speeds. Tested with BlHeli_S. From b8028531a63f5c90043db54b34532c54b0ed590f Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Wed, 13 Aug 2025 15:48:07 +0200 Subject: [PATCH 5/8] Update DShotRMT.cpp ...re-set telemetric bit to start motor ...don't know why it's needed right now --- DShotRMT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index ae6186f..43b2955 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -262,7 +262,7 @@ dshot_packet_t DShotRMT::_buildDShotPacket(const uint16_t value) // Creates DShot packet packet.throttle_value = value; - packet.telemetric_request = 0; + packet.telemetric_request = 1; // needed to get the motor spinning packet.checksum = _calculateCRC(packet); // From 8edbe8c5eb4177f28ba27704194ba55279a71ac0 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Wed, 13 Aug 2025 15:54:13 +0200 Subject: [PATCH 6/8] ...update namings --- DShotRMT.cpp | 6 +++--- DShotRMT.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index 43b2955..fb0a3d7 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -35,11 +35,11 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): // Double up frame time for bidirectional mode if (_is_bidirectional) { - _frame_time_us = (_timing_config.frame_length_us << 1) + DSHOT_SWITCH_TIME; + _frame_timer_us = (_timing_config.frame_length_us << 1) + DSHOT_SWITCH_TIME; } // Calculate frame time including switch time - _frame_time_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME; + _frame_timer_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME; } // Easy Constructor @@ -335,7 +335,7 @@ uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols) // Timer triggered bool DShotRMT::_timer_signal() { - return (micros() - _last_transmission_time) >= _frame_time_us; + return (micros() - _last_transmission_time) >= _frame_timer_us; } // Updates timestamp diff --git a/DShotRMT.h b/DShotRMT.h index babce1a..fc8b9f9 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -100,7 +100,7 @@ private: gpio_num_t _gpio; dshot_mode_t _mode; bool _is_bidirectional; - uint16_t _frame_time_us; + uint16_t _frame_timer_us; // --- DShot Timings --- const dshot_timing_t &_timing_config; From c37a66d5a5b2e666016cfc6037c83a8dfd4b8213 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Sun, 17 Aug 2025 18:58:40 +0200 Subject: [PATCH 7/8] ...keep things simple ...example sketch was getting out of hands --- DShotRMT.cpp | 39 +++++++++----------- DShotRMT.h | 2 +- examples/dshot300/dshot300.ino | 66 +++++++++++++--------------------- 3 files changed, 43 insertions(+), 64 deletions(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index fb0a3d7..33cd41c 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -9,13 +9,13 @@ #include "DShotRMT.h" // --- DShot Timings --- -// frame_length_us, ticks_per_bit, ticks_one_high, ticks_zero_high, ticks_zero_low, ticks_one_low +// frame_length_us, ticks_per_bit, ticks_one_high, ticks_one_low, ticks_zero_high, ticks_zero_low constexpr dshot_timing_t DSHOT_TIMINGS[] = { {0, 0, 0, 0, 0, 0}, // DSHOT_OFF - {128, 64, 48, 24, 40, 16}, // DSHOT150 - {64, 32, 24, 12, 20, 8}, // DSHOT300 - {32, 16, 12, 6, 10, 4}, // DSHOT600 - {16, 8, 6, 3, 5, 2} // DSHOT1200 + {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 }; // --- DShot Config --- @@ -48,9 +48,10 @@ DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional): mode, is_bidirectional) { + // ...just to accept pin numbers and GPIO_NUMs } -// Init DShotRMT +// Setup and configure DShotRMT bool DShotRMT::begin() { // Init TX Channel @@ -78,7 +79,7 @@ bool DShotRMT::begin() return DSHOT_OK; } -// Deprecated, use "sendThrottle() instead" +// Deprecated, use "sendThrottle()"" instead bool DShotRMT::setThrottle(uint16_t throttle) { return sendThrottle(throttle); @@ -87,24 +88,17 @@ bool DShotRMT::setThrottle(uint16_t throttle) // Sends a valid throttle value bool DShotRMT::sendThrottle(uint16_t throttle) { - static uint16_t last_throttle = DSHOT_THROTTLE_MIN; + // Make sure throttle value is valid by force + auto value = constrain(throttle, DSHOT_THROTTLE_MIN, DSHOT_THROTTLE_MAX); - // Precheck throttle value - if (throttle < DSHOT_THROTTLE_MIN || throttle > DSHOT_THROTTLE_MAX) - { - Serial.println(DSHOT_MSG_06); - return DSHOT_ERROR; - } else { - last_throttle = throttle; - } - - // Converts throttle value to dshot packet - _packet = _buildDShotPacket(last_throttle); + // Converts throttle value to dshot packet RMT symbols + _packet = _buildDShotPacket(value); + // Actually send the RMT symbols return (_sendDShotFrame(_packet)); } -// Deprecated, use "sendCommand() instead" +// Deprecated, use "sendCommand()"" instead bool DShotRMT::sendDShotCommand(uint16_t command) { return sendCommand(command); @@ -192,8 +186,9 @@ bool DShotRMT::_initRXChannel() _rx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION; _rx_channel_config.mem_block_symbols = DSHOT_SYMBOLS_SIZE; - _receive_config.signal_range_min_ns = 300; - _receive_config.signal_range_max_ns = 5000; + // TODO: need to figure out + _receive_config.signal_range_min_ns = 2; + _receive_config.signal_range_max_ns = 128; // Creates and activates RMT TX Channel if (rmt_new_rx_channel(&_rx_channel_config, &_rmt_rx_channel) != DSHOT_OK) diff --git a/DShotRMT.h b/DShotRMT.h index fc8b9f9..7e8dd25 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -54,9 +54,9 @@ typedef struct dshot_timing_s uint16_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; - uint16_t ticks_one_low; } dshot_timing_t; extern const dshot_timing_t DSHOT_TIMINGS[]; diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index 163661e..4ab2212 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -10,13 +10,13 @@ #include // USB serial port settings -static constexpr HardwareSerial &USB_SERIAL = Serial0; -static constexpr uint32_t USB_SERIAL_BAUD = 115200; +static constexpr auto &USB_SERIAL = Serial0; +static constexpr auto USB_SERIAL_BAUD = 115200; // Motor configuration // Pin number or GPIO_PIN // static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17; -static constexpr uint16_t MOTOR01_PIN = 17; +static constexpr auto MOTOR01_PIN = 17; // Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200) static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; @@ -25,10 +25,10 @@ static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; static constexpr bool IS_BIDIRECTIONAL = false; // Motor magnet count for RPM calculation -static constexpr uint8_t MOTOR01_MAGNET_COUNT = 14; +static constexpr auto MOTOR01_MAGNET_COUNT = 14; // -// +// Create the motor instance DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL); // @@ -51,48 +51,32 @@ void setup() // void loop() { - // Read value input from Serial - uint16_t throttle_input = readSerialThrottle(USB_SERIAL); - - // Send the value to the ESC - motor01.sendThrottle(throttle_input); - - // Prints out RPM if BiDirectional DShot is enabled every 2 seconds - printRPMPeriodically(2000); - - // Prints out "raw" DShot packet every 2 seconds - // printTXPacket(2000); -} - -// Reads throttle value from serial input -uint16_t readSerialThrottle(HardwareSerial &serial) -{ - static uint16_t last_throttle = DSHOT_THROTTLE_MIN; - - if (serial.available() > NULL) + static auto throttle = DSHOT_THROTTLE_MIN; + + if (USB_SERIAL.available() > NULL) { - // Reads a value - uint16_t throttle = (serial.readStringUntil('\n').toInt()); - - // Check for valid throttle value - if (throttle < DSHOT_THROTTLE_MIN || throttle > DSHOT_THROTTLE_MAX) - { - USB_SERIAL.println("Throttle value not in range (48 - 2047)!"); - return last_throttle; - } - - last_throttle = throttle; + auto new_throttle = (USB_SERIAL.readStringUntil('\n').toInt()); USB_SERIAL.println("*********************"); USB_SERIAL.print("Throttle set to: "); - USB_SERIAL.println(last_throttle); + USB_SERIAL.println(new_throttle); + + // + throttle = new_throttle; } - return last_throttle; + // Sends the value to the ESC + motor01.sendThrottle(throttle); + + // Prints out RPM if BiDirectional DShot is enabled every 2 seconds + // printRPMPeriodically(2000); + + // Debug: Prints out "raw" DShot packet every 2 seconds + print_RMT_packet(2000); } // Prints RPM every ms -void printRPMPeriodically(uint16_t timer_ms) +void printRPMPeriodically(auto timer_ms) { if (IS_BIDIRECTIONAL) { @@ -100,7 +84,7 @@ void printRPMPeriodically(uint16_t timer_ms) if (millis() - last_print_time >= timer_ms) { - uint32_t rpm = motor01.getMotorRPM(MOTOR01_MAGNET_COUNT); + auto rpm = motor01.getMotorRPM(MOTOR01_MAGNET_COUNT); USB_SERIAL.print("RPM: "); USB_SERIAL.println(rpm); @@ -111,13 +95,13 @@ void printRPMPeriodically(uint16_t timer_ms) } // Prints "raw" packet every ms -void printTXPacket(uint16_t timer_ms) +void print_RMT_packet(auto timer_ms) { static unsigned long last_print_time = 0; if (millis() - last_print_time >= timer_ms) { - uint16_t packet = motor01.getDShotPacket(); + auto packet = motor01.getDShotPacket(); // Print bit by bit for (int i = 15; i >= 0; --i) From 2f5948f3bec9eeaf397eb61855c1ed8ef7286aeb Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Sun, 17 Aug 2025 23:00:43 +0200 Subject: [PATCH 8/8] ...use some modern features ...using "auto" for some variables is good, new style --- DShotRMT.cpp | 77 +++++++++++++++++++--------------- DShotRMT.h | 55 ++++++++++++------------ examples/dshot300/dshot300.ino | 31 ++++++-------- 3 files changed, 85 insertions(+), 78 deletions(-) diff --git a/DShotRMT.cpp b/DShotRMT.cpp index 33cd41c..f64edf6 100644 --- a/DShotRMT.cpp +++ b/DShotRMT.cpp @@ -18,7 +18,7 @@ constexpr dshot_timing_t DSHOT_TIMINGS[] = { {16, 8, 6, 2, 3, 5} // DSHOT1200 }; -// --- DShot Config --- +// --- DShot Config Constructor --- DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): _gpio(gpio), _mode(mode), @@ -32,21 +32,24 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional): _packet{0}, _last_transmission_time(0) { - // Double up frame time for bidirectional mode + // Calculates frame time and adds switch/pause time + _frame_timer_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME; + + // Doubles up frame time for bidirectional mode if (_is_bidirectional) { - _frame_timer_us = (_timing_config.frame_length_us << 1) + DSHOT_SWITCH_TIME; + // DSHOT_SWITCH_TIME also needed two times + _frame_timer_us = (_frame_timer_us << 1); } - - // Calculate frame time including switch time - _frame_timer_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME; } // Easy Constructor -DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional): - DShotRMT((gpio_num_t)pin_nr, - mode, - is_bidirectional) +DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional): + DShotRMT( + (gpio_num_t)pin_nr, + mode, + is_bidirectional + ) { // ...just to accept pin numbers and GPIO_NUMs } @@ -54,24 +57,24 @@ DShotRMT::DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional): // Setup and configure DShotRMT bool DShotRMT::begin() { - // Init TX Channel + // Inits TX Channel if (!_initTXChannel()) { Serial.println(DSHOT_MSG_01); return DSHOT_ERROR; } - // Init RX Channel + // Inits RX Channel if (!_initRXChannel() && _is_bidirectional) { Serial.println(DSHOT_MSG_02); return DSHOT_ERROR; } - // Init DShot Decoder + // Inits DShot Decoder if (!_initDShotEncoder()) { - Serial.println(DSHOT_MSG_03); + // Serial.println(DSHOT_MSG_03); return DSHOT_ERROR; } @@ -109,7 +112,7 @@ bool DShotRMT::sendCommand(uint16_t command) // Check for valid command if (command < DSHOT_CMD_MOTOR_STOP || command > DSHOT_CMD_MAX) { - Serial.println(DSHOT_MSG_07); + Serial.println(DSHOT_MSG_06); return DSHOT_ERROR; } @@ -123,7 +126,7 @@ uint16_t DShotRMT::getERPM() { if (!_is_bidirectional || !_rmt_rx_channel) { - Serial.println(DSHOT_MSG_08); + Serial.println(DSHOT_MSG_07); return _last_erpm; } @@ -131,7 +134,7 @@ uint16_t DShotRMT::getERPM() rmt_symbol_word_t _rx_symbols[RX_BUFFER_SIZE]; if (!rmt_receive(_rmt_rx_channel, _rx_symbols, DSHOT_SYMBOLS_SIZE, &_receive_config)) { - Serial.println(DSHOT_MSG_09); + Serial.println(DSHOT_MSG_08); return _last_erpm; } @@ -152,10 +155,9 @@ uint32_t DShotRMT::getMotorRPM(uint8_t magnet_count) return getERPM() / pole_pairs; } -// +// --- RMT TX Config --- bool DShotRMT::_initTXChannel() { - // --- RMT TX Config --- _tx_channel_config.gpio_num = _gpio; _tx_channel_config.clk_src = DSHOT_CLOCK_SRC_DEFAULT; _tx_channel_config.resolution_hz = DSHOT_RMT_RESOLUTION; @@ -171,46 +173,55 @@ bool DShotRMT::_initTXChannel() // Creates and activates RMT TX Channel if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK) { + Serial.println(DSHOT_MSG_01); return DSHOT_ERROR; } - return (rmt_enable(_rmt_tx_channel) == 0); + return (rmt_enable(_rmt_tx_channel) == DSHOT_OK); } -// +// --- RMT RX Config --- bool DShotRMT::_initRXChannel() { - // --- RMT RX Config --- _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 = DSHOT_SYMBOLS_SIZE; - // TODO: need to figure out + // TODO: figure out ranges _receive_config.signal_range_min_ns = 2; _receive_config.signal_range_max_ns = 128; // Creates and activates RMT TX Channel if (rmt_new_rx_channel(&_rx_channel_config, &_rmt_rx_channel) != DSHOT_OK) { + Serial.println(DSHOT_MSG_02); return DSHOT_ERROR; } - return (rmt_enable(_rmt_rx_channel) == 0); + return (rmt_enable(_rmt_rx_channel) == DSHOT_OK); } -// +// --- RMT Encoder Config --- bool DShotRMT::_initDShotEncoder() { - // Creates a dummy encoder + // Encoder "config" rmt_copy_encoder_config_t encoder_config = {}; - return rmt_new_copy_encoder(&encoder_config, &_dshot_encoder) == 0; + + // Creates a dummy encoder + if (rmt_new_copy_encoder(&encoder_config, &_dshot_encoder) != DSHOT_OK) + { + Serial.println(DSHOT_MSG_03); + return DSHOT_ERROR; + } + + return DSHOT_OK; } -// Use RMT to transmit a prepared DShot packet and returns it +// Uses RMT to transmit a prepared DShot packet and returns it bool DShotRMT::_sendDShotFrame(const dshot_packet_t &packet) { - // Excludes calculation from timing is more stable + // Excluding calculation from timing is more timing stable rmt_symbol_word_t tx_symbols[DSHOT_BITS_PER_FRAME]; _encodeDShotFrame(packet, tx_symbols); @@ -257,15 +268,15 @@ dshot_packet_t DShotRMT::_buildDShotPacket(const uint16_t value) // Creates DShot packet packet.throttle_value = value; - packet.telemetric_request = 1; // needed to get the motor spinning + packet.telemetric_request = 1; // needed to get the motor spinning packet.checksum = _calculateCRC(packet); // return packet; } -// Encodes DShot packet into RMT buffer -bool IRAM_ATTR DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols) +// Encodes DShot packet into RMT buffer and places code into IRAM instead of flash +bool DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols) { // Parse actual packet into buffer _current_packet = _parseDShotPacket(packet); @@ -330,7 +341,7 @@ uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols) // Timer triggered bool DShotRMT::_timer_signal() { - return (micros() - _last_transmission_time) >= _frame_timer_us; + return (micros() - _last_transmission_time >= _frame_timer_us); } // Updates timestamp diff --git a/DShotRMT.h b/DShotRMT.h index 7e8dd25..6eab82f 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -15,20 +15,20 @@ #include // --- DShot Protocol Constants --- -static constexpr uint16_t DSHOT_THROTTLE_FAILSAFE = 0; -static constexpr uint16_t DSHOT_THROTTLE_MIN = 48; -static constexpr uint16_t DSHOT_THROTTLE_MAX = 2047; +static constexpr auto DSHOT_THROTTLE_FAILSAFE = 0; +static constexpr auto DSHOT_THROTTLE_MIN = 48; +static constexpr auto DSHOT_THROTTLE_MAX = 2047; -static constexpr uint8_t DSHOT_BITS_PER_FRAME = 16; -static constexpr uint8_t DSHOT_SWITCH_TIME = 300; // 30us -static constexpr uint16_t DSHOT_NULL_PACKET = 0b0000000000000000; +static constexpr auto DSHOT_BITS_PER_FRAME = 16; +static constexpr auto DSHOT_SWITCH_TIME = 30; // 30us +static constexpr auto DSHOT_NULL_PACKET = 0b0000000000000000; // --- RMT Config Constants --- -static constexpr rmt_clock_source_t DSHOT_CLOCK_SRC_DEFAULT = RMT_CLK_SRC_DEFAULT; -static constexpr uint32_t DSHOT_RMT_RESOLUTION = 10 * 1000 * 1000; // 10 MHz -static constexpr size_t TX_BUFFER_SIZE = DSHOT_BITS_PER_FRAME; -static constexpr size_t RX_BUFFER_SIZE = 64; // debug -static constexpr size_t DSHOT_SYMBOLS_SIZE = 64; +static constexpr auto DSHOT_CLOCK_SRC_DEFAULT = RMT_CLK_SRC_DEFAULT; +static constexpr auto DSHOT_RMT_RESOLUTION = 10 * 1000 * 1000; // 10 MHz +static constexpr auto TX_BUFFER_SIZE = DSHOT_BITS_PER_FRAME; +static constexpr auto RX_BUFFER_SIZE = 64; // debug +static constexpr auto DSHOT_SYMBOLS_SIZE = 64; // --- DShot Mode Select --- typedef enum dshot_mode_e @@ -59,6 +59,7 @@ typedef struct dshot_timing_s uint16_t ticks_zero_low; } dshot_timing_t; +// Some typedef magic for DShot timing config extern const dshot_timing_t DSHOT_TIMINGS[]; // --- DShotRMT Class --- @@ -73,11 +74,11 @@ public: bool begin(); // Sets the throttle value and transmits - bool setThrottle(uint16_t throttle); // deprecated + bool setThrottle(uint16_t throttle); // deprecated bool sendThrottle(uint16_t throttle); // Sends a DShot Command - bool sendDShotCommand(uint16_t command); // deprecated + bool sendDShotCommand(uint16_t command); // deprecated bool sendCommand(uint16_t command); // Gets eRPM from ESC telemetry @@ -86,10 +87,10 @@ public: // Converts eRPM to motor RPM uint32_t getMotorRPM(uint8_t magnet_count); - // Returns GPIO Pin + // Returns pin number uint16_t getGPIO() const { return _gpio; } - // Returns "raw" Dshot packet sent by RMT + // Debug: returns "raw" Dshot packet sent by RMT uint16_t getDShotPacket() const { return _current_packet; } // @@ -120,7 +121,7 @@ private: uint16_t _last_erpm; uint16_t _current_packet; dshot_packet_t _packet; - unsigned long _last_transmission_time; + uint32_t _last_transmission_time; // ---Helpers --- bool _initTXChannel(); @@ -131,7 +132,7 @@ private: uint16_t _calculateCRC(const dshot_packet_t &packet); dshot_packet_t _buildDShotPacket(const uint16_t value); uint16_t _parseDShotPacket(const dshot_packet_t &packet); - bool IRAM_ATTR _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols); + bool _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols); uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols); // --- Simple Timer --- @@ -139,14 +140,14 @@ private: bool _timer_reset(); // --- Error Handling --- - static constexpr bool DSHOT_OK = 0; - static constexpr bool DSHOT_ERROR = 1; - static constexpr char *DSHOT_MSG_01 = "Failed to initialize TX channel!"; - static constexpr char *DSHOT_MSG_02 = "Failed to initialize RX channe!l"; - static constexpr char *DSHOT_MSG_03 = "Failed to initialize encoder!"; - static constexpr char *DSHOT_MSG_04 = "RX CRC Check failed!"; - static constexpr char *DSHOT_MSG_06 = "Throttle value not in range (48 - 2047)!"; - static constexpr char *DSHOT_MSG_07 = "Not a valid DShot Command (0 - 47)!"; - static constexpr char *DSHOT_MSG_08 = "Bidirectional DShot support not enabled!"; - static constexpr char *DSHOT_MSG_09 = "RX RMT module failure!"; + static constexpr auto DSHOT_OK = 0; + static constexpr auto DSHOT_ERROR = 1; + static constexpr auto *DSHOT_MSG_01 = "Failed to initialize TX channel!"; + static constexpr auto *DSHOT_MSG_02 = "Failed to initialize RX channe!l"; + static constexpr auto *DSHOT_MSG_03 = "Failed to initialize DShot encoder!"; + static constexpr auto *DSHOT_MSG_04 = "RX CRC Check failed!"; + static constexpr auto *DSHOT_MSG_05 = "Throttle value not in range (48 - 2047)!"; + static constexpr auto *DSHOT_MSG_06 = "Not a valid DShot Command (0 - 47)!"; + static constexpr auto *DSHOT_MSG_07 = "Bidirectional DShot support not enabled!"; + static constexpr auto *DSHOT_MSG_08 = "RX RMT module failure!"; }; diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index 4ab2212..1556632 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -13,8 +13,7 @@ static constexpr auto &USB_SERIAL = Serial0; static constexpr auto USB_SERIAL_BAUD = 115200; -// Motor configuration -// Pin number or GPIO_PIN +// Motor configuration - Pin number or GPIO_PIN // static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17; static constexpr auto MOTOR01_PIN = 17; @@ -22,27 +21,24 @@ static constexpr auto MOTOR01_PIN = 17; static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; // BiDirectional DShot Support (default: false) -static constexpr bool IS_BIDIRECTIONAL = false; +static constexpr auto IS_BIDIRECTIONAL = false; // Motor magnet count for RPM calculation static constexpr auto MOTOR01_MAGNET_COUNT = 14; // -// Create the motor instance +// Creates the motor instance DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL); // void setup() { - // Start the USB Serial Port + // Starts the USB Serial Port USB_SERIAL.begin(USB_SERIAL_BAUD); - // Initialize DShot Signal + // Initializes DShot Signal motor01.begin(); - // Arm ESC with minimum throttle - // motor01.sendThrottle(DSHOT_THROTTLE_MIN); - USB_SERIAL.println("***********************************"); USB_SERIAL.println(" === DShotRMT Demo started. === "); USB_SERIAL.println("Enter a throttle value (48 – 2047):"); @@ -51,18 +47,17 @@ void setup() // void loop() { + // Safety first: start with DSHOT_MIN_THROTTLE static auto throttle = DSHOT_THROTTLE_MIN; + // Takes "every" throttle value if (USB_SERIAL.available() > NULL) { - auto new_throttle = (USB_SERIAL.readStringUntil('\n').toInt()); + throttle = (USB_SERIAL.readStringUntil('\n').toInt()); USB_SERIAL.println("*********************"); USB_SERIAL.print("Throttle set to: "); - USB_SERIAL.println(new_throttle); - - // - throttle = new_throttle; + USB_SERIAL.println(throttle); } // Sends the value to the ESC @@ -75,12 +70,12 @@ void loop() print_RMT_packet(2000); } -// Prints RPM every ms +// Prints RPM every X_ms void printRPMPeriodically(auto timer_ms) { if (IS_BIDIRECTIONAL) { - static unsigned long last_print_time = 0; + static auto last_print_time = 0; if (millis() - last_print_time >= timer_ms) { @@ -97,14 +92,14 @@ void printRPMPeriodically(auto timer_ms) // Prints "raw" packet every ms void print_RMT_packet(auto timer_ms) { - static unsigned long last_print_time = 0; + static auto last_print_time = 0; if (millis() - last_print_time >= timer_ms) { auto packet = motor01.getDShotPacket(); // Print bit by bit - for (int i = 15; i >= 0; --i) + for (auto i = 15; i >= 0; --i) { if ((packet >> i) & 1) {