Reimplement utils

This commit is contained in:
Wastl Kraus 2025-09-25 16:15:36 +02:00
parent 57d6a27f74
commit 7447855c32
9 changed files with 168 additions and 132 deletions

View File

@ -8,7 +8,6 @@
#include <Arduino.h> #include <Arduino.h>
#include "DShotRMT.h" #include "DShotRMT.h"
#include "DShotRMT_Utils.h" // Include utility functions
// USB serial port settings // USB serial port settings
static constexpr auto &USB_SERIAL = Serial0; static constexpr auto &USB_SERIAL = Serial0;
@ -42,7 +41,7 @@ void setup()
motor01.begin(); motor01.begin();
// Print CPU Info // Print CPU Info
printCpuInfo(USB_SERIAL); DShotRMT::printCpuInfo(USB_SERIAL);
// //
printMenu(); printMenu();
@ -81,7 +80,7 @@ void loop()
// Print motor stats every 3 seconds in continuous mode // Print motor stats every 3 seconds in continuous mode
if (continuous_throttle && (esp_timer_get_time() - last_stats_print >= 3000000)) if (continuous_throttle && (esp_timer_get_time() - last_stats_print >= 3000000))
{ {
printDShotInfo(motor01, USB_SERIAL); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
@ -133,7 +132,7 @@ void handleSerialInput(const String &input, uint16_t &throttle, bool &continuous
} }
else if (input == "info") else if (input == "info")
{ {
printDShotInfo(motor01, USB_SERIAL); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
} }
else if (input == "rpm" && IS_BIDIRECTIONAL) else if (input == "rpm" && IS_BIDIRECTIONAL)
{ {

View File

@ -17,7 +17,7 @@ static constexpr auto USB_SERIAL_BAUD = 115200;
static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_27; static constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_27;
// Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200) // Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200)
static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; static constexpr dshot_mode_t DSHOT_MODE = dshot_mode_t::DSHOT300;
// BiDirectional DShot Support (default: false) // BiDirectional DShot Support (default: false)
// Note: Bidirectional DShot is currently not officially supported // Note: Bidirectional DShot is currently not officially supported
@ -98,7 +98,7 @@ void handleSerialInput(const String &input)
} }
else if (input == "info") else if (input == "info")
{ {
motor01.printDShotInfo(); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
} }
else if (input == "rpm" && IS_BIDIRECTIONAL) else if (input == "rpm" && IS_BIDIRECTIONAL)
{ {
@ -110,14 +110,14 @@ void handleSerialInput(const String &input)
// Send DShot command // Send DShot command
int cmd_num = input.substring(4).toInt(); int cmd_num = input.substring(4).toInt();
if (cmd_num >= DSHOT_CMD_MOTOR_STOP && cmd_num <= DSHOT_CMD_MAX) if (cmd_num >= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP) && cmd_num <= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX))
{ {
dshot_result_t result = motor01.sendCommand(cmd_num); dshot_result_t result = motor01.sendCommand(cmd_num);
printDShotResult(result); printDShotResult(result);
} }
else else
{ {
USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, DSHOT_CMD_MAX); USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX));
} }
} }
else if (input == "h" || input == "help") else if (input == "h" || input == "help")

View File

