SoftPWM - PWM für viele Arduino-Pins

PWM (Pulsweitenmodulation) wird beim Arduino beispielsweise als Möglichkeit zum Dimmen von LEDs oder zum Ansteuern von Servo-Motoren verwendet. Allerdings ist die Anzahl der Pin, die für PWM verwendet werden können, beschränkt:

Board PWM-fähige Pins PWM-Frequenz
Arduino Uno/Nano/Mini 3, 5, 6, 9, 10, 11 490 Hz (pins 5 + 6: 980 Hz)
Arduino Mega 2 - 13, 44 - 46 490 Hz (pins 4 + 13: 980 Hz)
Arduino Leonardo/Micro/Yún 3, 5, 6, 9, 10, 11, 13 490 Hz (pins 3 + 11: 980 Hz)
Arduino board
Abb.: Arduino board (Quelle: Seven_au auf Pixabay)

Es gibt jedoch Möglichkeiten diese Einschränkung zu erweitern, z.B. mit der Library bhagman/SoftPWM, die alle verfügbaren Pins des Arduino in PWM-fähige Ausgänge verwandelt. Diese Library wurde ursprünglich zum Dimmen von LEDs geschrieben, kann aber wohl auch auf andere Aufgaben angewendet bzw. umgeschrieben werden.

Verwendete Bauteile

Funktionsweise von SoftPWM

Um PWM auf einem beliebigen Pin des Arduino zu ermöglichen, verwendet die Library SoftPWM einen Hardware-Timer (Timer 2 auf AVR-Systemen bzw. IntervalTimer auf Teensy 3.x).
Es können allerdings nur maximal 20 PWM-Kanäle gleichzeitig erstellt werden, wobei die Wahl der Pins völlig frei ist. Zusätzliche Features der Library sind separate Dimmzeiten für ON und OFF, sowie ein echtes Ausschalten beim Modus OFF.

Ex I.: Dimmen einer einelnen LED

Zuächst wird SoftPWM initialisiert und mit einem Pin (hier 13) als PWM eingerichtet. Dann wird die Dimmzeit gesetzt (hier 1s = 1000ms). Sobald im loop() ein Wert (=Tastrate/Duty cycle) für den Pin mit SoftPWMSetPercent gesetzt wird, fängt die angeschlossene LED an, sich zu dimmen.
Wichtig bei der Verwendung von SoftPWMSetPercent bzw. SoftPWMSet ist, dass sie den weiteren Verlauf des Sketches nicht blockiert. Im folgenden Sketch wird allerdings der Einfachheit halber ein delay()-Aufruf zum Warten verwendet.

#include <SoftPWM.h>

#define PIN_LED    13
#define FADE_DELAY 1000 // in ms

void setup()
{
    SoftPWMBegin();
    SoftPWMSet(PIN_LED, 0); // init LED and turn it off
    SoftPWMSetFadeTime(PIN_LED, FADE_DELAY, FADE_DELAY);
}

void loop()
{
    static byte setValue = 0;
    setValue += 100;
    setValue %= 200;
    SoftPWMSetPercent(PIN_LED, setValue);
    delay(FADE_DELAY);
}

Ex. II: Gleichzeitiges Dimmen mehrerer LEDs

In diesem Beispiel werden zwei LEDs abwechselnd gedimmt, wobei hierbei eine nicht-blockierende Methode des Wartens zwischen den Sequenzen verwendet wird.

#include <SoftPWM.h>

#define PIN_LED_1    12
#define PIN_LED_2    13
#define FADE_DELAY 1000 // in ms

void setup()
{
    SoftPWMBegin();
    SoftPWMSet(PIN_LED_1, 0);
    SoftPWMSet(PIN_LED_2, 0);
    SoftPWMSetFadeTime(PIN_LED_1, FADE_DELAY, FADE_DELAY);
    SoftPWMSetFadeTime(PIN_LED_2, FADE_DELAY, FADE_DELAY);
}

void loop()
{
    static long nextAction = (long)millis() + FADE_DELAY;
    static byte setValue = 0;

    if ((long)millis() - nextAction >= 0) {
        nextAction = (long)millis() + FADE_DELAY;
        setValue += 100;
        setValue %= 200;
        SoftPWMSetPercent(PIN_LED_1, setValue);
        SoftPWMSetPercent(PIN_LED_2, (setValue+100)%200);
    }
}
Video: Gleichzeitiges Dimmen mehrerer LEDs mit der SoftPWM-Library (850 kB).
zurück