LED controller PWM timer compare values

User avatar
dg9ngf
Posts: 65
Joined: Mon Sep 16, 2019 6:49 pm
Location: Germany
Contact:

LED controller PWM timer compare values

Postby dg9ngf » Sat Jun 11, 2022 2:23 pm

Hello,

As I've seen it, the LED controller sets up PWM signals on up to 8 output channels. All channels turn on at the beginning of the shared PWM period, so all simultaneously, and then turn off when their individual compare value has been reached in the internal timer.

Is there a way to turn on channels at different times, or compare values? Or at least invert the output so that a channel isn't on during the time from LOW to CMP, but from CMP to HIGH.

I'd like to distribute the channel on-times more evenly to even the load on the PSU and have a less flickering light. One of my main scenarios is a dual-white (CCT) lighting that combines cold and warm white with 2 channels. When the light is on at maximum single brightness (100% of one channel), it doesn't flicker at all. But if it's distributed over two colours, it starts flickering again. This can be avoided if both colours (channels) simply alternate instead of partially overlap. Then it's never dark, just the colour changes very quickly according to the desired colour temperature.

I can achieve the output inverting on AVR MCUs with a flag and it works very well. But I'm using an ESP32 for a bigger application with more channels.

username
Posts: 602
Joined: Thu May 03, 2018 1:18 pm

Re: LED controller PWM timer compare values

Postby username » Sun Jun 12, 2022 12:44 am

Just checking, have you read through this ?
https://docs.espressif.com/projects/esp ... ntrol-ledc

Sprite
Espressif staff
Espressif staff
Posts: 10650
Joined: Thu Nov 26, 2015 4:08 am

Re: LED controller PWM timer compare values

Postby Sprite » Sun Jun 12, 2022 12:22 pm

For what it's worth, you can invert the GPIOs used in the GPIO matrix to get the inversion effect you want. You could also have a look at the MCPWM peripheral; while it has less outputs, it does have phase angle features.

User avatar
dg9ngf
Posts: 65
Joined: Mon Sep 16, 2019 6:49 pm
Location: Germany
Contact:

Re: LED controller PWM timer compare values

Postby dg9ngf » Sun Jun 12, 2022 2:53 pm

Yes, I've read that before and looked at it again. Do you have a certain part of that page in mind? Because it doesn't anwer my question.

MCPWM (Motor PWM) has only 3 channels? That's as much as the ATtiny1614 has. I'm using ESP32 for the 8 channels.

So I assume that it's not possible to use custom compare values. But the output inverting is already a good solution. Is it this?

Code: Select all

GPIO.func_out_sel_cfg[my_gpio_num].inv_sel = invert ? 1 : 0;

Sprite
Espressif staff
Espressif staff
Posts: 10650
Joined: Thu Nov 26, 2015 4:08 am

Re: LED controller PWM timer compare values

Postby Sprite » Mon Jun 13, 2022 2:53 am

The ESP32 has two MCPWM units, so I think you should get 6 channels. (Which is still less than 8, to be fair.)
Yes, that code would do the trick I think.

User avatar
dg9ngf
Posts: 65
Joined: Mon Sep 16, 2019 6:49 pm
Location: Germany
Contact:

Re: LED controller PWM timer compare values

Postby dg9ngf » Tue Jun 14, 2022 11:23 am

So it does work, but initialisation is not smooth. Depending on the order of instructions, the inverted channels will briefly flash up at boot, or they will remain on, and some are even different than the others.

Code: Select all

ledc_channel.channel = LEDC_CHANNEL_6;
ledc_channel.gpio_num = LED6_GPIO;
ledc_channel_config(&ledc_channel);

GPIO.func_out_sel_cfg[LED7_GPIO].inv_sel = 1;
ledc_channel.channel = LEDC_CHANNEL_7;
ledc_channel.gpio_num = LED7_GPIO;
ledc_channel_config(&ledc_channel);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, 7, PWM_MAXDUTY);
What can I do to keep all LEDs off at all times during initialisation and use the inverted channels normally later? I will provide corresponding inverted duty values, the initial value should be the maximum so that the pin remains completely off at startup.

User avatar
dg9ngf
Posts: 65
Joined: Mon Sep 16, 2019 6:49 pm
Location: Germany
Contact:

Re: LED controller PWM timer compare values

Postby dg9ngf » Tue Jun 14, 2022 12:32 pm

