Raspberry PI Pico #3 – PWM Signale erzeugen

In diesem Beitrag möchte ich dir nun gerne zeigen wie du ein PWM Signal am Raspberry PI Pico mit Micropython erzeugst. Mit einem solchen PWM Signal kannst du im einfachsten Fall eine LED zum langsamen auf und ableuchten lassen (auch Fade Effekt genannt) oder auch kleine Servomotoren steuern. Und wie du das machst zeige ich dir im folgenden Text.

Raspberry PI Pico mit Servomotor SG90
Raspberry PI Pico mit Servomotor SG90

Was ist ein PWM Signal?

Das Kürzel PWM steht für Pulswellenmodulation und ist ein gesteuertes Rechtecksignal. Dabei wird die Spannung in einem definierbaren Zeitabstand ein und ausgeschaltet. (Dabei entsteht an einer LED ein Fade Effekt da das menschliche Auge sehr träge ist.)

Dieses Signal hat nun eine gewisse Frequenz wo es aktiv und deaktiv ist. Der Strom rechnet sich nun aus der Zeit des aktiven und deaktiven Zustands zusammen.

Raspberry PI Pico & Mini Osziloskop DSO138mini
Raspberry PI Pico & Mini Osziloskop DSO138mini

Mehr über das PWM Signal kannst du im sehr ausführlichen Wikipedia Artikel weiterlesen.

Seite „Pulsdauermodulation“. In: Wikipedia, Die freie Enzyklopädie. Bearbeitungsstand: 27. November 2020, 12:43 UTC. URL: https://de.wikipedia.org/w/index.php?title=Pulsdauermodulation&oldid=205986062 (Abgerufen: 5. Februar 2021, 15:38 UTC)

erzeugen eines PWM Signals am Pico mit MicroPython

Wie du ein PWM Signal mit MicroPython erzeugst habe ich bereits im Beitrag Programmieren mit MicroPython #2: steuern von Leuchtdioden (LED) gezeigt. Dieses funktioniert am Raspberry PI Pico sehr ähnlich.

Es gibt von der Raspberry PI Foundation einen passenden Artikel wo dir auf englisch erläutert wird, wie du eine LED steuern kannst Control LED brightness with PWM.

Für das Erzeugen des PWM Signals benötigen wir einen freien Pin sowie aus dem MicroPython Modul „machine“ die Klasse „PWM“. Und für das Erzeugen einer minimalen Pause die Klasse „sleep“ aus dem Modul „time“.

#Klasse zum ansteuern eines GPIO Pin 
from machine import Pin 

#Klasse zum erzeugen eines PWM Signals 
#an einem GPIO Pin 
from machine import PWM

#aus dem Modul "time" die Klasse sleep laden 
from time import sleep

In meinem Fall ist eine LED am GPIO 15 angeschlossen welche wir zum Faden (langsames auf und ableuchten) bringen möchten.

#GPIO welcher als PWM Pin benutzt werden soll 
pwm = PWM(Pin(15))

Das PWM Signal soll eine Frequenz von 1kHz haben.

#eine Frequenz von 1000hz also 1kHz 
pwm.freq(1000)

Der mögliche Wert für den Tastgrad zwischen zwei PWM Signalen ist 65025. Bei 0 ist die LED aus und bei dem maximalen Wert von 65025 ist diese voll erleuchtet. Also nehmen wir nun eine Schleife von 0 bis 65025 und setzen darin den Tastgrad (duty) des PWM Signals.

for duty in range(65025): 
   #setzen des Tastgrades 
   pwm.duty_u16(duty) 
   #1 Mikrosekunde Pause 
   sleep(0.0001)

Wenn diese Schleife abgearbeitet ist, wird wiederum eine Schleife vom maximalen Wert zu 0 durchlaufen.

#und das ganze Rückwärts 
for duty in range(65025, 0, -1): 
   pwm.duty_u16(duty) 
   sleep(0.0001)

Hier nun der gesamte Code zum Erzeugen eines PWM Signals mit MicroPython.

#Klasse zum ansteuern eines GPIO Pin
from machine import Pin 

#Klasse zum erzeugen eines PWM Signals
#an einem GPIO Pin
from machine import PWM

#die beiden Imports kann man auch verkürzen
#indem diese Kommasepariert aufgeführt werden
# from machine import Pin, PWM

#aus dem Modul "time" die Klasse sleep laden
from time import sleep

#GPIO welcher als PWM Pin benutzt werden soll
pwm = PWM(Pin(15))

#eine Frequenz von 1000hz also 1kHz
pwm.freq(1000)

#Endlosschleife...
while True:
    #duty == Tastgrad, definiert die Zeit zwischen jeweils
    #zwei eingeschalteten Signalen, je kleiner dieser Wert
    #umso Heller ist zbsp. eine LED
    for duty in range(65025):
        #setzen des Tastgrades
        pwm.duty_u16(duty)
        #1microsekunde Pause
        sleep(0.0001)
        
    #und das ganze Rückwärts
    for duty in range(65025, 0, -1):
        pwm.duty_u16(duty)
        sleep(0.0001)

steuern eines Servomotors per PWM Signal

Wie du einen Servomotor per  Python am Raspberry PI steuern kannst habe ich im gleichnamigen Beitrag Raspberry PI Tutorial #7: Servomotor steuern erläutert. Nachfolgend möchte ich dir nun zeigen wie das mit Micropython am Raspberry PI Pico mit dem fast gleichen Code funktioniert.

Zunächst müssen wir die korrekte Frequenz für den Servomotor setzen. Diesen Wert kannst du aus dem Datenblatt zum Servomotor ablesen. In meinem Fall verwende ich einen Servo vom Typ SG90 welcher eine Frequenz von 50Hz benötigt.

from time import sleep
from machine import Pin 
from machine import PWM

pwm = PWM(Pin(15))
pwm.freq(50)

# Funktion zum setzen eines Winkels
# als Parameter wird die Position erwartet
def setServoCycle(position):
  pwm.duty_u16(position)
  sleep(0.01)


while True:
    for pos in range(100, 8000,50):
      setServoCycle(pos)
    for pos in range(8000, 100,-50):
      setServoCycle(pos)

Der Servo SG90 kann sich um 180° bewegen. In meinem Fall bewege ich das Ruderhorn von dem Winkel 0° zum maximum 180° in Schritten von jeweils 50 und eine kleine Pause von 10 Millisekunden.

Video

3 Kommentare

  1. Sehr Interessant

    Zum Thema PWM Erzeugen mit PI PICO und MicroPython habe ich im Netz sicher 20 Beispiele gefunden.
    Jedoch: Ein PWM Signal (500us – 2500us 200Hz, zum Beispiel von einem RC Gyro) mit dem PI PICO und MicroPython Präzise und Jitterfrei zu lesen, da habe ich noch kein einziges gut Funktionierendes Beispiel gefunden.
    Könnt Ihr da nachlegen?

    1. Hallo Pascal,
      ich denke mal 200Hz Abtastrate am Raspberry PI Pico ist schon recht sportlich. Denke mal das wird schwierig.

      Gruß,
      Stefan Draeger

  2. Hallo
    sehr interessanter Beitrag:) mich würde allerdings auch interessieren, wie man ein pwm Signal als Sollwert mit z.B. einem Xbox One Controller vorgibt. Dann wäre der Pico der erste „PWM Empfänger“, der das könnte und gleichzeitig bauformtechnisch einem RC Empfänger nahe kommt.

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert