Problem getting multiple PWM outputs with ESP32_FastPWM library

I'm working with the ESP32_fastPWM library on an ESP32 DEVKIT V1 DOIT module. The project (simplified) has the ESP32 driving 10 LEDs at 1000 Hz where each has its own duty cycle (brightness). Each LED is driven by a PWM instance (defined in the library). After instantiating each PWM instance, I using the function setPWM_manual ( ) to change the duty cycle of the respective instances over time such that each LED has its own pattern.

I'm not getting what I expect and am probably doing something dumb. After much dinking around, I thought it time to ask for help. The code below was written to demonstrate what the issue is and the initial comment section gives detail about what I'm seeing with an o-scope and what I expected to see. I'm uploading the verbose compile output....and believe I'm using the required core ESP code and Arduino IDE. I've also uploaded 2 oscilloscope screen shots showing what I'm seeing.

Any help is much appreciated. If it turns out to be a library issue, any alternative library suggestions are welcome....looking for hardware based implementation capable of at least 10 different PWM outputs of the same frequency but different duty cycle. Many thanks.....jim

/* Name:	PWM_set_manual.ino Created:	9/282024 2:58:38 PM Purpose:	minimal code to demonstrate issues I'm having with ESP32_FastPWM library using setPWM_manual() on a ESP32 Dev Kit V1 module. In the example below, there are 2 PWMinstances. The main loop updates the duty cycles of the PWM instances at different rates. The duty cycle drives an LED to cycle according to sine wave. The 8 bit values for the sine wave are in a look-up table. There are 64 steps in the sine wave. The first instance should cycle 'fast' and the second instance should cycle 'slow'.....but that is not what I'm seeing. I'm using an o-scope to look at the PWM outputs of GPIO 16 and 17 (pins 6 & 7 on the module). The code below has two defines to turn on/off calls to setPWM_manual for the fast and slow cycle rate. Here is what I'm seeing....and what I expected to see. With #define ShowSlowRate commented out, I see both PWM instances cycling at the FAST rate.....however, what I expected was to see the fast rate at GPIO 16 and nothing at GPIO 17. With #define ShowFastRate commented out, I see both PWM instances cycling at the SLOW rate.....however, what I expected was to see was nothing at GPIO 16 and the slow rate at GPIO 17. With neither #defines commented out, I see both GPIO pins outputting the same jumbled output.....what I expected was to see the fast rate at GPIO 16 and the slow rate at GPIO 17. Any help here is much appreciated. I'm probably doing something dumb, but after much dinking around without making any progress, I figured it was time to ask for some help. Thx!!!....jim */ #include <ESP32_FastPWM.h> #define UseSerial	// used to turn on/off setting up serial port #define ShowFastRate	// shows fast PWM rate on GPIO 16, module pin 6 #define ShowSlowRate	// shows slow PWM rate on GPIO 17, module pin 7 #define Debug2	// turns on digital outputs to test timeing with o-scope //----Defines and variables used to set rate of pattern change at LED strand level unsigned long OctalInterval;	// microsec interval between changes in PWM for fastest LED strobe rate unsigned long LastOctalTic;	// micros() of last time OctalInterval was met //----Defines and variables used for PWM drivers of LED strands (ESP32_FastPWM) #define NumOfPins 2	// Number of gpio pins used to drive strands of LEDS float PWMres = 8.0f;	// Resolution 256 (8-bit) float Frequency = 1000.0f;	// frequency of PWM waveform generation ESP32_FAST_PWM* PWMinstance[NumOfPins];	// array of pointers to the PWM drivers defined by ESP32_FastPWM library, one for each pin used to drive a LED // look up table for 8 bit sine wave containing 64 steps per wave cycle (TicsPerWave). Used to change duty cycle for PWM. const uint8_t SinLU[64] = { 137, 149, 161, 173, 184, 194, 205, 215, 223, 229, 236, 243, 246, 249, 251, 254, 253, 250, 248, 245, 239, 233, 226, 219, 210, 200, 189, 179, 167, 155, 143, 131, 119, 107, 95, 83, 72, 62, 51, 41, 33, 27, 20, 13, 10, 7, 5, 2, 3, 6, 8, 11, 17, 23, 30, 37, 46, 56, 67, 77, 89, 101, 113, 125 }; uint8_t Strand[NumOfPins] = { 16,17 }; #ifdef Debug2 // digital signals output to pins 25 and 26 used with o-scope to make sure we are getting into the timing cycles we expect. #define Rate4pin 25 #define Rate8pin 26 static bool tst4 = true, tst8 = true;	// used to toggle test timing with o-scope #endif //--- void printPWMInfo(ESP32_FAST_PWM* PWM_Instance);	// prints out info about the PWM instance /* ==================================================================== */ /* ==================== SETUP ========================================= */ /* ==================================================================== */ void setup() { #ifdef UseSerial	Serial.begin(115200);	while (!Serial && millis() < 5000);	delay(100);	Serial.print(F("\nStarting PWM_set_manual on "));	Serial.println(ARDUINO_BOARD);	Serial.println(ESP32_FAST_PWM_VERSION);	Serial.print("Number of pins= ");	Serial.println(NumOfPins); #endif	// Create a PWM instance for each pin, intialize with duty cycle of 0% which will make pin output low	for (int x = 0; x < NumOfPins; x++) {	PWMinstance[x] = new ESP32_FAST_PWM(Strand[x], Frequency, 0.0f, 0, PWMres);	// instantiate PWM instance with duty cycle=0, channel 0, frequency 1k, and 256 resolution	if (PWMinstance[x])	{	// non-zero pointer means instance created ok	PWMinstance[x]->setPWM();	printPWMInfo(PWMinstance[x]);	}	else {	Serial.print(" failed to initialize PWM channel="); Serial.println(x);	}	}	// set up timers and flags used to know when to change LED PWM output	OctalInterval = 16741;	// microsec interval between potential changes in PWM for fastest rate	LastOctalTic = 0;	// set timer for potential change of PWM rate for fastest BPM. Note, this drives all BPM rates (Beats::sing, dbl, quad, ocatal) #ifdef Debug2	// use digital output pins to see that timing of blocks of code for fast and slow PWM adjustment	pinMode(Rate4pin, OUTPUT);	digitalWrite(Rate4pin, 0);	pinMode(Rate8pin, OUTPUT);	digitalWrite(Rate8pin, 0); #endif } /* ==================================================================== */ /* ==================== MAIN LOOP ===================================== */ /* ==================================================================== */ void loop() {	unsigned long Now;	// value of micros() used for timing when to change PWM	static bool tstSin = true;	// boolean used to execute half time changes in PWM	static uint8_t SinIdx=0, SinIdx1=0;	// Check if it is time to change PWM rates	Now = micros();	if (Now - LastOctalTic >= OctalInterval) {	// interval for fastest BPM rate has elapsed	LastOctalTic = Now;	// set new interval #ifdef ShowFastRate	// LED oscillation should be full speed	digitalWrite(Rate8pin, tst8);	tst8 = !tst8;	PWMinstance[0]->setPWM_manual(Strand[0], SinLU[SinIdx % 64]);	// SinIdx will loop from 0-->63	SinIdx++; #endif #ifdef ShowSlowRate	// LED oscillation should be half speed	if (tstSin==true) {	digitalWrite(Rate4pin, tst4);	tst4 = !tst4;	PWMinstance[1]->setPWM_manual(Strand[1], SinLU[SinIdx1 % 64]); // SinIdx will loop from 0-->63	SinIdx1++;	}	tstSin = !tstSin;	// skip updating low speed LED every other time through main loop #endif	} } /* ==================================================================== */ /* ============================ functions ============================= */ /* ==================================================================== */ void printPWMInfo(ESP32_FAST_PWM* PWM_Instance) {	Serial.println("============================================================================================");	Serial.print("Actual data: pin = ");	Serial.print(PWM_Instance->getPin());	Serial.print(", PWM DutyCycle = ");	Serial.print(PWM_Instance->getActualDutyCycle());	Serial.print(", PWMPeriod = ");	Serial.print(PWM_Instance->getPWMPeriod());	Serial.print(", PWM Freq (Hz) = ");	Serial.println(PWM_Instance->getActualFreq(), 4);	Serial.println("============================================================================================"); } //----------------------------- 

Verbose Compiling debug version of 'PWM_set.txt (86.1 KB)
Serial output.txt (679 Bytes)


O inves de usar bibliotecas para PWM, experimente usar o recurso de LEDC
nativo do ESP32.

É muito preciso.

Ref: LED Control (LEDC) - ESP32 - — ESP-IDF Programming Guide v5.2.3 documentation

PS: I tried to compile your code using my IDE version 1.8.9, and I got compilation errors indicating errors in the library.

What release of your IDE and what library link did you use to download it?

Error:

C:\Users\ruilv\Documents\Arduino\libraries\ESP32_FastPWM-main\src/ESP32_FastPWM.h:108:37: error: 'SOC_LEDC_CHANNEL_NUM' was not declared in this scope #define _LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM) ..... ...... 

Hi, thanks for your efforts. I'm using IDE 1.8.19. I double checked the code that I uploaded by copying it and recompiling it and got no errors.....both with the Arduino IDE and Visual Studio / Visual Micro that I usually use. The library I'm using is ver 1.1.0 downloaded from GitHub ESP32_FastPWM.
I did also upload the verbose compile output with the original post, but I admit that I'm not good at making much sense out of it. Thx again....jim

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.