How to generate sin and cos waves using the LECD PWM on the STM32
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: