Built-in project · ESP32-C3-DevKitM-1

ESP32-C3 PWM fade

Breathes an LED on GPIO 4 and the on-board one on GPIO 8 with analogWrite, so the waveform comes out of the LEDC hardware and the core sleeps between steps. The whole build, an ESP32-C3 and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Runs in your browser. Free, and no account needed.

ESP32-C3 PWM fade · ESP32-C3-DevKitM-1live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · ESP32-C3-DevKitM-1
// PWM fade: a breathing LED on hardware PWM.
//
// The `fade` example next door bit-bangs its waveform: it holds the pin high
// for a while and low for a while, and the core is awake for every microsecond
// of it. This one hands the pin to LEDC, the chip's LED PWM controller, and
// then does nothing but change a number thirty-three times a second. The
// waveform comes out of the hardware, so the core spends its life asleep and
// the edges still land where they should.
//
// analogWrite is the Arduino spelling and it is all this needs: 0 to 255 at
// 1 kHz on any GPIO, because LEDC reaches the pins through the GPIO matrix and
// not through a fixed set of `~` pins.
//
// Wire an LED and a resistor from GPIO 4 to ground to watch it; GPIO 8, the
// DevKitM-1's own LED, fades along with it.

const uint8_t LED = 4;
const int STEPS = 64;
const unsigned long STEP_MS = 30;  // a whole breath takes about two seconds

// One cycle of (1 - cos)/2 scaled to 0..255. A linear ramp looks wrong: the
// eye is roughly logarithmic, so an even climb in duty is an uneven climb in
// brightness, and this is the shape that reads as breathing.
const uint8_t breath[STEPS] = {
    0,   1,   2,   6,  10,  16,  22,  29,
   38,  47,  57,  68,  79,  91, 103, 116,
  128, 140, 153, 165, 177, 188, 199, 209,
  218, 226, 234, 240, 246, 250, 253, 255,
  255, 255, 253, 250, 246, 240, 234, 226,
  218, 209, 199, 188, 177, 165, 153, 140,
  128, 116, 103,  91,  79,  68,  57,  47,
   38,  29,  22,  16,  10,   6,   2,   1,
};

void setup() {
  // Nothing to do: the first analogWrite attaches the pin to a free channel.
}

void loop() {
  for (int step = 0; step < STEPS; step++) {
    analogWrite(LED, breath[step]);
    analogWrite(LED_BUILTIN, breath[step]);
    delay(STEP_MS);
  }
}

Parts list

4 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

3 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Ground: ESP32-C3-DevKitM-1 pin GND; LED, yellow pin C
  • ESP32-C3-DevKitM-1 pin 4; Resistor, 220 Ω pin 1
  • Resistor, 220 Ω pin 2; LED, yellow pin A

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.