ESP32-S2 (Wemos/Lolin S2 mini)
Arduino 2.1.1 on Windows 11
Hello,
Thank you for taking the time to read this post and for any assistance you can provide. I'm a newbie when it comes to, what I consider, the more advanced aspects of microcontrollers.
My goal is to output two LED PWM channels using hardware timers to control the frequency and duty cycle of the strobing LEDs. Here are the specific requirements:
A. The LEDs need to be power-controlled (I've been using the ledc function)
B. The LEDs should be able to be strobed at specific intervals within the range of 0 to 1KHz. I'm using hardware timers so blocking functions such as non-DMA SPI updates of the display does not interfere with the strobe.
C. The duty cycle of the strobe needs to be adjustable as a float percentage ranging from 0.01 to 99.99% uptime per cycle.
Unfortunately, I've encountered an issue where I can either (unreliably) time the strobe and duty cycle or (somewhat more reliably) control the PWM power modulation, but not both simultaneously. I've tried various combinations of timer bindings, ledc channels, timing libraries, ISR handling, and rewriting the code from scratch multiple times.
I apologize for the messy state of the code, as it has undergone numerous modifications, and I'm fried at looking at the code. I would greatly appreciate any assistance or pointers you can provide to help resolve this issue.
This short segment of code seems to sometimes activate the timers, but it never seems to activate the shutoff timer reliably.
Thank you once again for your help!
#include <esp32-hal-timer.h>
// Pin assignments
#define LED_660 17
#define LED_850 16
// Intensity control variables (percentage)
int pwr_850 = 0;
int pwr_660 = 0;
// Strobe control variables
float led_hz = 1.0; // Strobe cycles per second
float led_duty = 50.0; // Duty cycle percentage
// Timing variables
volatile unsigned long on_time;
volatile unsigned long off_time;
hw_timer_t *timer_on = NULL;
hw_timer_t *timer_off = NULL;
bool leds_on = false; // Flag to track the state of LEDs
void IRAM_ATTR onTimer() {
ledcWrite(2, 254);
ledcWrite(3, 254);
timerAlarmDisable(timer_off);
timerAlarmWrite(timer_on, on_time, true);
timerAlarmEnable(timer_on);
}
void IRAM_ATTR offTimer() {
ledcWrite(2, 0);
ledcWrite(3, 0);
timerAlarmDisable(timer_on);
timerAlarmWrite(timer_off, off_time, true);
timerAlarmEnable(timer_off);
}
void startLEDs() {
ledcSetup(2, 4000, 8); // 4 kHz PWM, 8-bit resolution
ledcSetup(3, 4000, 8); // 4 kHz PWM, 8-bit resolution
ledcAttachPin(LED_660, 2);
ledcAttachPin(LED_850, 3);
if (led_hz == 0) {
ledcWrite(2, (pwr_660 / 100.0) * 255);
ledcWrite(3, (pwr_850 / 100.0) * 255);
leds_on = true;
}
else if (!leds_on && led_hz > 0.0) {
// Calculate on/off times based on strobe parameters
unsigned long cycle_time = 1000000.0 / led_hz; // Convert Hz to microseconds
off_time = ((cycle_time * led_duty) / 100);
on_time = (cycle_time - off_time);
// Update timer alarms
timerAlarmWrite(timer_on, on_time, true);
timerAlarmWrite(timer_off, off_time, true);
// Enable timers
timerAlarmEnable(timer_on);
timerAlarmEnable(timer_off); // Enable this at the same time as timerOn
leds_on = true;
}
}
void stopLEDs() {
if (leds_on) {
ledcWrite(1, 0);
ledcWrite(0, 0);
timerAlarmDisable(timer_on);
timerAlarmDisable(timer_off);
leds_on = false;
}
}
void setup() {
pinMode(LED_660, OUTPUT);
pinMode(LED_850, OUTPUT);
pinMode(15, OUTPUT);
// Create timers
timer_on = timerBegin(0, 80, true); // Timer 0, prescaler 80 (1MHz)
timer_off = timerBegin(1, 80, true); // Timer 1, prescaler 80 (1MHz)
// Attach interrupts
timerAttachInterrupt(timer_on, &onTimer, true);
timerAttachInterrupt(timer_off, &offTimer, true);
}
void loop() {
pwr_850 = 30;
pwr_660 = 30;
digitalWrite(15, 1);
led_hz = 1; // Strobe cycles per second
led_duty = 50;
startLEDs();
delay(5000);
stopLEDs();
pwr_850 = 30;
pwr_660 = 30;
digitalWrite(15, 0);
led_hz = 2; // Strobe cycles per second
led_duty = 50;
startLEDs();
delay(5000);
stopLEDs();
pwr_850 = 30;
pwr_660 = 30;
digitalWrite(15, 1);
led_hz = 5; // Strobe cycles per second
led_duty = 50;
startLEDs();
delay(5000);
stopLEDs();
pwr_850 = 30;
pwr_660 = 30;
digitalWrite(15, 0);
led_hz = 10; // Strobe cycles per second
led_duty = 50;
startLEDs();
delay(5000);
stopLEDs();
}