respiration.ino
The hardware PWM (LEDC) generates the carrier by itself: analogWrite applies a 0-255 duty cycle and the LED breathes without burning CPU time. The chosen frequency avoids PWM whine.
Hardware required
A classic ESP32 board (ESP32-WROOM-32 module, dual-core Xtensa 240 MHz, Wi-Fi + Bluetooth) such as a DevKitC / DOIT V1, powered over micro-USB. 1 LED + 330 Ω resistor (or common RGB LED + anode on the pin).
Wiring
LED on 2 through 330 Ω to GND. On pins also wired to flash memory, pick another GPIO.
How it works
analogWrite/analogWriteFrequency configure an LEDC channel; the loop only ramps the duty cycle 0-255 while the peripheral generates the signal. In the Arduino IDE, install the « esp32 » board package, pick « Dev Module », the port, then Upload (hold BOOT if detection fails). GPIO34-39 are input-only; avoid GPIO6-11 and GPIO12.
Going further
Three phase-shifted LEDC channels for an RGB LED, or a small MOSFET stage to drive a power LED strip.
respiration.ino
// Respiration LED par le contrôleur LEDC (PWM matériel du SoC).
const int LED = 2;
const int FREQ = 5000; // 5 kHz : inaudible, pas de sifflement
const int RESOLUTION = 8; // 256 niveaux
int niveau = 0;
int sens = 4; // pas par étape
void setup() {
analogWriteResolution(RESOLUTION);
analogWriteFrequency(FREQ);
analogWrite(LED, 0);
}
void loop() {
niveau += sens;
if (niveau >= 255 || niveau <= 0) sens = -sens;
analogWrite(LED, niveau);
delay(8); // 255/4*8 ms ≈ 0,5 s par rampe
}