ATmega328 PWM Frequenz

Antworten
Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

ATmega328 PWM Frequenz

Beitrag von Mathias »

Ich verwende den Timer0 als PWM-Steuerung.
Wen ich an mehreren Orten Google, steht überall, das die PWM-Frequenz auf Timer 0 nur 8Bit hat.
ZB. hier: https://sites.google.com/site/qeewiki/b ... -atmega328

Beo folgendem Programm ist ein leichtes flimmer an den angeschlossenen LEDs sichtbar.

Code: Alles auswählen

begin
  // PD6 und PD7 auf Ausgang
  DDRD := %01100000;
 
  // PD6 und PD7 als PWM
  TCCR0A := (%10 shl COM0A) or (%10 shl COM0B) or (%1 shl WGM0); // Das WGM0
 
  // Timer 0 aktivieren, Clock / 1024
  TCCR0B := TCCR0B or %101;
 
  repeat
    for i := 0 to 255 do begin
      OCR0A := i;
      OCR0B := 255 - i;
      mysleep(sl);
    end;
    for i := 0 to 255 do begin
      OCR0A := 255 - i;
      OCR0B := i;
      mysleep(sl);
    end;
  until 1 = 2;
end.

Mache ich aber folgendes

Code: Alles auswählen

(%10 shl WGM0)
habe ich eine 10Bit-Auflösung, die LEDs flimmern nicht mehr.
10Bit dürfte eigentlich gar nicht gehen. :roll:
Wieso geht es trotzdem ?
Irgendwie verstehe ich etwas falsch. :cry:
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1144
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: ATmega328 PWM Frequenz

Beitrag von Timm Thaler »

Mit WGM0 = %10 setzt Du den Timer auf CTC (Clear on Compare). Dann wird jeweils ausgelöst, wenn TCNT den Wert in OCRA erreicht und TCNT zurückgesetzt. Damit kann man eine veränderliche Frequenz erzeugen, ist OCRA klein ist die Frequenz hoch, wird OCRA größer sinkt die Frequenz.

Was nun wahrscheinlich passiert ist, dass bei kleinem OCRA die Frequenz so hoch ist, dass Du kein Flimmern siehst. Aber eine vernünftige PWM kann dabei eigentlich nicht rauskommen.

Wenn Du Flimmern vermeiden willst, musst Du die PWM-Frequenz erhöhen, indem Du den Prescaler TCCR0B verringerst oder den Bereich der PWM verringerst (64, 128 statt 256 Werte), letzteres geht natürlich auf die Auflösung.

Beispiel: AVR läuft mit 8MHz

Prescaler 1024 => Timerfrequenz = 8kHz => PWM 256 Stufen => PWM-Frequenz 30Hz!!! Klar flimmert das.
Prescaler 1024 => Timerfrequenz = 8kHz => PWM 64 Stufen => PWM-Frequenz 125Hz, akzeptabel.
Prescaler 256 => Timerfrequenz = 31kHz => PWM 256 Stufen => PWM-Frequenz 122Hz, akzeptabel.
Prescaler 64 => Timerfrequenz = 125kHz => PWM 256 Stufen => PWM-Frequenz 488Hz, nicht mehr sichtbar unter den meisten Bedingungen.

Du musst hier unterscheiden zwischen der Frequenz, mit der der Timer läuft und die durch den Prescaler bestimmt wird. Mit dieser Frequenz schaut der Timer, ob OCRA oder OCRB erreicht sind und er den Ausgang umschalten muss. Das erfolgt automatisch in Hardware ohne Interrupt.
Der Ausgang schaltet dann während 256 Durchläufen des Timers einmal ein, wenn OCRA erreicht ist, und wieder aus wenn TCNT überläuft. Daraus ergibt sich dann die PWM-Frequenz, die um 256 kleiner ist als die Timerfrequenz.
Es gibt auch noch andere PWM-Modi, dabei läuft der Timer einmal bis 256 und dann wieder bis 0 zurück, und schaltet jeweils bei OCRA ein und aus. Damit ergibt sich ein sauberes Signal, man erkauft sich das aber durch Halbierung der PWM-Frequenz, weil ja insgesamt 512 Schritte gezählt werden.

PWM Frequenz = Systemtakt / Prescaler / PWM-Auflösung

Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ATmega328 PWM Frequenz

Beitrag von Mathias »

