Based on our previous post How to generate PWM output representing a sine wave on the ESP32 (Arduino/PlatformIO) this post uses two different IO pins to generate both a sine and a cosine wave dynamically.
#include <Arduino.h> #include <driver/ledc.h> void setup() { Serial.begin(115200); ledcSetup(LEDC_CHANNEL_0, 10000 /* Hz */, 12); ledcSetup(LEDC_CHANNEL_1, 10000 /* Hz */, 12); ledcAttachPin(GPIO_NUM_32, LEDC_CHANNEL_0); ledcAttachPin(GPIO_NUM_25, LEDC_CHANNEL_1); } /** * @brief Calculate the PWM duty cycle (assuming 12 bits resolution) of a sine wave of * given frequency. micros() is used as a timebase * * @param frequency The frequency in Hz * @return int the corresponding 12-bit PWM value */ int sinePWMValue(float frequency, int maxPWMValue, float (*sinCos)(float)) { unsigned long currentMicros = micros(); // get the current time in microseconds // calculate the sine wave value for the current time int halfMax = maxPWMValue/2; int sineValue = halfMax + (halfMax-10) * sinCos(2 * PI * currentMicros / (1000000 / frequency)); return sineValue; } void loop() { // Example of how to change the duty cycle to 25% ledcWrite(LEDC_CHANNEL_0, sinePWMValue(1.0, 4096, sinf)); ledcWrite(LEDC_CHANNEL_1, sinePWMValue(1.0, 4096, cosf)); }
The output, filtered by a 4th order Salley-Key filter each (using the LM324) looks like this: