PWM-Ausgabe stimmt nicht bei AVR DDS

Gast #4704909
Lesenswert?

Hallo zusammen,

habe dieses Projekt hier (AVR DDS Signal Generator V2.0)
https://github.com/dev26th/avr_dds_20/blob/master/README.md
auch nachgebaut.

Mir ist dann aufgefallen, dass etwas mit der PWM-Ausgabe nicht stimmt.

Und zwar ist es so, dass bei besonders kleinen und besonders großen 
Tastverhältnissen die Flanken springen. Man kann es mit dem Oszilloskop 
beobachten und man sieht, dass eine angeschlossene LED parallel dazu 
flackert.

Da ansonsten alles sauber funktioniert, vermute ich, dass es ein 
Software-Bug ist.

Den C-Code habe ich in den Anhang getan (main.c).

Vielleicht kann man der Sache hier gemeinsam auf den Grund gehen.


Es geht in jedem Fall um die PWM-Ausgabe, nicht um die PWM-HS-Ausgabe 
(die liegt an einem anderen Pin).
Angehängte Dateien:
Gast #4704926
Lesenswert?

Hier der Code-Bereich, in dem ich den Fehler vermute:
1
C
2
void pwm_displayDuty(void) {
3
  LCDGotoXY(10, 0);
4
  printf("%5.1f%%", ((double)config.pwmDuty+1) / 256 * 100);
5
}
6

7
void pwm_updateDisplay(void) {
8
  signal_updateDisplay();
9
  pwm_displayDuty();
10
}
11

12
void pwn_prepareBuffer(void) {
13
  for(uint8_t i = 0; ; ++i) {
14
    signalBuffer[i] = (i <= config.pwmDuty) ? 255 : 0;
15
    if(i == 255) break;
16
  }
17
}
18

19
void pwm_run(void) {
20
  while(running) {
21
    pwn_prepareBuffer();
22
    signal_continue(true);
23
  }
24
}
25

26
void pwm_onStart(void) {
27
  if(!running) {
28
    signal_start();
29
    pwm_run();
30
    signal_stop();
31
  }
32
  else {
33
    running = false;
34
  }
35
}
36

37
void pwm_onUp(void) {
38
  if(!running) {
39
    menu_onUp();
40
  }
41
  else {
42
    if(config.pwmDuty < 255) ++config.pwmDuty;
43
    pwm_updateDisplay();
44
  }
45
}
46

47
void pwm_onDown(void) {
48
  if(!running) {
49
    menu_onDown();
50
  }
51
  else {
52
    if(config.pwmDuty > 0) --config.pwmDuty;
53
    pwm_updateDisplay();
54
  }
55
}
56
Code
Gast #4706138
Lesenswert?

Alex schrieb:
> Man sieht deutlich die Lücken und die unterschiedlich hohe Amplitude der
> PWM-Pulse.

Wieso erwartest du bei einer Abtastrate von 1 MSa/s ein vernünftiges 
Bild deines PWM-Signals, wenn der Takt zur Erzeugung eines 0.4% Pulses 
mit 11kHz schon bei deutlich über 2MHz liegen muss?
Gast #4706141
Lesenswert?

Rein gefühlsmäßig vermute ich folgendes:

a) Es wurde vergessen, bei der PWM-Ausgabe einen störenden Interrupt zu 
deaktivieren.

b) Das Orginal-Projekt läuft auf einem Atmega16. Der Autor für den oben 
angegebenen Code verwendet einen neueren (oder anderen) Atmega (im 
Schaltplan gibt er Mega16-P an - ich selber benutze einen Mega16-PU).


Könnte eins von beidem zu dem Fehlerbild passen?



--------------------------------------------------------------

spess53 schrieb:
> Ich sehe nur eine Reihe von Messfehlern.

An Messfehler hatte ich auch zuerst gedacht. Dann habe ich eine LED über 
einen Widerstand parallel zum Ausgang angeschlossen und die LED flackert 
nun gut sichtbar im Takt der "Messfehler".

Werde gleich noch mit einem Frequenzmesser gegentesten.

