Page 1 of 1

LED-PWM example for a beginner?

Posted: Thu Dec 29, 2016 2:27 pm
by jabakobob
Hi!

I've just started programming the ESP32 with IDF, and I am a complete beginner. I've managed to set up the tool chain and flash some examples. The next step I want to take is to control a motor with a PWM signal. It looks like the LED-PWM function of ESP32 is very versatile, but I am a bit overwhelmed with all the talk about clocks and dividers and high speed timers etc.

I'm looking for some example code that explains all the steps I need to take to get a PWM signal to a GPIO pin. I want the frequency of the signal to be around 20-25kHz (to avoid audible oscillations). I want to vary the duty cycle from 0% to 100%, the phase of the PWM signal is not important.

Is there someone who has some working code to share?

Thank you for your help in advance!
Jakob

Re: LED-PWM example for a beginner?

Posted: Thu Dec 29, 2016 5:40 pm
by onehorse
Here is an example using the Arduino IDE:

https://github.com/kriswiner/ESP32/tree/master/PWM

Re: LED-PWM example for a beginner?

Posted: Thu Dec 29, 2016 9:39 pm
by jabakobob
I've already seen that example. But as far as I understand, this just works if I use the Arduino IDE, right? Those ledc-funtions are not available in IDF, are they?

I don't want to use the Arduino IDE since it is still missing a few important bits (as far as I understand UDP and analog read are still missing, which is important for my project)

Re: LED-PWM example for a beginner?

Posted: Fri Dec 30, 2016 12:45 am
by ESP_Angus
It's not a standalone example, but in esp-idf the "16_pcnt" example uses the LEDC PWM engine to generate pulses for the pulse count (PCNT) unit to count. You can break out the PCNT example code by itself to control an LED.

The LEDC reference documentation is here: http://esp-idf.readthedocs.io/en/latest ... ader-files

Re: LED-PWM example for a beginner?

Posted: Tue Jan 03, 2017 4:44 pm
by jabakobob
Thanks a lot, Angus! That example helped a lot, I was able to get it working. It turned out to be really simple:

- first call ledc_channel_config() to set up a PWM channel
- then call ledc_timer_config() to set up a timer

There's one caveat: don't switch the order of the calls. I tried to set up the timer first, then the channel, but that didn't work. So don't switch the order of those two statements.

Once the PWM channel is set up, you can change the duty cycle by calling ledc_set_duty() followed by ledc_update_duty().

In case anybody else is interested, here's the code I used to set up PWM for two motors (left & right):

Code: Select all

#include <math.h>
#include "driver/ledc.h"
#include "esp_err.h"

#define MOTOR_PWM_CHANNEL_LEFT LEDC_CHANNEL_1
#define MOTOR_PWM_CHANNEL_RIGHT LEDC_CHANNEL_2
#define MOTOR_PWM_TIMER LEDC_TIMER_1
#define MOTOR_PWM_BIT_NUM LEDC_TIMER_10_BIT

#define RIGHT_PWM_PIN GPIO_NUM_19
#define LEFT_PWM_PIN GPIO_NUM_21

void motor_pwm_init(void)
{
    ledc_channel_config_t ledc_channel_left = {0}, ledc_channel_right = {0};
    ledc_channel_left.gpio_num = LEFT_PWM_PIN;
    ledc_channel_left.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_channel_left.channel = MOTOR_PWM_CHANNEL_LEFT;
    ledc_channel_left.intr_type = LEDC_INTR_DISABLE;
    ledc_channel_left.timer_sel = MOTOR_PWM_TIMER;
    ledc_channel_left.duty = 0;
	
    ledc_channel_right.gpio_num = RIGHT_PWM_PIN;
    ledc_channel_right.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_channel_right.channel = MOTOR_PWM_CHANNEL_RIGHT;
    ledc_channel_right.intr_type = LEDC_INTR_DISABLE;
    ledc_channel_right.timer_sel = MOTOR_PWM_TIMER;
    ledc_channel_right.duty = 0;
	
    ledc_timer_config_t ledc_timer = {0};
    ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_timer.bit_num = MOTOR_PWM_BIT_NUM;
    ledc_timer.timer_num = MOTOR_PWM_TIMER;
    ledc_timer.freq_hz = 25000;
	
	ESP_ERROR_CHECK( ledc_channel_config(&ledc_channel_left) );
	ESP_ERROR_CHECK( ledc_channel_config(&ledc_channel_right) );
	ESP_ERROR_CHECK( ledc_timer_config(&ledc_timer) );
}

void motor_pwm_set(float left_duty_fraction, float right_duty_fraction) {
	uint32_t max_duty = (1 << MOTOR_PWM_BIT_NUM) - 1;
	uint32_t left_duty = lroundf(left_duty_fraction * (float)max_duty);
	uint32_t right_duty = lroundf(right_duty_fraction * (float)max_duty);
	
	ESP_ERROR_CHECK( ledc_set_duty(LEDC_HIGH_SPEED_MODE, MOTOR_PWM_CHANNEL_LEFT, left_duty) );
	ESP_ERROR_CHECK( ledc_update_duty(LEDC_HIGH_SPEED_MODE, MOTOR_PWM_CHANNEL_LEFT) );

	ESP_ERROR_CHECK( ledc_set_duty(LEDC_HIGH_SPEED_MODE, MOTOR_PWM_CHANNEL_RIGHT, right_duty) );
	ESP_ERROR_CHECK( ledc_update_duty(LEDC_HIGH_SPEED_MODE, MOTOR_PWM_CHANNEL_RIGHT) );
}

Re: LED-PWM example for a beginner?

Posted: Tue Jun 12, 2018 4:28 pm
by dwitit
Thanks a lot, I had those functions flipped because they were flipped in the ledc example in the IDF...