The following function will compute the value of a sine wave using micros()
as a timebase, with adjustable frequency. It is hardcoded to expect a 12 bit resolution PWM
/** * @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) { unsigned long currentMicros = micros(); // get the current time in microseconds // calculate the sine wave value for the current time int sineValue = 2048 + 2047 * sin(2 * PI * currentMicros / (1000000 / frequency)); return sineValue; }
Based on this, we can use the basic code of our previous post ESP32 minimal Arduino PWM output example (PlatformIO) to generate a 1Hz sine wave (represented by a 10kHz PWM):
#include <Arduino.h> #include <driver/ledc.h> void setup() { Serial.begin(115200); ledcSetup(LEDC_CHANNEL_0, 10000 /* Hz */, 12); ledcAttachPin(GPIO_NUM_14, LEDC_CHANNEL_0); ledcWrite(LEDC_CHANNEL_0, 2048); // 50% } /** * @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) { unsigned long currentMicros = micros(); // get the current time in microseconds // calculate the sine wave value for the current time int sineValue = 2048 + 2047 * sin(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)); }