(Oszi ist ein 20MHz-China-USB-Teil - könnte auch noch mal mit einem 
Analogoszi gegenprüfen, aber wegen der ebenfalls flackernden LED tippe 
ich sehr darauf, dass das Problem ein Software-Bug ist)
Gast #4706152
Lesenswert?

Alex schrieb:
> An Messfehler hatte ich auch zuerst gedacht.

Alleine die Tatsache, dass bei einem (digitalen) PWM-Signal negative 
Spitzen auftreten, spricht zumindest für einen falsch abgeglichenen 
Tastkopf. Guck dir mal bei einer angemessenen Abtastrate die Einzelpulse 
an.
Gast #4706178
Lesenswert?

Wolfgang schrieb:
>> Man sieht deutlich die Lücken und die unterschiedlich hohe Amplitude der
>> PWM-Pulse.
>
> Wieso erwartest du bei einer Abtastrate von 1 MSa/s ein vernünftiges
> Bild deines PWM-Signals, wenn der Takt zur Erzeugung eines 0.4% Pulses
> mit 11kHz schon bei deutlich über 2MHz liegen muss?

Da hast du recht, Danke für den Hinweis!

An den Lücken ändert sich aber auch bei höherer Abrastrate nichts (z.B. 
8 MSa/s).
Und wie gesagt "wandern" die Lücken beim Messen über den Bildschirm und 
eine parallel geschaltete LED flackert im Takt der Wanderbewegungen der 
Lücken.
Gast #4706185
Lesenswert?

Der Frequenzzähler (Reziprokzähler bis 80MHz mit 
Schmitt-Trigger-Eingang) zählt ab einem Tastverhältnis von >= 0,8% die 
korrekte Frequenz aus.
Bei einem TV von 0,4% zeigt er genau 2/3 der Frequenz an. Hm.


Im Anhang noch der Messaufbau (Oszi-Anschluss unten mitte/rechts).
Angehängte Dateien:
Gast #4706190
Lesenswert?

Alex schrieb:
> Und wie gesagt "wandern" die Lücken beim Messen über den Bildschirm und
> eine parallel geschaltete LED flackert im Takt der Wanderbewegungen der
> Lücken.

Zwischenzeitlich hatte ich zwischen Ausgang und LED (mit Rv) ein 
Bustreiber-IC zwischengeschaltet, weil ich dachte, die LED belastet 
vielleicht den Ausgang zu stark. Das Flackern blieb aber nach wie vor 
bestehen.
Gast #4706201
Lesenswert?

Wolfgang schrieb:
> Alleine die Tatsache, dass bei einem (digitalen) PWM-Signal negative
> Spitzen auftreten, spricht zumindest für einen falsch abgeglichenen
> Tastkopf.

Die Tastköpfe sind perfekt abgeglichen, grade noch mal getestet.

Wenn ich den Tastkopf direkt an Messpunkt 1 anschließe (s. Schaltplan 
oben), bleiben die negativen Überschwinger aus.
Gast #4706250
Lesenswert?

Wolfgang schrieb:
> Mit PWM hat dieser Puls ja nicht viel zu tun.

Ja, merkwürdig, fast so, als wäre irgendwo eine parasitäre Kapazität.


> Guck doch mal, die Signale direkt an den Digitalausgängen vorm DAC z.B.
> mit einem LA an.

Die Sache ist ganz einfach, im PWM-Modus gehen alle Pins (also PA0 bis 
PA7) gleichzeitig auf hi oder lo.

Im Anhang direkt an PA0 gemessen. In der Realität springt der Peak hin 
und her (auf dem Bild natürlich nicht erkennbar).
Angehängte Dateien:
Gast #4706265
Lesenswert?

Alex schrieb:
> In der Realität springt der Peak hin
> und her (auf dem Bild natürlich nicht erkennbar).

Bezogen auf was spring der hin- und her. Wenn du auf den vorhergehenden 
triggerst, muss er (halbwegs) stehen.

Dann kannst du dir auch den Jitter angucken, indem du den Mittelwert 
über vieles Triggerereignisse anguckst.
Gast #4706281
Lesenswert?

Wolfgang schrieb:
> Bezogen auf was spring der hin- und her.

