Fade an LED smoothly from off to on and back again, like breathing, instead of just switching it fully on or off. Introduces PWM (Pulse-Width Modulation) — the technique used to make a digital pin behave like an analog output.
for loopsAn analog signal is continuous in both time and value — like temperature changing smoothly throughout the day. A digital signal only ever holds discrete values (1s and 0s), and can change instantly between them. Both can be converted into the other.

Microcontroller pins can only output fully HIGH or fully LOW — they can’t output a true analog voltage. PWM fakes an analog output by switching a pin HIGH and LOW very quickly. The duty cycle is the percentage of each cycle (period) spent HIGH. A longer duty cycle behaves like a higher average voltage; a shorter one behaves like a lower voltage.

The longer the duty cycle, the higher the effective brightness of an LED driven by that pin.
On the ESP32-S3, the PWM (LEDC) controller has 8 channels, each independently configurable for frequency, duty cycle, and resolution.
for LoopsA for loop runs the code inside of it multiple times. e.g. These two code snippets produce the same output:
print(0)
print(1)
print(2)
for i in range(0, 3):
print(i)
The for loop defines a variable i and that variable will be assigned a different value before each iteration of the loop as defined by the range. In this case range is telling python the first value for i is 0, the last value is 2 and increase the value by one before it starts running the code contained in the loop.
Same components as 02_blink_external_led.md.

NOTE: If you have the circuit setup for 03 Button and LED you can leave the button connected for this project.
Disconnect all power before building the circuit. Reconnect once verified.


Connections:
File: 01_first_examples/code/BreatheLight.py
from machine import Pin,PWM
import time
pwm =PWM(Pin(2),10000)
try:
while True:
for i in range(0,1023):
pwm.duty(i)
time.sleep_ms(1)
for i in range(0,1023):
pwm.duty(1023-i)
time.sleep_ms(1)
except:
pwm.deinit()
01_first_examples/code/.BreatheLight.py.Creates a PWM object on GPIO2 with a frequency of 10,000Hz.
pwm = PWM(Pin(2), 10000)
Duty cycle ranges from 0–1023. The first loop ramps the duty cycle up (0% → 100% brightness); the second ramps it back down (100% → 0%).
for i in range(0, 1023):
pwm.duty(i) # increase brightness
time.sleep_ms(1)
for i in range(0, 1023):
pwm.duty(1023 - i) # decrease brightness
time.sleep_ms(1)
Using PWM turns on a hardware timer behind the scenes. deinit() turns that timer off — skipping it can cause PWM to fail on the next run.
except:
pwm.deinit()
pwm.duty(value): sets the duty cyclepwm.deinit(): releases the hardware timer used by PWM — always call this when doneAdapted from Python_Tutorial.pdf Project 4.1