๐๏ธ BasePwm API Reference
๐ Overview
BasePwm is the abstract base class for all PWM (Pulse Width Modulation) implementations in the
HardFOC system.
It provides a unified interface for motor control, LED dimming, servo control,
and other PWM applications with comprehensive multi-channel support.
โจ Features
- ๐ข Multi-Channel Support - Control multiple PWM channels simultaneously
- โก Variable Frequency - Configurable frequency per channel with wide range support
- ๐ฏ Precise Duty Control - High-resolution duty cycle control with hardware precision
- ๐ Fade Operations - Smooth transitions between duty cycle values
- ๐ก๏ธ Hardware Protection - Built-in fault detection and recovery mechanisms
- ๐ Performance Monitoring - Comprehensive statistics and diagnostics
- ๐ง Lazy Initialization - Resources allocated only when needed
- ๐๏ธ Real-Time Optimized - Designed for time-critical motor control applications
๐ Header File
1
#include "inc/base/BasePwm.h"
๐ฏ Type Definitions
๐จ Error Codes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum class hf_pwm_err_t : hf_u32_t {
PWM_SUCCESS = 0, // โ
Success
PWM_ERR_FAILURE = 1, // โ General failure
PWM_ERR_NOT_INITIALIZED = 2, // โ ๏ธ Not initialized
PWM_ERR_ALREADY_INITIALIZED = 3, // โ ๏ธ Already initialized
PWM_ERR_INVALID_PARAMETER = 4, // ๐ซ Invalid parameter
PWM_ERR_NULL_POINTER = 5, // ๐ซ Null pointer
PWM_ERR_OUT_OF_MEMORY = 6, // ๐พ Out of memory
PWM_ERR_INVALID_CHANNEL = 7, // ๐ Invalid PWM channel
PWM_ERR_CHANNEL_BUSY = 8, // ๐ Channel already in use
PWM_ERR_CHANNEL_NOT_AVAILABLE = 9, // ๐ซ Channel not available
PWM_ERR_INSUFFICIENT_CHANNELS = 10, // ๐ Insufficient channels
PWM_ERR_INVALID_FREQUENCY = 11, // ๐ป Invalid frequency
PWM_ERR_FREQUENCY_TOO_HIGH = 12, // ๐ Frequency too high
PWM_ERR_FREQUENCY_TOO_LOW = 13, // ๐ Frequency too low
PWM_ERR_RESOLUTION_NOT_SUPPORTED = 14, // ๐ฏ Resolution not supported
PWM_ERR_INVALID_DUTY_CYCLE = 15, // ๐๏ธ Invalid duty cycle
PWM_ERR_DUTY_OUT_OF_RANGE = 16, // ๐ Duty cycle out of range
PWM_ERR_HARDWARE_FAULT = 17, // ๐ฅ Hardware fault
PWM_ERR_TIMER_CONFLICT = 18, // โฑ๏ธ Timer resource conflict
PWM_ERR_PIN_CONFLICT = 19, // ๐ Pin already in use
PWM_ERR_COMMUNICATION_TIMEOUT = 20, // โฐ Communication timeout
PWM_ERR_COMMUNICATION_FAILURE = 21, // ๐ก Communication failure
PWM_ERR_DEVICE_NOT_RESPONDING = 22, // ๐ Device not responding
PWM_ERR_INVALID_DEVICE_ID = 23, // ๐ Invalid device ID
PWM_ERR_UNSUPPORTED_OPERATION = 24 // ๐ซ Unsupported operation
};
๐ Statistics Structure
1
2
3
4
5
6
7
8
struct hf_pwm_statistics_t {
hf_u32_t duty_updates_count; // ๐ Total duty cycle updates
hf_u32_t frequency_changes_count; // ๐ป Total frequency changes
hf_u32_t fade_operations_count; // ๐ Total fade operations
hf_u32_t error_count; // โ Total error count
hf_u32_t channel_enables_count; // โ
Total channel enable operations
hf_u32_t channel_disables_count; // โ Total channel disable operations
};
๐๏ธ Class Interface
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class BasePwm {
public:
// ๐ง Lifecycle management
virtual ~BasePwm() noexcept = default;
virtual hf_pwm_err_t Initialize() noexcept = 0;
virtual hf_pwm_err_t Deinitialize() noexcept = 0;
bool IsInitialized() const noexcept;
bool EnsureInitialized() noexcept;
bool EnsureDeinitialized() noexcept;
// ๐ก Channel management
virtual hf_pwm_err_t EnableChannel(hf_channel_id_t channel_id) noexcept = 0;
virtual hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept = 0;
virtual bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept = 0;
// ๐๏ธ PWM control
virtual hf_pwm_err_t SetDutyCycle(hf_channel_id_t channel_id, float duty_cycle) noexcept = 0;
virtual float GetDutyCycle(hf_channel_id_t channel_id) const noexcept = 0;
virtual hf_pwm_err_t SetFrequency(hf_channel_id_t channel_id, hf_frequency_hz_t frequency) noexcept = 0;
virtual hf_pwm_err_t GetFrequency(hf_channel_id_t channel_id, hf_frequency_hz_t& frequency) const noexcept = 0;
// ๐ Advanced features
virtual hf_pwm_err_t StartFade(hf_channel_id_t channel_id, float target_duty_percent,
hf_time_t fade_time_ms) noexcept = 0;
virtual hf_pwm_err_t StopFade(hf_channel_id_t channel_id) noexcept = 0;
virtual bool IsFading(hf_channel_id_t channel_id) const noexcept = 0;
// ๐ Information and diagnostics
virtual hf_u8_t GetMaxChannels() const noexcept = 0;
virtual bool IsChannelAvailable(hf_channel_id_t channel_id) const noexcept = 0;
virtual hf_pwm_err_t GetStatistics(hf_pwm_statistics_t& stats) const noexcept = 0;
virtual hf_pwm_err_t ResetStatistics() noexcept = 0;
};
๐ฏ Core Methods
๐ง Initialization
1
bool EnsureInitialized() noexcept;
Purpose: ๐ Lazy initialization - automatically initializes PWM if not already done
Returns: true if successful, false on failure
Usage: Call before any PWM operations
๐ก Channel Control
1
2
3
hf_pwm_err_t EnableChannel(hf_channel_id_t channel_id) noexcept;
hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept;
bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept;
Purpose: ๐๏ธ Enable/disable individual PWM channels
Parameters: Channel ID (0-based indexing)
Returns: Error code or boolean status
๐๏ธ Duty Cycle Control
1
2
hf_pwm_err_t SetDutyCycle(hf_channel_id_t channel_id, float duty_percent) noexcept;
hf_pwm_err_t GetDutyCycle(hf_channel_id_t channel_id, float& duty_percent) const noexcept;
Purpose: ๐ฏ Set/get PWM duty cycle as percentage (0.0 - 100.0)
Parameters:
channel_id- Target PWM channelduty_percent- Duty cycle percentage (0.0 = 0%, 100.0 = 100%)
๐ป Frequency Control
1
2
hf_pwm_err_t SetFrequency(hf_channel_id_t channel_id, hf_frequency_hz_t frequency) noexcept;
hf_pwm_err_t GetFrequency(hf_channel_id_t channel_id, hf_frequency_hz_t& frequency) const noexcept;
Purpose: โก Set/get PWM frequency in Hz
Parameters:
channel_id- Target PWM channelfrequency- Frequency in Hz
๐ Fade Operations
1
2
3
4
hf_pwm_err_t StartFade(hf_channel_id_t channel_id, float target_duty_percent,
hf_time_t fade_time_ms) noexcept;
hf_pwm_err_t StopFade(hf_channel_id_t channel_id) noexcept;
bool IsFading(hf_channel_id_t channel_id) const noexcept;
Purpose: ๐
Smooth transitions between duty cycle values
Parameters:
target_duty_percent- Target duty cycle (0.0 - 100.0)fade_time_ms- Fade duration in milliseconds
๐ก Usage Examples
๐ฏ Basic Motor Speed Control
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "inc/mcu/esp32/EspPwm.h"
// ๐๏ธ Create PWM instance for motor control
EspPwm motor_pwm;
void setup_motor_control() {
// ๐ Initialize PWM system
if (!motor_pwm.EnsureInitialized()) {
printf("โ Failed to initialize PWM\n");
return;
}
// ๐ก Enable channel 0 for motor speed control
hf_pwm_err_t result = motor_pwm.EnableChannel(0);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to enable PWM channel: %s\n", HfPwmErrToString(result));
return;
}
// ๐ป Set PWM frequency to 20kHz (typical for motor control)
result = motor_pwm.SetFrequency(0, 20000);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to set frequency: %s\n", HfPwmErrToString(result));
return;
}
printf("โ
Motor PWM initialized successfully\n");
}
void set_motor_speed(float speed_percent) {
// ๐๏ธ Set motor speed (0-100%)
hf_pwm_err_t result = motor_pwm.SetDutyCycle(0, speed_percent);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐๏ธ Motor speed set to %.1f%%\n", speed_percent);
} else {
printf("โ Failed to set motor speed: %s\n", HfPwmErrToString(result));
}
}
void motor_control_demo() {
setup_motor_control();
// ๐ Gradually increase motor speed
for (float speed = 0.0f; speed <= 100.0f; speed += 10.0f) {
set_motor_speed(speed);
vTaskDelay(pdMS_TO_TICKS(500)); // Wait 500ms
}
// ๐ Stop motor
set_motor_speed(0.0f);
}
๐ก LED Dimming with Fade Effects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "inc/mcu/esp32/EspPwm.h"
class SmartLED {
private:
EspPwm led_pwm*;
hf_channel_id_t channel*;
public:
SmartLED(hf_channel_id_t channel) : channel*(channel) {}
bool initialize() {
// ๐ Initialize PWM for LED control
if (!led_pwm*.EnsureInitialized()) {
printf("โ Failed to initialize LED PWM\n");
return false;
}
// ๐ก Enable LED channel
hf_pwm_err_t result = led_pwm*.EnableChannel(channel*);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to enable LED channel: %s\n", HfPwmErrToString(result));
return false;
}
// ๐ป Set frequency to 1kHz (good for LED dimming)
result = led_pwm*.SetFrequency(channel*, 1000);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to set LED frequency: %s\n", HfPwmErrToString(result));
return false;
}
printf("โ
Smart LED initialized on channel %u\n", channel*);
return true;
}
void set_brightness(float brightness_percent) {
// ๐ก Set LED brightness instantly
hf_pwm_err_t result = led_pwm*.SetDutyCycle(channel*, brightness_percent);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐ก LED brightness set to %.1f%%\n", brightness_percent);
} else {
printf("โ Failed to set brightness: %s\n", HfPwmErrToString(result));
}
}
void fade_to(float target_brightness, hf_time_t fade_time_ms) {
// ๐ Start smooth fade to target brightness
hf_pwm_err_t result = led_pwm*.StartFade(channel*, target_brightness, fade_time_ms);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐
Starting fade to %.1f%% over %u ms\n", target_brightness, fade_time_ms);
} else {
printf("โ Failed to start fade: %s\n", HfPwmErrToString(result));
}
}
void breathing_effect() {
printf("๐ซ Starting breathing effect...\n");
// ๐ Fade in over 2 seconds
fade_to(100.0f, 2000);
vTaskDelay(pdMS_TO_TICKS(2500)); // Wait for fade + extra
// ๐ Fade out over 2 seconds
fade_to(0.0f, 2000);
vTaskDelay(pdMS_TO_TICKS(2500)); // Wait for fade + extra
}
bool is_fading() {
return led_pwm*.IsFading(channel*);
}
};
๐ต Multi-Channel RGB LED Control
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class RGBController {
private:
EspPwm rgb_pwm*;
static constexpr hf_channel_id_t RED_CHANNEL = 0;
static constexpr hf_channel_id_t GREEN_CHANNEL = 1;
static constexpr hf_channel_id_t BLUE_CHANNEL = 2;
public:
bool initialize() {
// ๐ Initialize RGB PWM controller
if (!rgb_pwm*.EnsureInitialized()) {
printf("โ Failed to initialize RGB PWM\n");
return false;
}
// ๐ก Enable all RGB channels
const hf_channel_id_t channels[] = {RED_CHANNEL, GREEN_CHANNEL, BLUE_CHANNEL};
const char* colors[] = {"๐ด Red", "๐ข Green", "๐ต Blue"};
for (int i = 0; i < 3; i++) {
hf_pwm_err_t result = rgb_pwm*.EnableChannel(channels[i]);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to enable %s channel: %s\n", colors[i], HfPwmErrToString(result));
return false;
}
// ๐ป Set frequency to 1kHz for all channels
result = rgb_pwm*.SetFrequency(channels[i], 1000);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to set %s frequency: %s\n", colors[i], HfPwmErrToString(result));
return false;
}
}
printf("๐ RGB Controller initialized successfully\n");
return true;
}
void set_rgb_color(float red_percent, float green_percent, float blue_percent) {
// ๐จ Set RGB color components
struct {
hf_channel_id_t channel;
float value;
const char* name;
const char* emoji;
} components[] = {
{RED_CHANNEL, red_percent, "Red", "๐ด"},
{GREEN_CHANNEL, green_percent, "Green", "๐ข"},
{BLUE_CHANNEL, blue_percent, "Blue", "๐ต"}
};
printf("๐จ Setting RGB color: R=%.1f%%, G=%.1f%%, B=%.1f%%\n",
red_percent, green_percent, blue_percent);
for (const auto& comp : components) {
hf_pwm_err_t result = rgb_pwm*.SetDutyCycle(comp.channel, comp.value);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to set %s %s: %s\n", comp.emoji, comp.name, HfPwmErrToString(result));
}
}
}
void color_demo() {
printf("๐ Starting RGB color demo...\n");
// ๐ด Pure red
set_rgb_color(100.0f, 0.0f, 0.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// ๐ข Pure green
set_rgb_color(0.0f, 100.0f, 0.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// ๐ต Pure blue
set_rgb_color(0.0f, 0.0f, 100.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// ๐ก Yellow (red + green)
set_rgb_color(100.0f, 100.0f, 0.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// ๐ฃ Magenta (red + blue)
set_rgb_color(100.0f, 0.0f, 100.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// ๐ฆ Cyan (green + blue)
set_rgb_color(0.0f, 100.0f, 100.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// โช White (all colors)
set_rgb_color(100.0f, 100.0f, 100.0f);
vTaskDelay(pdMS_TO_TICKS(1000));
// โซ Off
set_rgb_color(0.0f, 0.0f, 0.0f);
}
void rainbow_fade() {
printf("๐ Starting rainbow fade effect...\n");
// Start fade operations for smooth color transitions
rgb_pwm*.StartFade(RED_CHANNEL, 100.0f, 2000);
vTaskDelay(pdMS_TO_TICKS(500));
rgb_pwm*.StartFade(GREEN_CHANNEL, 100.0f, 2000);
vTaskDelay(pdMS_TO_TICKS(500));
rgb_pwm*.StartFade(BLUE_CHANNEL, 100.0f, 2000);
}
};
๐ค Servo Motor Control
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
class ServoController {
private:
EspPwm servo_pwm*;
hf_channel_id_t channel*;
static constexpr float SERVO_MIN_DUTY = 2.5f; // 2.5% duty cycle (0 degrees)
static constexpr float SERVO_MAX_DUTY = 12.5f; // 12.5% duty cycle (180 degrees)
static constexpr hf_frequency_hz_t SERVO_FREQ = 50; // 50Hz for standard servos
public:
ServoController(hf_channel_id_t channel) : channel*(channel) {}
bool initialize() {
// ๐ Initialize servo PWM
if (!servo_pwm*.EnsureInitialized()) {
printf("โ Failed to initialize servo PWM\n");
return false;
}
// ๐ก Enable servo channel
hf_pwm_err_t result = servo_pwm*.EnableChannel(channel*);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to enable servo channel: %s\n", HfPwmErrToString(result));
return false;
}
// ๐ป Set servo frequency to 50Hz
result = servo_pwm*.SetFrequency(channel*, SERVO_FREQ);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to set servo frequency: %s\n", HfPwmErrToString(result));
return false;
}
// ๐ฏ Set to center position (90 degrees)
set_angle(90.0f);
printf("๐ค Servo controller initialized on channel %u\n", channel*);
return true;
}
void set_angle(float angle_degrees) {
// ๐ฏ Convert angle to PWM duty cycle
// Servo range: 0-180 degrees maps to 2.5%-12.5% duty cycle
if (angle_degrees < 0.0f) angle_degrees = 0.0f;
if (angle_degrees > 180.0f) angle_degrees = 180.0f;
float duty_percent = SERVO_MIN_DUTY + (angle_degrees / 180.0f) * (SERVO_MAX_DUTY - SERVO_MIN_DUTY);
hf_pwm_err_t result = servo_pwm*.SetDutyCycle(channel*, duty_percent);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐ค Servo angle set to %.1fยฐ (%.2f%% duty)\n", angle_degrees, duty_percent);
} else {
printf("โ Failed to set servo angle: %s\n", HfPwmErrToString(result));
}
}
void smooth_move_to(float target_angle, hf_time_t move_time_ms) {
// ๐ Smooth movement to target angle
float current_duty, target_duty;
servo_pwm*.GetDutyCycle(channel*, current_duty);
// Calculate target duty cycle
if (target_angle < 0.0f) target_angle = 0.0f;
if (target_angle > 180.0f) target_angle = 180.0f;
target_duty = SERVO_MIN_DUTY + (target_angle / 180.0f) * (SERVO_MAX_DUTY - SERVO_MIN_DUTY);
hf_pwm_err_t result = servo_pwm*.StartFade(channel*, target_duty, move_time_ms);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐ Servo smoothly moving to %.1fยฐ over %u ms\n", target_angle, move_time_ms);
} else {
printf("โ Failed to start smooth movement: %s\n", HfPwmErrToString(result));
}
}
void sweep_demo() {
printf("๐ Starting servo sweep demo...\n");
// ๐ Sweep from 0 to 180 degrees
for (float angle = 0.0f; angle <= 180.0f; angle += 30.0f) {
set_angle(angle);
vTaskDelay(pdMS_TO_TICKS(1000));
}
// ๐ Sweep back from 180 to 0 degrees
for (float angle = 180.0f; angle >= 0.0f; angle -= 30.0f) {
set_angle(angle);
vTaskDelay(pdMS_TO_TICKS(1000));
}
// ๐ฏ Return to center
set_angle(90.0f);
}
};
๐ Performance and Diagnostics
๐ Statistics Monitoring
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void monitor_pwm_performance(BasePwm& pwm) {
hf_pwm_statistics_t stats;
hf_pwm_err_t result = pwm.GetStatistics(stats);
if (result == hf_pwm_err_t::PWM_SUCCESS) {
printf("๐ PWM Performance Statistics:\n");
printf(" ๐ Duty Updates: %u\n", stats.duty_updates_count);
printf(" ๐ป Frequency Changes: %u\n", stats.frequency_changes_count);
printf(" ๐ Fade Operations: %u\n", stats.fade_operations_count);
printf(" โ
Channel Enables: %u\n", stats.channel_enables_count);
printf(" โ Channel Disables: %u\n", stats.channel_disables_count);
printf(" โ ๏ธ Total Errors: %u\n", stats.error_count);
}
}
๐ก๏ธ Error Handling Best Practices
๐ฏ Comprehensive Error Checking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
hf_pwm_err_t safe_set_duty_cycle(BasePwm& pwm, hf_channel_id_t channel, float duty) {
// โ
Validate duty cycle range
if (duty < 0.0f || duty > 100.0f) {
printf("โ Invalid duty cycle: %.2f%% (must be 0-100%%)\n", duty);
return hf_pwm_err_t::PWM_ERR_DUTY_OUT_OF_RANGE;
}
// โ
Check if channel is available
if (!pwm.IsChannelAvailable(channel)) {
printf("โ Channel %u not available\n", channel);
return hf_pwm_err_t::PWM_ERR_INVALID_CHANNEL;
}
// โ
Ensure PWM is initialized
if (!pwm.EnsureInitialized()) {
printf("โ Failed to initialize PWM\n");
return hf_pwm_err_t::PWM_ERR_NOT_INITIALIZED;
}
// โ
Enable channel if not already enabled
if (!pwm.IsChannelEnabled(channel)) {
hf_pwm_err_t result = pwm.EnableChannel(channel);
if (result != hf_pwm_err_t::PWM_SUCCESS) {
printf("โ Failed to enable channel %u: %s\n", channel, HfPwmErrToString(result));
return result;
}
}
// ๐๏ธ Set duty cycle
return pwm.SetDutyCycle(channel, duty);
}
๐๏ธ Performance Considerations
โก Optimization Tips
- ๐ข Channel Limits - Check
GetMaxChannels()before allocating channels - ๐ป Frequency Ranges - Respect hardware frequency limitations
- ๐ฏ Resolution Trade-offs - Higher frequencies may reduce duty cycle resolution
- ๐ Fade Performance - Hardware-based fading is faster than software loops
- ๐พ Memory Usage - Use lazy initialization to save memory
๐ Typical Performance Ranges
| Hardware | Channels | Frequency Range | Resolution |
|โโโโโ|โโโโโ|โโโโโโโ|โโโโโ-|
| ESP32-C6 LEDC | 8 | 1Hz - 40MHz | 1-20 bits |
| External PWM ICs | 4-16 | 1Hz - 1.5MHz | 8-16 bits |
| Motor Controllers | 2-6 | 1kHz - 100kHz | 10-16 bits |
๐งต Thread Safety
The BasePwm class is not thread-safe.
For concurrent access,
use appropriate synchronization or consider thread-safe wrapper implementations.
๐ Related Documentation
- EspPwm API Reference - ESP32-C6 PWM implementation
- BaseGpio API Reference - GPIO interface for PWM output pins
- HardwareTypes Reference - Platform-agnostic type definitions