Das Signal entsteht bei TV von 0,4% immer an einer der drei rot 
markierten Stellen (auf mehr oder weniger chaotische Art und Weise).

Wenn man das Tastverhältnis von 0,4% auf 0,8% hochstellt, ist jeweils 
über jeder roten Markierung ein Signal zu sehen (stabil ohne Springen 
und Wechseln).
Gast #4706306
Lesenswert?

Jörg schrieb:
> Wird bei der Schaltung die PWM nicht am Anschluss HS ausgegeben?

Nein, die HS-Signale werden an Pin 19 ausgegeben. Es gibt auch HS-PWM, 
von dem ist hier aber nicht die Rede. Hier geht es um die normale 
PWM-Ausgabe, die über das R2R-Netzwerk an Port A ausgegeben wird.

Aber auf jeden Fall Danke fürs Mitüberlegen!!!



(HS-PWM kann nur ein paar fest vorgegebene Frequenzen über OC1A 
ausgeben)
Gast #4706309
Lesenswert?

Alex schrieb:
> Da hast du recht, Danke für den Hinweis!
>
> An den Lücken ändert sich aber auch bei höherer Abrastrate nichts (z.B.
> 8 MSa/s).

Wie änderst du denn in dem Programm die Abtastrate?

Ich denke du hast da noch etwas überhaupt nicht
verstanden .....
Gast #4706327
Lesenswert?

PWM Frequenz: 11 KHz
Tastgrad: 1/256 %
PWM-Auflösung: 8 Bit

Updatezeit: ~364 ns entspicht 7 Zyklen, Rest 14 ns

Die Frage ist, ob der µC das auflösen kann? Das Programm habe ich mir 
jetzt nicht näher angesehen, da es einfach nicht gut genug kommentiert 
ist.
Gast #4706354
Lesenswert?

Alex schrieb:
> Das Signal entsteht bei TV von 0,4% immer an einer der drei rot
> markierten Stellen (auf mehr oder weniger chaotische Art und Weise).

Dann guck doch mal im Simulator, warum das passiert. Der Zyklenzähler 
oder die Stop-Uhr verrät dir, wo du zeitlich liegst.
Gast #4706409
Lesenswert?

Wolfgang schrieb:
> Alex schrieb:
>> Das Signal entsteht bei TV von 0,4% immer an einer der drei rot
>> markierten Stellen (auf mehr oder weniger chaotische Art und Weise).
>
> Dann guck doch mal im Simulator, warum das passiert. Der Zyklenzähler
> oder die Stop-Uhr verrät dir, wo du zeitlich liegst.

Mit Simulator meinst du eine Simulation im AVR-Studio? Bin da nicht so 
bewandert, habe es aber immerhin installiert.
Gast #4706412
Lesenswert?

Walter schrieb:
> PWM Frequenz: 11 KHz
> Tastgrad: 1/256 %
> PWM-Auflösung: 8 Bit
>
> Updatezeit: ~364 ns entspicht 7 Zyklen, Rest 14 ns
>
> Die Frage ist, ob der µC das auflösen kann? Das Programm habe ich mir
> jetzt nicht näher angesehen, da es einfach nicht gut genug kommentiert
> ist.

Ok, wenn der Atmega das gar nicht schaffen kann, ist die weitere 
Fehlersuche wohl sinnlos.

Aber vielleicht gibt es ja bestimmte Frequenzen, bei denen es exakt 
hinkommt. Das wäre ja schon mal was, wenn man die kennen würde :O)
Gast #4706422
Lesenswert?

Alex schrieb:
> Mir ist dann aufgefallen, dass etwas mit der PWM-Ausgabe nicht stimmt.

Das angegebene Sourcen-Gefüge ist nicht auf Anhieb fehlerfrei
compilierbar.

Wenn man dann die kleinen Ungereimtheiten ausmerzt entsteht
ein Code der nicht in den angegebenen ATMega16 hineinpasst.

---------------------------------------
AVR Memory Usage
----------------
Device: atmega16

Program:   21028 bytes (128.3% Full)
(.text + .data + .bootloader)