Das dachte ich mir fast, das man dies mit dem Prescaler löst.
Schlussendlich muss man die Parameter abschätzen, wen man den Timer noch anderwärtig braucht.

Wieder einmal zur Arduino-Software. Da macht man etwas mit dem Timer und verwundert sich, wieso, das auf einmal mit dem PWM etwas nicht stimmt.
Wen man alles selbst macht, dann sieht man die Abhängigkeiten. :wink:
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1144
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: ATmega328 PWM Frequenz

Beitrag von Timm Thaler »

Mathias hat geschrieben:Schlussendlich muss man die Parameter abschätzen, wen man den Timer noch anderwärtig braucht.


Nunja, da der 328 mit 3 Timern komfortabel ausgestattet ist, gibts meist eine Lösung.

Bei 8MHz kommt man in einer interruptgesteuerten Soft-PWM auf 300Hz PWM-Frequenz bei 256 Stufen Auflösung auf 8 Ausgängen gleichzeitig - allerdings in Assembler programmiert.

Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ATmega328 PWM Frequenz

Beitrag von Mathias »

Nunja, da der 328 mit 3 Timern komfortabel ausgestattet ist, gibts meist eine Lösung.

Der Atmega328 schon, aber es gibt noch ATTiny, zB. der 2313, der hat nur 2 Timer.
3 Servos, und alle Timer sind in Gebrauch.

Bei 8MHz kommt man in einer interruptgesteuerten Soft-PWM auf 300Hz PWM-Frequenz bei 256 Stufen Auflösung auf 8 Ausgängen gleichzeitig - allerdings in Assembler programmiert.
Die ist natürlich auch eine Lösung, das Ganze Softwaremässig zu steuern, aber ob die Ideal ist ?
Wie viel HZ braucht es, um einen Servo zu steuern ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1144
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: ATmega328 PWM Frequenz

Beitrag von Timm Thaler »

Mathias hat geschrieben:Der Atmega328 schon, aber es gibt noch ATTiny, zB. der 2313, der hat nur 2 Timer.
3 Servos, und alle Timer sind in Gebrauch.


Ja nur wenn man nicht programmieren kann.

Servos laufen mit 20msec Periodendauer und Pulsen zwischen 0.5msec und 2.5msec. Das mach ich Dir mit einem Timer und 256 Stufen Auflösung in Software - für 8 Kanäle gleichzeitig. Und da kann der Attiny nebenbei noch Seti rechnen...

sstvmaster
Beiträge: 394
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.0.10
CPU-Target: 32+64bit
Wohnort: Dresden

Re: ATmega328 PWM Frequenz

Beitrag von sstvmaster »

Hi Mathias,

vielleicht hilft dir das weiter, ist zwar in cpp.

Quelle: https://github.com/k3ng/k3ng_rotator_co ... /TimerFive

TimerFive.cpp + TimerFive.h

Maik
Windows 10, Lazarus 2.0.10 + Lazarus Trunk
LG Maik

Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ATmega328 PWM Frequenz

Beitrag von Mathias »

Jetzt habe ich gerade gedacht, der Atmega328 hat auf einem 5 Timer. Aber dein Code ist für einen Atmega2560, welcher auf dem Arduino Mega verbaut ist.

Das ursprüngliche Problem ist gelöst, ich hatte es mit einem fehlerhaften Parameter probiert.

Unterdessen habe ich noch erfahren, das die Arduino-Bibliothek für Servos auch Software PWM benutzt.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

sstvmaster
Beiträge: 394
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.0.10
CPU-Target: 32+64bit
Wohnort: Dresden

Re: ATmega328 PWM Frequenz

Beitrag von sstvmaster »

Um Timer5 ging es mir eigentlich nicht, den Code hatte ich nur gerade bei der Suche nach was anderem gefunden.

Ich hatte nur gedacht, weil es dort auch um PWM und Timer ging, das es für interessant sein könnte.

Da auch in der TimerFive.cpp was vom ATmega328 stand:
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support


LG Maik
Windows 10, Lazarus 2.0.10 + Lazarus Trunk
LG Maik

Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ATmega328 PWM Frequenz

Beitrag von Mathias »

Um Timer5 ging es mir eigentlich nicht, den Code hatte ich nur gerade bei der Suche nach was anderem gefunden.

Das ist mir auch schon so gegangen, das sucht man etwas und findet dabei etwas anderes interessantes.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Antworten