respiration.ino
The ESP8266 has a single hardware PWM channel, but analogWrite() routes it to any pin at ~44 kHz. The sketch retunes frequency and range, and inverts the duty for the active-low LED.
Hardware required
An ESP-12E module (ESP8266EX, 2.4 GHz Wi-Fi) mounted on a NodeMCU / Wemos D1 mini board, powered over micro-USB. 1 LED + 330 Ω resistor (or the onboard LED).
Wiring
LED on D4 through 330 Ω to 3.3 V (active-low) or to GND via a small transistor. Only one PWM pin at a time on the 8266.
How it works
analogWriteFreq/analogWriteRange reprogram the global PWM; the loop ramps the duty 0-255. The 255-niveau inversion compensates the onboard LED electronics. In the Arduino IDE, install the « esp8266 » package, select « NodeMCU 1.0 (ESP-12E Module) » then Upload (hold GPIO0 LOW if flashing fails). The A0 ADC reads 0-1 V (NodeMCU divider: 0-3.3 V).
Going further
Drive a small MOSFET to dim a lamp, or sync two NodeMCUs over radio.
respiration.ino
// Respiration LED — analogWrite() de l'ESP8266 (PWM 1 canal, ~44 kHz).
const int LED = 2; // D4 (actif-bas : duty inverse)
int niveau = 0;
int sens = 3;
void setup() {
pinMode(LED, OUTPUT);
analogWriteFreq(1000); // 1 kHz : evite le scintillement
analogWriteRange(255);
Serial.begin(115200);
}
void loop() {
niveau += sens;
if (niveau >= 255 || niveau <= 0) sens = -sens;
analogWrite(LED, 255 - niveau); // inversion actif-bas
delay(10);
}