@ -42,7 +42,7 @@ static constexpr auto USB_SERIAL_BAUD = 115200;
static constexpr auto MOTOR01_PIN = 17; static constexpr auto MOTOR01_PIN = 17;
// Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200) // Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200)
static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; static constexpr dshot_mode_t DSHOT_MODE = dshot_mode_t::DSHOT300;
// BiDirectional DShot Support (default: false) // BiDirectional DShot Support (default: false)
static constexpr auto IS_BIDIRECTIONAL = false; // Note: Bidirectional DShot is currently not officially supported due to instability and external hardware requirements. static constexpr auto IS_BIDIRECTIONAL = false; // Note: Bidirectional DShot is currently not officially supported due to instability and external hardware requirements.
@ -58,7 +58,7 @@ AsyncWebServer server(80);
AsyncWebSocket ws("/ws"); AsyncWebSocket ws("/ws");
// Global variables // Global variables
static uint16_t throttle = DSHOT_CMD_MOTOR_STOP; static uint16_t throttle = static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP);
static bool isArmed = false; static bool isArmed = false;
static bool last_sent_armed = false; static bool last_sent_armed = false;
static bool continuous_throttle = true; static bool continuous_throttle = true;
@ -126,7 +126,7 @@ void setup()
void loop() void loop()
{ {
static uint64_t last_serial_update = 0; static uint64_t last_serial_update = 0;
static uint16_t last_sent_throttle = DSHOT_CMD_MOTOR_STOP; static uint16_t last_sent_throttle = static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP);
static String last_sent_rpm = "N/A"; static String last_sent_rpm = "N/A";
static uint64_t last_wifi_check = 0; static uint64_t last_wifi_check = 0;
@ -166,16 +166,13 @@ void loop()
} }
else if (!isArmed && continuous_throttle) else if (!isArmed && continuous_throttle)
{ {
// Ensure motor is stopped when disarmed motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP);
} }
// Print motor stats every 3 seconds in continuous mode // Print motor stats every 3 seconds in continuous mode
if ((esp_timer_get_time() - last_serial_update >= 3000000)) if ((esp_timer_get_time() - last_serial_update >= 3000000))
{ {
motor01.printDShotInfo(); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
USB_SERIAL.println(" ");
// Get Motor RPM if bidirectional and armed // Get Motor RPM if bidirectional and armed
if (IS_BIDIRECTIONAL && isArmed) if (IS_BIDIRECTIONAL && isArmed)
@ -269,9 +266,8 @@ void handleOTAUpload(AsyncWebServerRequest *request, String filename, size_t ind
if (!index) if (!index)
{ {
// Safety: Ensure motor is stopped during update // Safety: Ensure motor is stopped during update
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP)); setArmingStatus(false);
setArmingStatus(false);
USB_SERIAL.printf("OTA Update Start: %s\n", filename.c_str()); USB_SERIAL.printf("OTA Update Start: %s\n", filename.c_str());
@ -384,7 +380,7 @@ void setArmingStatus(bool armed)
// Safety: Stop motor and reset throttle when disarming // Safety: Stop motor and reset throttle when disarming
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.println("=== MOTOR DISARMED - SAFETY STOP EXECUTED ==="); USB_SERIAL.println("=== MOTOR DISARMED - SAFETY STOP EXECUTED ===");
@ -451,7 +447,7 @@ void handleSerialInput(const String &input)
if (input == "info") if (input == "info")
{ {
motor01.printDShotInfo(); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.printf("Arming Status: %s\n", isArmed ? "ARMED" : "DISARMED"); USB_SERIAL.printf("Arming Status: %s\n", isArmed ? "ARMED" : "DISARMED");
return; return;
@ -521,7 +517,7 @@ void handleSerialInput(const String &input)
continuous_throttle = false; continuous_throttle = false;
int cmd_num = input.substring(4).toInt(); int cmd_num = input.substring(4).toInt();
if (cmd_num >= DSHOT_CMD_MOTOR_STOP && cmd_num <= DSHOT_CMD_MAX) if (cmd_num >= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP) && cmd_num <= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX))
{ {
dshot_result_t result = motor01.sendCommand(cmd_num); dshot_result_t result = motor01.sendCommand(cmd_num);
printDShotResult(result); printDShotResult(result);
@ -529,7 +525,7 @@ void handleSerialInput(const String &input)
else else
{ {
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, DSHOT_CMD_MAX); USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX));
} }
return; return;
} }
@ -584,7 +580,7 @@ void handleSerialInput(const String &input)
{ {
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
dshot_result_t result = motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); dshot_result_t result = motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
printDShotResult(result); printDShotResult(result);
return; return;
} }
@ -638,7 +634,7 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len)
{ {
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
} }
else if (web_throttle >= DSHOT_THROTTLE_MIN && web_throttle <= DSHOT_THROTTLE_MAX) else if (web_throttle >= DSHOT_THROTTLE_MIN && web_throttle <= DSHOT_THROTTLE_MAX)
{ {

View File

@ -41,7 +41,7 @@ static constexpr auto USB_SERIAL_BAUD = 115200;
static constexpr auto MOTOR01_PIN = 17; static constexpr auto MOTOR01_PIN = 17;
// Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200) // Supported: DSHOT150, DSHOT300, DSHOT600, (DSHOT1200)
static constexpr dshot_mode_t DSHOT_MODE = DSHOT300; static constexpr dshot_mode_t DSHOT_MODE = dshot_mode_t::DSHOT300;
// BiDirectional DShot Support (default: false) // BiDirectional DShot Support (default: false)
static constexpr auto IS_BIDIRECTIONAL = false; // Note: Bidirectional DShot is currently not officially supported due to instability and external hardware requirements. static constexpr auto IS_BIDIRECTIONAL = false; // Note: Bidirectional DShot is currently not officially supported due to instability and external hardware requirements.
@ -57,7 +57,7 @@ AsyncWebServer server(80);
AsyncWebSocket ws("/ws"); AsyncWebSocket ws("/ws");
// Global variables // Global variables
static uint16_t throttle = DSHOT_CMD_MOTOR_STOP; static uint16_t throttle = static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP);
static bool isArmed = false; static bool isArmed = false;
static bool continuous_throttle = true; static bool continuous_throttle = true;
@ -109,7 +109,7 @@ void setup()
void loop() void loop()
{ {
static uint64_t last_serial_update = 0; static uint64_t last_serial_update = 0;
static uint16_t last_sent_throttle = DSHOT_CMD_MOTOR_STOP; static uint16_t last_sent_throttle = static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP);
static bool last_sent_armed = false; static bool last_sent_armed = false;
static String last_sent_rpm = "N/A"; static String last_sent_rpm = "N/A";
@ -131,14 +131,13 @@ void loop()
} }
else if (!isArmed && continuous_throttle) else if (!isArmed && continuous_throttle)
{ {
// Ensure motor is stopped when disarmed motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP);
} }
// Print motor stats every 3 seconds in continuous mode // Print motor stats every 3 seconds in continuous mode
if ((esp_timer_get_time() - last_serial_update >= 3000000)) if ((esp_timer_get_time() - last_serial_update >= 3000000))
{ {
motor01.printDShotInfo(); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
@ -207,7 +206,7 @@ void setArmingStatus(bool armed)
// Safety: Stop motor and reset throttle when disarming // Safety: Stop motor and reset throttle when disarming
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.println("=== MOTOR DISARMED - SAFETY STOP EXECUTED ==="); USB_SERIAL.println("=== MOTOR DISARMED - SAFETY STOP EXECUTED ===");
} }
@ -254,7 +253,7 @@ void handleSerialInput(const String &input)
} }
if (input == "info") if (input == "info")
{ {
motor01.printDShotInfo(); DShotRMT::printDShotInfo(motor01, USB_SERIAL);
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.printf("Arming Status: %s\n", isArmed ? "ARMED" : "DISARMED"); USB_SERIAL.printf("Arming Status: %s\n", isArmed ? "ARMED" : "DISARMED");
return; return;
@ -285,7 +284,7 @@ void handleSerialInput(const String &input)
continuous_throttle = false; continuous_throttle = false;
int cmd_num = input.substring(4).toInt(); int cmd_num = input.substring(4).toInt();
if (cmd_num >= DSHOT_CMD_MOTOR_STOP && cmd_num <= DSHOT_CMD_MAX) if (cmd_num >= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP) && cmd_num <= static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX))
{ {
dshot_result_t result = motor01.sendCommand(cmd_num); dshot_result_t result = motor01.sendCommand(cmd_num);
printDShotResult(result); printDShotResult(result);
@ -293,7 +292,7 @@ void handleSerialInput(const String &input)
else else
{ {
USB_SERIAL.println(" "); USB_SERIAL.println(" ");
USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, DSHOT_CMD_MAX); USB_SERIAL.printf("Invalid command: %d (valid range: 0 - %d)\n", cmd_num, static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MAX));
} }
return; return;
} }
@ -340,7 +339,7 @@ void handleSerialInput(const String &input)
{ {
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
dshot_result_t result = motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); dshot_result_t result = motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
printDShotResult(result); printDShotResult(result);
return; return;
} }
@ -394,7 +393,7 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len)
{ {
throttle = 0; throttle = 0;
continuous_throttle = false; continuous_throttle = false;
motor01.sendCommand(DSHOT_CMD_MOTOR_STOP); motor01.sendCommand(static_cast<uint16_t>(dshotCommands_e::DSHOT_CMD_MOTOR_STOP));
} }
else if (web_throttle >= DSHOT_THROTTLE_MIN && web_throttle <= DSHOT_THROTTLE_MAX) else if (web_throttle >= DSHOT_THROTTLE_MIN && web_throttle <= DSHOT_THROTTLE_MAX)
{ {

View File

@ -58,8 +58,8 @@ DShotRMT::~DShotRMT()
{ {
if (rmt_disable(_rmt_tx_channel) == DSHOT_OK) if (rmt_disable(_rmt_tx_channel) == DSHOT_OK)
{ {
rmt_del_channel(_rmt_tx_channel); rmt_del_channel(_rmt_tx_channel);
_rmt_tx_channel = nullptr; _rmt_tx_channel = nullptr;
} }
} }
@ -68,8 +68,8 @@ DShotRMT::~DShotRMT()
{ {
if (rmt_disable(_rmt_rx_channel) == DSHOT_OK) if (rmt_disable(_rmt_rx_channel) == DSHOT_OK)
{ {
rmt_del_channel(_rmt_rx_channel); rmt_del_channel(_rmt_rx_channel);
_rmt_rx_channel = nullptr; _rmt_rx_channel = nullptr;
} }
} }
@ -109,7 +109,8 @@ dshot_result_t DShotRMT::begin()
rmt_del_channel(_rmt_tx_channel); rmt_del_channel(_rmt_tx_channel);
_rmt_tx_channel = nullptr; _rmt_tx_channel = nullptr;
if (_rmt_rx_channel) { if (_rmt_rx_channel)
{
rmt_disable(_rmt_rx_channel); rmt_disable(_rmt_rx_channel);
rmt_del_channel(_rmt_rx_channel); rmt_del_channel(_rmt_rx_channel);
_rmt_rx_channel = nullptr; _rmt_rx_channel = nullptr;
@ -292,7 +293,7 @@ dshot_result_t DShotRMT::_initTXChannel()
_tx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS; _tx_channel_config.mem_block_symbols = RMT_BUFFER_SYMBOLS;
_tx_channel_config.trans_queue_depth = RMT_QUEUE_DEPTH; _tx_channel_config.trans_queue_depth = RMT_QUEUE_DEPTH;
_rmt_tx_config.loop_count = 0; // No automatic loops - real-time calculation _rmt_tx_config.loop_count = 0; // No automatic loops - real-time calculation
_rmt_tx_config.flags.eot_level = _is_bidirectional ? 1 : 0; _rmt_tx_config.flags.eot_level = _is_bidirectional ? 1 : 0;
if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK) if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK)
@ -544,3 +545,32 @@ bool IRAM_ATTR DShotRMT::_on_rx_done(rmt_channel_handle_t rmt_rx_channel, const
return false; return false;
} }
// Public Static Utility Functions
void DShotRMT::printDShotInfo(const DShotRMT &dshot_rmt, Stream &output)
{
output.println("\n === DShot Signal Info === ");
output.printf("Current Mode: DSHOT%d\n", dshot_rmt.getMode() == dshot_mode_t::DSHOT150 ? 150 : dshot_rmt.getMode() == dshot_mode_t::DSHOT300 ? 300
: dshot_rmt.getMode() == dshot_mode_t::DSHOT600 ? 600
: dshot_rmt.getMode() == dshot_mode_t::DSHOT1200 ? 1200
: 0);
output.printf("Bidirectional: %s\n", dshot_rmt.isBidirectional() ? "YES" : "NO");
output.printf("Current Packet: ");
for (int i = DSHOT_BITS_PER_FRAME - 1; i >= 0; --i)
{
output.print((dshot_rmt.getEncodedFrameValue() >> i) & 1);
}
output.printf("\nCurrent Value: %u\n", dshot_rmt.getThrottleValue());
}
void DShotRMT::printCpuInfo(Stream &output)
{
output.println("\n === CPU Info === ");
output.printf("Chip Model: %s\n", ESP.getChipModel());
output.printf("Chip Revision: %d\n", ESP.getChipRevision());
output.printf("CPU Freq = %lu MHz\n", ESP.getCpuFreqMHz());
output.printf("XTAL Freq = %lu MHz\n", getXtalFrequencyMhz());
output.printf("APB Freq = %lu Hz\n", getApbFrequency());
}

View File

@ -9,7 +9,7 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include "dshot_definitions.h" #include <dshot_definitions.h>
#include <driver/gpio.h> #include <driver/gpio.h>
#include <driver/rmt_tx.h> #include <driver/rmt_tx.h>
#include <driver/rmt_rx.h> #include <driver/rmt_rx.h>
@ -113,6 +113,19 @@ public:
dshot_result_t saveESCSettings(); dshot_result_t saveESCSettings();
// Public Utility & Info Functions // Public Utility & Info Functions
/**
* @brief Prints detailed DShot signal information for a given DShotRMT instance.
* @param dshot_rmt The DShotRMT instance to get information from.
* @param output The output stream (e.g., Serial) to print to. Defaults to Serial.
*/
static void printDShotInfo(const DShotRMT &dshot_rmt, Stream &output = Serial);
/**
* @brief Prints detailed CPU information.
* @param output The output stream (e.g., Serial) to print to. Defaults to Serial.
*/
static void printCpuInfo(Stream &output = Serial);
/** /**
* @brief Sets the motor magnet count for RPM calculation. * @brief Sets the motor magnet count for RPM calculation.
* @param magnet_count The number of magnets in the motor. * @param magnet_count The number of magnets in the motor.
@ -197,9 +210,9 @@ private:
rmt_ticks_t _rmt_ticks; rmt_ticks_t _rmt_ticks;
uint16_t _last_throttle; uint16_t _last_throttle;
uint64_t _last_transmission_time_us; uint64_t _last_transmission_time_us;
uint64_t _last_command_timestamp; uint64_t _last_command_timestamp;
uint16_t _encoded_frame_value; uint16_t _encoded_frame_value;
dshot_packet_t _packet; dshot_packet_t _packet;
uint16_t _level0; // DShot protocol: Signal is idle-low, so pulses start by going HIGH. uint16_t _level0; // DShot protocol: Signal is idle-low, so pulses start by going HIGH.
uint16_t _level1; // DShot protocol: Signal returns to LOW after the high pulse. uint16_t _level1; // DShot protocol: Signal returns to LOW after the high pulse.

View File

@ -1,30 +0,0 @@
#include "DShotRMT_Utils.h"
#include "DShotRMT.h" // Include DShotRMT.h for DShotRMT class definition
void printDShotInfo(const DShotRMT &dshot_rmt, Stream &output)
{
output.println("\n === DShot Signal Info === ");
output.printf("Current Mode: DSHOT%d\n", dshot_rmt.getMode() == dshot_mode_t::DSHOT150 ? 150 :
dshot_rmt.getMode() == dshot_mode_t::DSHOT300 ? 300 :
dshot_rmt.getMode() == dshot_mode_t::DSHOT600 ? 600 :
dshot_rmt.getMode() == dshot_mode_t::DSHOT1200 ? 1200 : 0);
output.printf("Bidirectional: %s\n", dshot_rmt.isBidirectional() ? "YES" : "NO");
output.printf("Current Packet: ");
for (int i = DSHOT_BITS_PER_FRAME - 1; i >= 0; --i)
{
output.print((dshot_rmt.getEncodedFrameValue() >> i) & 1);
}
output.printf("\nCurrent Value: %u\n", dshot_rmt.getThrottleValue());
}
void printCpuInfo(Stream &output)
{
output.println("\n === CPU Info === ");
output.printf("Chip Model: %s\n", ESP.getChipModel());
output.printf("Chip Revision: %d\n", ESP.getChipRevision());
output.printf("CPU Freq = %lu MHz\n", ESP.getCpuFreqMHz());
output.printf("XTAL Freq = %lu MHz\n", getXtalFrequencyMhz());
output.printf("APB Freq = %lu Hz\n", getApbFrequency());
}

View File

@ -1,21 +0,0 @@
#pragma once
#include <Arduino.h>
#include "DShotRMT.h" // Include DShotRMT.h for DShotRMT class definition
/**
* @brief Utility functions for printing DShot and CPU information
*/
/**
* @brief Prints detailed DShot signal information for a given DShotRMT instance.
* @param dshot_rmt The DShotRMT instance to get information from.
* @param output The output stream (e.g., Serial) to print to. Defaults to Serial.
*/
void printDShotInfo(const DShotRMT &dshot_rmt, Stream &output = Serial);
/**
* @brief Prints detailed CPU information.
* @param output The output stream (e.g., Serial) to print to. Defaults to Serial.
*/
void printCpuInfo(Stream &output = Serial);

View File

@ -94,8 +94,8 @@ typedef struct dshot_result
{ {
bool success; bool success;
dshot_msg_code_t error_code; ///< Specific error or success code. dshot_msg_code_t error_code; ///< Specific error or success code.
uint16_t erpm; ///< Electrical RPM (eRPM) if telemetry is successful. uint16_t erpm; ///< Electrical RPM (eRPM) if telemetry is successful.
uint16_t motor_rpm; ///< Motor RPM if telemetry is successful and magnet count is known. uint16_t motor_rpm; ///< Motor RPM if telemetry is successful and magnet count is known.
} dshot_result_t; } dshot_result_t;
/** /**
@ -174,7 +174,7 @@ const uint16_t DSHOT_PULSE_MIN = 800; // 0.8us minimum pulse
const uint16_t DSHOT_PULSE_MAX = 8000; // 8.0us maximum pulse const uint16_t DSHOT_PULSE_MAX = 8000; // 8.0us maximum pulse
const uint16_t DSHOT_TELEMETRY_INVALID = DSHOT_THROTTLE_MAX; const uint16_t DSHOT_TELEMETRY_INVALID = DSHOT_THROTTLE_MAX;
const uint16_t DSHOT_TELEMETRY_BIT_POSITION = 11; // Bit position of the telemetry request flag in the DShot frame const uint16_t DSHOT_TELEMETRY_BIT_POSITION = 11; // Bit position of the telemetry request flag in the DShot frame
const uint16_t DSHOT_CRC_BIT_SHIFT = 4; // Number of bits to shift to extract data from data_and_crc const uint16_t DSHOT_CRC_BIT_SHIFT = 4; // Number of bits to shift to extract data from data_and_crc
// Command Constants (from DShotRMT.h private section) // Command Constants (from DShotRMT.h private section)
const uint16_t DEFAULT_CMD_DELAY_US = 10; const uint16_t DEFAULT_CMD_DELAY_US = 10;
@ -229,31 +229,81 @@ inline void printDShotResult(dshot_result_t &result, Stream &output = Serial)
const char *msg_str; const char *msg_str;
switch (result.error_code) switch (result.error_code)
{ {
case dshot_msg_code_t::DSHOT_ERROR_NONE: msg_str = "None"; break; case dshot_msg_code_t::DSHOT_ERROR_NONE:
case dshot_msg_code_t::DSHOT_ERROR_UNKNOWN: msg_str = "Unknown Error!"; break; msg_str = "None";
case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED: msg_str = "TX RMT channel init failed!"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED: msg_str = "RX RMT channel init failed!"; break; case dshot_msg_code_t::DSHOT_ERROR_UNKNOWN:
case dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_FAILED: msg_str = "RMT encoder init failed!"; break; msg_str = "Unknown Error!";
case dshot_msg_code_t::DSHOT_ERROR_CALLBACK_REGISTERING_FAILED: msg_str = "RMT RX Callback registering failed!"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_RECEIVER_FAILED: msg_str = "RMT receiver failed!"; break; case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_FAILED: msg_str = "Transmission failed!"; break; msg_str = "TX RMT channel init failed!";
case dshot_msg_code_t::DSHOT_ERROR_THROTTLE_NOT_IN_RANGE: msg_str = "Throttle not in range! (48 - 2047)"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_PERCENT_NOT_IN_RANGE: msg_str = "Percent not in range! (0.0 - 100.0)"; break; case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_COMMAND_NOT_VALID: msg_str = "Command not valid! (0 - 47)"; break; msg_str = "RX RMT channel init failed!";
case dshot_msg_code_t::DSHOT_ERROR_BIDIR_NOT_ENABLED: msg_str = "Bidirectional DShot not enabled!"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_FAILED: msg_str = "No valid Telemetric Frame received!"; break; case dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_INVALID_MAGNET_COUNT: msg_str = "Invalid motor magnet count!"; break; msg_str = "RMT encoder init failed!";
case dshot_msg_code_t::DSHOT_ERROR_INVALID_COMMAND: msg_str = "Invalid command!"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_TIMING_CORRECTION: msg_str = "Timing correction!"; break; case dshot_msg_code_t::DSHOT_ERROR_CALLBACK_REGISTERING_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_INIT_FAILED: msg_str = "SignalGeneratorRMT init failed!"; break; msg_str = "RMT RX Callback registering failed!";
case dshot_msg_code_t::DSHOT_ERROR_INIT_SUCCESS: msg_str = "SignalGeneratorRMT initialized successfully"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_SUCCESS: msg_str = "TX RMT channel initialized successfully"; break; case dshot_msg_code_t::DSHOT_ERROR_RECEIVER_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_SUCCESS: msg_str = "RX RMT channel initialized successfully"; break; msg_str = "RMT receiver failed!";
case dshot_msg_code_t::DSHOT_ERROR_ENCODING_SUCCESS: msg_str = "Packet encoded successfully"; break; break;
case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_SUCCESS: msg_str = "Transmission successfully"; break; case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_FAILED:
case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_SUCCESS: msg_str = "Valid Telemetric Frame received!"; break; msg_str = "Transmission failed!";
case dshot_msg_code_t::DSHOT_ERROR_COMMAND_SUCCESS: msg_str = "DShot command sent successfully"; break; break;
default: msg_str = "Unhandled Error Code!"; break; case dshot_msg_code_t::DSHOT_ERROR_THROTTLE_NOT_IN_RANGE:
msg_str = "Throttle not in range! (48 - 2047)";
break;
case dshot_msg_code_t::DSHOT_ERROR_PERCENT_NOT_IN_RANGE:
msg_str = "Percent not in range! (0.0 - 100.0)";
break;
case dshot_msg_code_t::DSHOT_ERROR_COMMAND_NOT_VALID:
msg_str = "Command not valid! (0 - 47)";
break;
case dshot_msg_code_t::DSHOT_ERROR_BIDIR_NOT_ENABLED:
msg_str = "Bidirectional DShot not enabled!";
break;
case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_FAILED:
msg_str = "No valid Telemetric Frame received!";
break;
case dshot_msg_code_t::DSHOT_ERROR_INVALID_MAGNET_COUNT:
msg_str = "Invalid motor magnet count!";
break;
case dshot_msg_code_t::DSHOT_ERROR_INVALID_COMMAND:
msg_str = "Invalid command!";
break;
case dshot_msg_code_t::DSHOT_ERROR_TIMING_CORRECTION:
msg_str = "Timing correction!";
break;
case dshot_msg_code_t::DSHOT_ERROR_INIT_FAILED:
msg_str = "SignalGeneratorRMT init failed!";
break;
case dshot_msg_code_t::DSHOT_ERROR_INIT_SUCCESS:
msg_str = "SignalGeneratorRMT initialized successfully";
break;
case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_SUCCESS:
msg_str = "TX RMT channel initialized successfully";
break;
case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_SUCCESS:
msg_str = "RX RMT channel initialized successfully";
break;
case dshot_msg_code_t::DSHOT_ERROR_ENCODING_SUCCESS:
msg_str = "Packet encoded successfully";
break;
case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_SUCCESS:
msg_str = "Transmission successfully";
break;
case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_SUCCESS:
msg_str = "Valid Telemetric Frame received!";
break;
case dshot_msg_code_t::DSHOT_ERROR_COMMAND_SUCCESS:
msg_str = "DShot command sent successfully";
break;
default:
msg_str = "Unhandled Error Code!";
break;
} }
output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", msg_str); output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", msg_str);