Aus Raspberry Pi Geek 04/2020

Grundlagen der Pulsweitenmodulation (Seite 2)

Das Reservieren eines PWM-Kanals erfolgt über die Datei export. Schreibt man mit Root-Rechten versehen in diese Datei eine 0, erscheint das neue Verzeichnis pwm0/, das unter anderem die Dateien capture, duty_cycle, enable, period und polarity beherbergt. Über diese Dateien lässt sich die Pulsweitenmodulation am konfigurierten Ausgang (GPIO 12 oder GPIO 18) in Betrieb nehmen.

Dazu schreiben Sie die Periodendauer (Kehrwert der Frequenz) in die Datei period und die Impulsdauer respektive Pulsweite – beides angegeben in Nanosekunden – in die Datei duty_cycle. Um etwa für ein Blinklicht einen Impuls mit einer halben Sekunde Länge zu erzeugen, der jede Sekunde einmal auftritt, müssen Sie in period den Wert 1 000 000 000 und in duty_cycle 500 000 000 ablegen. Das Schreiben einer 1 in die Datei enable aktiviert anschließend die PWM (Listing 1). Um sie wieder abzuschalten, schreiben Sie eine 0 in die Datei enable.

Listing 1

pi@raspberrypi:~ $ sudo su
root@raspberrypi:/home/pi# cd /sys/class/pwm/pwmchip0/
root@raspberrypi:/sys/class/pwm/pwmchip0/# echo 0 > export
root@raspberrypi:/sys/class/pwm/pwmchip0/# cd pwm0
root@raspberrypi:/sys/class/pwm/pwmchip0/pwm0# echo 500000000 > period
root@raspberrypi:/sys/class/pwm/pwmchip0/pwm0# echo 250000000 > duty_cycle
root@raspberrypi:/sys/class/pwm/pwmchip0/pwm0# echo 1 > enable

Namensirritation

Bei der Konfiguration der Perioden- und der Impulsdauer überprüft der Linux-Kernel die Sinnhaftigkeit der Daten. Er lehnt eine Impulsdauer, die länger als die Periodendauer ausfällt, ebenso ab wie eine Periodendauer, die kürzer ist als die Impulsdauer. Konsequenz: Erst schreibt man die Periodendauer (period), anschließend die Impulsdauer (duty_cycle).

Den Namen der Datei duty_cycle haben die Linux-Macher unglücklich gewählt, bedeutet duty cycle in der Fachsprache doch Tastgrad, was gemäß Norm eine dimensionslose Verhältniszahl von Pulsweite zu Periodendauer darstellt. Um also bei gegebenem Tastgrad die Pulsweite zu berechnen, wird der zwischen Null und Eins, also zwischen 0 und 100 Prozent liegende Tastgrad mit der Periodendauer multipliziert. In unserem Blinklicht-Beispiel ergibt sich damit ein Tastgrad respektive duty cycle von 50 Prozent.

Darüber hinaus kann man anstelle der Impulsdauer (Pulsweite) die Zeitdauer innerhalb der Periodendauer angeben, in der kein Impuls ausgegeben wird. Dazu trägt man in die Datei polarity den Wert inversed ein. Jetzt interpretiert der Kernel den Inhalt von duty_cycle als die Zeit ohne Impuls. Ein normal in derselben Datei schaltet wieder alles zurück auf die ursprüngliche Interpretation. Abbildung 4 zeigt die Ausgänge der beiden PWM-Kanäle des Raspberry Pi, wenn Sie einen Kanal normal und den anderen mit denselben Parametern invertiert betreiben. Die Periodendauer ist ebenso wie die Impulsdauer sehr deutlich zu erkennen.

Abbildung 4: Ein normales und ein invertiertes PWM-Signal auf dem Logic-Analyzer.

Abbildung 4: Ein normales und ein invertiertes PWM-Signal auf dem Logic-Analyzer.