Data:        763 bytes (74.5% Full)
(.data + .bss + .noinit)
---------------------------------------

wie funktioniert das bei dir?
Gast #4706452
Lesenswert?

> Ok, wenn der Atmega das gar nicht schaffen kann, ist die weitere
> Fehlersuche wohl sinnlos.

So schnell sollte man nicht aufgeben.

---

Die schnellste Routine auf dem µCNet stammt von Werner:

Beitrag "Re: DDS Sinus erzeugung"
1
  add    r28,r24
2
LOOP1:
3
  adc    r29,r25    ; 1
4
  adc    r30,r26    ; 1
5
  lp                ; 2
6
  out    PORTB,r0   ; 1    UpDate
7
  add    r28,r24    ; 1
8
  adc    r29,r25    ; 1
9
  adc    r30,r26    ; 1
10
  add    r28,r24    ; 1
11
  lp                ; 2
12
  out    PORTB,r0   ; 1    UpDate
13
  rjmp   LOOP1      ; 2 => 14/2 = 7 cycles


Wenn du die Ausgabe so machst wie Werner (unbedingt den ganzen Thread 
lese, der sehr interessant ist), dann hast du bei einer Taktfrequenz der 
CPU von 20 MHz und eine PWM-Auflösung von 8 Bit eine max. Frequenz von 
rund 11160,7 Hz. Gehst du mit der Frequenz höher, dann verringert sich 
die Auflösung der PWM.
Gast #4706740
Lesenswert?

Hallo Leute, vielen herzlichen Dank für das Interesse und das 
Ausprobieren etc.

Codelesa schrieb:
> Das angegebene Sourcen-Gefüge ist nicht auf Anhieb fehlerfrei
> compilierbar.
>
> Wenn man dann die kleinen Ungereimtheiten ausmerzt entsteht
> ein Code der nicht in den angegebenen ATMega16 hineinpasst.
>
> ---------------------------------------
> AVR Memory Usage
> ----------------
> Device: atmega16
>
> Program:   21028 bytes (128.3% Full)
> (.text + .data + .bootloader)
>
> Data:        763 bytes (74.5% Full)
> (.data + .bss + .noinit)
> ---------------------------------------
>
> wie funktioniert das bei dir?

Ich habe einfach die fertige main.hex von hier
https://github.com/dev26th/avr_dds_20
auf den Atmega16 geflasht (siehe Anhang).

Interessant, dass das Compilieren vom Source-Code ein File erzeugt, das 
nicht mehr auf den M16 geschrieben werden kann. Eventuell wurde vom 
Autor ein M32 verwendet, ohne dass er es im Schaltplan geändert hat?!?
Auch sehr verwunderlich, das es eine deutlich andere Größe hat als die 
mitgelieferte main.hex-Datei.
Könnte das Problem bei einer Compiler-Optimierungseinstellung liegen?

Wolfgang schrieb:
> Dann starte den Simulator doch mal mit deinem DDS-Code. Nur installieren
> alleine bringt nichts. ;-)

Ist auf dem anderen Rechner installiert, morgen kann ich es testen.


Walter schrieb:
> dann hast du bei einer Taktfrequenz der
> CPU von 20 MHz und eine PWM-Auflösung von 8 Bit eine max. Frequenz von
> rund 11160,7 Hz. Gehst du mit der Frequenz höher, dann verringert sich
> die Auflösung der PWM.

Danke für den Beitrag, sehr aufschlussreich!!! Das aktuelle Projekt 
läuft mit 16MHz, liegt dann die max. mögliche 8-Bit-PWM bei 8928 Hz?
Angehängte Dateien:
Gast #4706787
Lesenswert?

Alex schrieb:
> Könnte das Problem bei einer Compiler-Optimierungseinstellung liegen?

Nein, ich habe/hatte -0s eingestellt, das ist schon die Optimierung
mit dem kleinsten Code. Mehr geht nicht.

Einzige mögliche Stolperfalle bei mir: ich habe WinAVR-20100110
benutzt, also weit weg von aktuellen Compiler-Versionen.
Aber ich bezweifle dass man noch mehr als 20% mit einer neueren
Version einsparen kann ....

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