Open
Description
//Fixing if all bits in resolution is set = LEDC FULL ON
uint32_t max_duty = (1 << bus->channel_resolution) - 1;
if ((duty == max_duty) && (max_duty != 1)) {
duty = max_duty + 1;
If a user want to set resolution as 5 and set duty 31/32, it should be failed.
Duty ratio should be like as below.
channel_resolution = 5, duty = 0 → duty ratio = 0/32
channel_resolution = 5, duty = 1 → duty ratio = 1/32
channel_resolution = 5, duty = 2 → duty ratio = 2/32
...
channel_resolution = 5, duty = 30 → duty ratio = 30/32
channel_resolution = 5, duty = 31 → duty ratio = 31/32
channel_resolution = 5, duty = 32 → duty ratio = 32/32
However, current code makes it like below.
channel_resolution = 5, duty = 31 → duty ratio = 32/32 -> WRONG RATIO
channel_resolution = 5, duty = 32 → duty ratio = 32/32
The code on top just need to be deleted.
Activity
SuGlider commentedon Apr 7, 2025
Looking into the LEDC documentation, we can verify that the Duty goes from 0 to 2^resolution.
Using 5 buts resolution, duty goes from 0 to 32 (33 levels).
Duty 0 = 0% ... Duty = 32 = 100%.
But... Arduino API says that Duty shoud go from 0 to (2^resolution) - 1.
Therefore, for Arduino API compatibility, the resolution is 5 bits is like this:
Duty 0 = 0% ... Duty 31 = 100%.
Thus, we have a different metric for resolution.
In such case, ESP32 Arduino Core has decided to implement the Arduino API metric system.
channel_resolution = 5, duty = 31 → duty ratio = 32/32 -> Arduino API compatible
channel_resolution = 5, duty = 32 → duty ratio = 32/32 -> IDF comaptible
SuGlider commentedon Apr 7, 2025
@scrtrees - What we could change here is that
ledcWrite()
could act as IDF defines (0..32) andanalogWrite()
act as Arduino defines (0..31). In that case, duty = 31 would behave as 100%, mapping it to aledcWrite(pin, 32)
.In other words, the code you have pointed out shall be moved to
analogWrite()
and removed fromledcWrite()
.