Arduino Uno · PWM

Fade In / Fade Out på ekstern LED (PWM)

Forstå PWM (Pulse-Width Modulation) og lav et lækkert, periodisk fade på en ekstern LED via en PWM-pin.

Det skal du bruge

  • Arduino Uno (klon er fint) + USB-kabel.
  • Breadboard-shield eller lille breadboard + jumperledninger.
  • 1 × LED (5 mm) + 220–330 Ω seriemodstand.
PWM-pins på Uno
Brug en pin med ~ på printet: ~3~5~6~9~10~11.

Teori: Hvad er PWM?

  • Arduino kan ikke lave “rigtig” analog spænding – i stedet “pulser” den hurtigt mellem 0 V og 5 V.
  • Duty cycle (% tændt i hver periode) styrer den gennemsnitlige effekt → LED opleves som lysere/mørkere.
  • analogWrite(pin, værdi) bruger 8-bit: 0 = altid slukket, 255 = altid tændt.
  • PWM-frekvens: ca. ~490 Hz på de fleste PWM-pins (5 & 6 ~980 Hz). Det er fint til LED-dimming.
// Eksempel: 50% duty cycle
analogWrite(9, 128); // ~ halv lysstyrke på pin ~9

Forbindelser (LED på D9)

Vi bruger D9 som PWM-udgang.

D9 ──[ 220Ω ]──►|── GND

Modstanden kan sidde på begge sider af LED’en (i serie). LED’ens lange ben = anode (mod D9).

Vigtigt
Styr aldrig en LED direkte fra 5V uden modstand – den kan brænde af.

Program 1 · Simpelt Fade In/Out (med delay())

Let at forstå. Fin til demo – men “blokerer” CPU’en mens den venter.

const int LED_PIN = 9;      // PWM-pin (~)
const int STEP    = 5;      // ændring pr. trin (1-10 er fint)
const int PAUSE   = 20;     // ms mellem trin (mindre = hurtigere)

void setup(){
  pinMode(LED_PIN, OUTPUT);
}

void loop(){
  // Fade ind (0 -> 255)
  for(int v=0; v <= 255; v += STEP){
    analogWrite(LED_PIN, v);
    delay(PAUSE);
  }
  // Fade ud (255 -> 0)
  for(int v=255; v >= 0; v -= STEP){
    analogWrite(LED_PIN, v);
    delay(PAUSE);
  }
}
Tempo & glathed
Mindsk STEP og/eller PAUSE for glattere fade. Større værdier = hurtigere men grovere trin.

Program 2 · “Breathing” uden blokering (med millis())

CPU’en holdes fri for andre opgaver (knapper, sensorer). Vi bruger en blød kurve (ease-in-out) for mere naturligt lys.

const int LED_PIN = 9;       // PWM-pin (~)
const unsigned long PERIOD_MS = 3000; // én fuld cyklus (ind+ud) = 3 s
const int MAX_PWM = 255;

// Kvadratisk ease-in-out i [0..1] -> [0..1]
float easeInOutQuad(float t){
  return t < 0.5 ? 2.0f*t*t : 1.0f - pow(-2.0f*t + 2.0f, 2.0f)/2.0f;
}

void setup(){
  pinMode(LED_PIN, OUTPUT);
}

void loop(){
  unsigned long now = millis();
  // faser: 0..1 over PERIOD_MS (gentages)
  float phase = (now % PERIOD_MS) / (float)PERIOD_MS; // 0..1
  // gør det til trekant (0->1->0)
  float tri = phase < 0.5 ? (phase*2.0f) : (2.0f - phase*2.0f);
  // anvend easing for glatter perception
  float eased = easeInOutQuad(tri);
  int pwm = (int)(eased * MAX_PWM + 0.5f);
  analogWrite(LED_PIN, pwm);
}
Perceptuel jævnhed
Øjet er logaritmisk – lineære PWM-trin føles ikke helt jævne. Easing (eller gamma-korrektion) giver flottere “åndedræt”.

Bonus · Sinus og let “gamma”

En enkel sinus kan også give elegant breathing. Her er et letvægtsbud uden sin(), men du kan bruge sin() hvis pladsen tillader.

const int LED_PIN = 9;
const unsigned long PERIOD_MS = 3000;

float fastSine01(float x){ // x i [0..1] -> approx. sinus i [0..1]
  // Parabolsk bue som stand-in for sinus
  float t = (x < 0.5f) ? (2.0f*x) : (2.0f - 2.0f*x); // trekant 0..1..0
  // simple gamma-ish (hæver kontrast)
  float y = t*t*(3 - 2*t); // smoothstep
  return y;
}

void setup(){ pinMode(LED_PIN, OUTPUT); }

void loop(){
  float phase = (millis() % PERIOD_MS) / (float)PERIOD_MS;
  int pwm = (int)(fastSine01(phase) * 255 + 0.5f);
  analogWrite(LED_PIN, pwm);
}
Flere LEDs?
Sæt én modstand pr. LED, og én PWM-pin pr. kanal. For RGB-LED (fælles katode/anode) skal du tjekke polaritet og evt. invertere logik.

Fejlfinding

  • Ingen fade: Brug en PWM-pin (med ~). Tjek at LED er i serie med 220–330 Ω.
  • Meget svag lys: For stor modstand (1 kΩ virker, men dæmper). Prøv 220–330 Ω.
  • Flicker i kamera: Det er normalt pga. PWM-frekvens vs. kamera-shutter. Øjet ser det sjældent.
  • Behov for hurtigere/kortere åndedræt: Justér PERIOD_MS.
  • Vil lave andre ting samtidig: Brug den ikke-blokerende version (Program 2).

Næste skridt

  • Styr fade-tempo med en potentiometer (analogRead) → mappes til PERIOD_MS eller lysstyrke.
  • Lav en “lysanimation” på flere PWM-pins (9/10/11) – fx bølge der flytter sig.
  • Kombinér med trykknap: tryk for at skifte mellem faste niveauer og breathing-mode.