This is a version that sets the correct initial state, but the short flash of all inverted channels remains. This may sound small but it feels frightening if a powerful room light does that in the dark.

Code: Select all

// Configure LED timers
ledc_timer_config_t ledc_timer = {
	.duty_resolution = PWM_RESOLUTION,
	.freq_hz = 2500,
	.speed_mode = LEDC_HIGH_SPEED_MODE,
	.timer_num = LEDC_TIMER_0,
	.clk_cfg = LEDC_AUTO_CLK,
};
ledc_timer_config(&ledc_timer);

// Configure LED channels
ledc_channel_config_t ledc_channel = {
	.channel    = LEDC_CHANNEL_0,
	.duty       = 0,
	.gpio_num   = LED0_GPIO,
	.speed_mode = LEDC_HIGH_SPEED_MODE,
	.hpoint     = 0,
	.timer_sel  = LEDC_TIMER_0
};
ledc_channel_config(&ledc_channel);

// Other channels...

ledc_channel.channel = LEDC_CHANNEL_6;
ledc_channel.gpio_num = LED6_GPIO;
ledc_channel.duty = 0;
ledc_channel_config(&ledc_channel);

ledc_channel.channel = LEDC_CHANNEL_7;
ledc_channel.gpio_num = LED7_GPIO;
ledc_channel.duty = PWM_MAXDUTY;
ledc_channel_config(&ledc_channel);
GPIO.func_out_sel_cfg[LED7_GPIO].inv_sel = 1;

Sprite
Espressif staff
Espressif staff
Posts: 10650
Joined: Thu Nov 26, 2015 4:08 am

Re: LED controller PWM timer compare values

Postby Sprite » Wed Jun 15, 2022 1:35 am

You could possibly get around this by initializing all channels to an unused GPIO, starting the LEDC channels (including inverting the ones you need inverted), then manually routing the signals to the correct GPIOs using something like this:

Code: Select all

        gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);                                   
        gpio_set_direction(gpio, GPIO_MODE_OUTPUT);                                                       
        esp_rom_gpio_connect_out_signal(gpio, signal_idx, out_inv, oen_inv); 

User avatar
dg9ngf
Posts: 65
Joined: Mon Sep 16, 2019 6:49 pm
Location: Germany
Contact:

Re: LED controller PWM timer compare values

Postby dg9ngf » Thu Sep 08, 2022 9:35 pm

Sorry for the long delay, the project was stalled.

Could you please explain how to use the two functions?

I found the header for gpio_hal_iomux_func_sel here but can't figure out what the parameters mean.

I also found the header for esp_rom_gpio_connect_out_signal here but can't figure out what all parameters mean. First is the GPIO, third should probably be true for me. And the others?

Is this stuff documented anywhere or is it hidden internal magic that may change at any time?

And should these functions be called before or after ledc_channel_config? If some before/after, which when?

Sprite
Espressif staff
Espressif staff
Posts: 10650
Joined: Thu Nov 26, 2015 4:08 am

Re: LED controller PWM timer compare values

Postby Sprite » Fri Sep 09, 2022 12:39 am

Okay, so I typed a whole bunch of text here as an answer, which I'll still include as reference below, but then I noticed you can tell the LED driver to invert the channel by setting output_invert to true. I'll still include the answer as it's more generic and works for drivers other than the LEDC:
I found the header for gpio_hal_iomux_func_sel here but can't figure out what the parameters mean.
It sets up the IOMUX for the selected GPIO pin to make it act as a 'standard' GPIO. The IOMUX can be used to route some high-speed signals to the IO pin, but that's not what we want here. ('pin name' is GPIO number here, func is the function selected by the iomux)
I also found the header for esp_rom_gpio_connect_out_signal here but can't figure out what all parameters mean. First is the GPIO, third should probably be true for me. And the others?
This sets up the GPIO matrix. First argument is indeed the GPIO. Second one is the signal to route to that GPIO, you can get those from here. (The LEDC driver probably has that setup already, but the function still needs the proper signal as an argument.) Third is if the output needs to be inverted; you want that to be true. Fourth is if the output enable needs to be inverted; that should be false.

Is this stuff documented anywhere or is it hidden internal magic that may change at any time?

And should these functions be called before or after ledc_channel_config? If some before/after, which when?
That API should be stable, as it directly refers to the underlying hardware. You want to call it after configuring the driver, because otherwise the driver will overwrite the settings.

Who is online

Users browsing this forum: No registered users and 1 guest