Nur in den seltensten Fällen aktiviert man die PWM nach dem Muster aus Listing 1 über die Konsole. Da die Konfiguration in Unix-Manier über Dateizugriffe erfolgt, fällt eine Umsetzung beispielsweise in C-Code leicht, wie Listing 2 zeigt. Der Funktion write_pwm_config() übergibt man als Parameter den Namen der zu ändernden Konfigurationsdatei sowie den zu schreibenden Wert. Insbesondere die Datei export wird in einer realen Applikation nur einmal geschrieben, während man die Pulsweite oder auch die Periodendauer häufiger verändert, um beispielsweise einen Motor langsam anzufahren.

Listing 2

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
static int write_pwm_config( char *fname, char *value )
{
  int fd_pwm, ret, length;
  char fpath[128];
  if (fname==NULL || value==NULL) {
    return -1;
  }
  snprintf( fpath, sizeof(fpath), "/sys/class/pwm/pwmchip0/%s", fname);
  length = strlen( fpath );
  if (length >= sizeof(fpath)) {
    fprintf( stderr, "path %s too long\n", fname);
    return -1;
  }
  fd_pwm = open( fpath, O_WRONLY );
  if (fd_pwm<0) {
    perror( fpath );
    return -1;
  }
  ret = write(fd_pwm, value, strlen(value));
  if (ret<0) {
    perror( value );
    close( fd_pwm );
    return -2;
  }
  close( fd_pwm );
  return 0;
}
int main( int argc, char **argv )
{
  int ret;
  ret = write_pwm_config("export","0");
  if (ret) return ret;
  ret = write_pwm_config("pwm0/period", "500000000");
  if (ret) return ret;
  ret = write_pwm_config("pwm0/duty_cycle", "400000000");
  if (ret) return ret;
  ret = write_pwm_config("pwm0/enable", "1");
  if (ret) return ret;
  return 0;
}

Sicherheit geht vor

Um aus dem Quellcode pwm.c das ausführbare Programm pwm zu generieren, genügt der Aufruf make pwm im Verzeichnis mit dem Quellcode. Da die Konfiguration der PWM normalerweise Superuser-Rechte erfordert, passen Sie dazu die Zugriffsrechte der Konfigurationsdateien im Sys-Filesystem an.

Sie ändert die Besitzverhältnisse der zugehörigen Verzeichnisse und Konfigurationsdateien derart, dass sie der Gruppe gpio gehören. Um die Änderungen über Boot-Vorgänge hinweg persistent zu machen, ergänzen Sie dazu als Superuser auf dem Raspberry Pi die Datei /etc/udev/rules.d/99-com.rules um den Eintrag aus Listing 3.

Listing 3

SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm; chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip*  && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*'"

Nach einem Reboot greifen diese Änderungen und ermöglichen den Zugriff für alle Benutzer, die der Gruppe gpio angehören. Der Default-Benutzer pi gehört bereits zum Club; die Login-Namen anderer User hängen Sie gegebenenfalls in der Datei /etc/group an die Zeile an, die mit gpio beginnt. Jetzt startet das Programm pwm ohne Root-Rechte.

Die hardwaregesteuerte Pulsweitenmodulation lässt sich erwartungsgemäß auch direkt innerhalb des Kernels konfigurieren und nutzen, also in Gerätetreibern. Pfiffige Treiberprogrammierer realisieren zusätzliche hardwaregesteuerte PWM-Kanäle, indem sie noch DMA (Direct Memory Access) mit den beiden vorhandenen PWM-Kanälen kombinieren. Damit lassen sich dann beispielsweise alle vier Rotoren eines Quadrocopters unabhängig voneinander ansteuern. Doch das ist eher ein Thema für Spezialisten als für Anwender. (jlu)

Die Autoren

Eva-Katharina Kunst ist seit den Anfängen von Linux ein Fan von Open Source. Jürgen Quade lehrt als Professor an der Hochschule Niederrhein und führt auch für Unternehmen Schulungen zu den Themen Treiberprogrammierung und Embedded Linux durch.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben