Pi Pico PWM mit Totzeit

OP #8099855
Lesenswert?
• ▲
▼

Hat jemand mit dem Pico2 (RP2350) schon mal eine saubere PWM mit zwei Ausgängen für low- und high- Side mit Totzeit erzeugen können?

Bei Taktraten um 200kHz, Modulationssignal wenige Kiloherz.

Hatte gehofft, mit der PIO- Programmierung ginge das. Eine sichere Totzeit für die Halbbrücke bekomme ich hin, aber es gibt immer wieder kleine Ausreißer in den Pulsbreiten. Woher? Keine Ahnung, vielleicht läuft der Fifo zur PIO leer, der wird per Interrupt nachgefüttert.

Wie auch immer, ist der erste Versuch mit der PIO. Vielleicht mag jemand was lauffähiges teilen, wäre nett.

Ansonsten probiere ich die Hardware-PWM und muss die Totzeit extern erzeugen.

#8099858
Lesenswert?
• ▲
▼

Das geht sowohl mit PWM als auch mit PIO völlig problemlos. Wichtig ist, dass man die Systeme und (Vor)Teiler vorher sauber zurücksetzt und dann synchron startet.

Für PWM ist für den synchronen Start das Register PWM_BASE+EN zuständig. (Seite 1088)

Für PIO ist für den synchronen Start das Register PIO[012]_BASE+CTRL zuständig. (Seite 939)

#8099868
Lesenswert?
• ▲
▼

Wulf D. schrieb:

vielleicht läuft der Fifo zur PIO leer, der wird per Interrupt nachgefüttert.

Eines noch, wenn die StateMachine nur Daten von der Applikation empfängt, kann man die FIFO Tiefe verdoppeln. Des Weiteren sollte man bei einigen hundert kHz vielleicht Abstand von Interrupts nehmen (oder die Prioritäten im NVIC anpassen). Ein Nachfüllen der FIFOs kann man ohne Prozessorlast lieber mit einer in einer Schleife laufenden DMA machen. Gerade der 2350 hat diesbezüglich einiges an Funktionalität dazu gelegt, obschon es auch bequemstens mit 'nem 2040 ginge.

: Bearbeitet durch User
OP #8099871
Lesenswert?
• ▲
▼

Die mit der PIO nachgestellte PWM startet sauber und läuft auch durch. Nur ab- und zu entsteht entweder auf der High-Side oder der Low-Side ein längerer Puls, der sich natürlich negativ auf das Ausgangssignal auswirkt.

Anbei ein Bild was ich meine:

  • gelb: low side
  • türkis: high side
  • lila: (gefiltertes) Ausgangssignal.

Rot reingemalt der fehlerhafte Puls und gestrichelt das korrekte Ausgangssignal.

Der Fehler tritt ca alle 20-30 Pulse auf, nicht vorhersagbar. Könnte mit der Befüllung des PIO-Fifo zu tun haben.

Vielleicht führt das zur Lösung: kann man das Fifo so steuern, dass immer genügend Daten für die PIO vorhanden sind und nichts leerlaufen kann. Sorry, ist mein erster Versuch mit Fifo und PIO.

Der PIO-Code

1
; GPIO2 = Low-Side, GPIO3 = High-Side
2
; Systemtakt: 150 MHz
3

4
.wrap_target
5
    ; --- HIGH-SIDE Phase ---
6
    pull block          ; High-Side-Dauer aus FIFO holen
7
    mov x, osr          ; Verschiebe in das X-Register
8
    jmp !x skip_high    ; Wenn 0, ueberspringe
9
    set pins, 2         ; High-Side AN (GPIO3 = 1), Low-Side AUS (GPIO2 = 0)
10
high_loop:
11
    jmp x-- high_loop   ; High-Zeit runterzaehlen
12

13
skip_high:
14
    set pins, 0         ; Beide AUS -> Totzeit (~40ns)
15
    nop                 ; nops fuer Totzeit
16
    nop                 ; 
17
    nop
18
    nop
19

20
    ; --- LOW-SIDE Phase ---
21
    pull block          ; Low-Side-Dauer aus FIFO
22
    mov x, osr          ; Verschiebe in das X-Register
23
    jmp !x skip_low     ; Wenn 0, ueberspringe
24
    set pins, 1         ; Low-Side AN (GPIO2 = 1), High-Side AUS (GPIO3 = 0)
25
low_loop:
26
    jmp x-- low_loop    ; Zähle Low-Zeit runter
27

28
skip_low:
29
    set pins, 0         ; Beide AUS -> Totzeit vor dem nächsten Puls
30
    nop
31
    nop 
32
    irq 0               ; PIO-IRQ => neue Daten 
33
.wrap
Angehängte Dateien:
#8099873
Lesenswert?
• ▲
▼

Ja klar. Zwei unabhängige ›PULL‹ mit ›BLOCK‹.

Wenn da mit dem Nachfüllen etwas zeitlich schief geht, manifestiert sich das Problem sofort. Das ist das Problem mit IRQs, wenn noch andere Mitspieler (zB. USB) im System sind.

Also NVIC massieren und diesem PIO-IRQ die höchste Prio verpassen, oder besser: DMA mit Buffergröße 8Bytes (2WORDS) im DMA-Loop laufen lassen. Dann muss man sich gar nicht mehr kümmern.

#8099874
Lesenswert?
• ▲
▼

Ach ja, mit dem 2350 kann man den FIFO indexieren und als Ablageplatz für Variablen benutzen. SO muss man diesen nicht ständig mit den gleichen Werten befüllen. Nur wenn sich etwas ändert.

Zweite Möglichkeit: Zwei korrespondierende StateMachine teilen sich die Aufgabe in einer Art Ping-Pong Spiel. Eine bekommt den HI-Teil, eine den LO-Teil. Die kann man dann so programmieren, dass sie sich einen neuen Zählwert ins OSR (NOBLOCK) laden. Und wenn nichts in der FIFO ist, wird der (alte) X-Wert übernommen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren