Skip to content

ledcWrite doesn't change duty cycle if duty cycle was changed less than one period ago and if using HS LEDC (channels 0-7) #5306

Closed
@joshua-8

Description

@joshua-8

I tried to search for an issue about this didn't find anything, but if this is a known issue, I apologize.

Hardware:

Board: ESP32 Dev Module (WROOM)
Core Installation version: 1.0.6
IDE name: Arduino IDE 1.8.13
Flash Frequency: 80MHz
PSRAM enabled: Disabled
Upload Speed: 921600
Computer OS: Windows 10
no additional hardware needed.

Description:

I found this issue when using LEDC to control a servo. Sometimes, seemingly randomly, the servo wouldn't go to the position I was telling it to.
ledcWrite was not always changing the duty cycle of the signal.

ledcWrite doesn't change the duty cycle if ledcWrite is used soon after it was just used (with a shorter delay than the period of the PWM wave) and if using an HS LEDC channel(0-7) (channels 8-15 work perfectly, with the duty cycle always changing)

I was able to make a sketch that could consistently reproduce the issue for me.

Sketch:

const int outputPin = 25; //pin to attach ledc to (ch1 on scope)
const int triggerPin = 27; //pin used to trigger oscilloscope at point of interest (ch2 on scope)

const int freq = 500;
const int ledChannel = 6; //0-7 have issue, 8-15 work fine
const int resolution = 10;

void setup() {
  pinMode(triggerPin, OUTPUT);
  digitalWrite(triggerPin, LOW);

  ledcSetup(ledChannel, freq, resolution);
  ledcAttachPin(outputPin, ledChannel);

  ledcWrite(ledChannel, 800); //start PWM output

  delayMicroseconds(2500); //wait until partway through first pulse

//  delay(2); // uncomment this line to wait until second pulse and the issue goes away

  digitalWrite(triggerPin, HIGH); //trigger oscilloscope
  ledcWrite(ledChannel, 200); //attempt to change duty cycle
}

void loop() {
}

This image shows that the PWM output keeps its duty cycle of 800/1023 instead of changing to 200/1023 as set later.

issue

Adding a delay to allow the first pulse to go by makes the duty cycle change on the next pulse. This is what I would expect to always happen

line19uncommented

The issue doesn't just appear when the "first pulse" is the first pulse since the program started. ledcWrite was used three times here, the first duty cycle runs for a while, then a second duty cycle is successfully set, and where the top blue line goes up, a third frequency was set, but doesn't appear.

three

Debug Messages:

none

Solutions:

Unfortunately, I don't know enough about ledc and esp32s to be able to fix this issue.

I did find a workaround that's good enough for my servo project: if I continuously use ledcWrite from within a loop, if one call of ledcWrite doesn't work, the next one (or how ever many it takes to wait for a new cycle) will.

I know I could just use channels 8-15 since they don't have the issue, but I have a project that uses 9 pwm signals

I was hoping that I could call ledcWrite only when I need to change the duty cycle, to optimize the speed of my program.

As a related note, ledcRead returns the value that was most recently set even if the duty cycle didn't change to the new value, so I can't use that to detect if ledcWrite needs to be used.

If anyone has an idea for a better workaround, or knows why this issue happens, I would be very interested in hearing it.

I would be happy to help with any testing, or provide more information if needed.

Thank you, esp32 community, for all your work!

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions