ATmega328p Timer

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

Re: ATmega328p Timer

Beitrag von Mathias »

Damit zählt TCNT immer nur von 200 bis 255, macht dann Overflow auf 0, der Interrupt wird aufgerufen und da TCNT 0 ist wird es auf 200 gesetzt und zählt wieder bis 255.

Ich habe jetzt folgendes eingefügt:

Code: Alles auswählen

 TCNT2 := 240;
Jetzt blinkt die LED sehr schnell.
Verstehe ich es richtig, das man mit TCNTx, die Feinseinstellung eines Timer regulieren kann.
Beim Timer1 ist TCNT1 16Bit breit und dies ist der Grund, wieso das dieser Timer viel genauer ist ?

Beim Arduino-Code, war es richtig undurchsichtig, was beim einem Timer im Hintergrund passiert. :|

PS: Es wird da eine andere Schreibweise empfohlen, da alias angeblich veraltet ist.

Code: Alles auswählen

  //procedure Timer2_Interrupt; alias: 'TIMER2_OVF_ISR'; interrupt; public;
    procedure Timer2_Interrupt; public Name 'TIMER2_OVF_ISR'; interrupt;

Wen man die ändert, kommt auch der Code-Formatierer zu recht. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Ich habe jetzt folgendes eingefügt:

Code: Alles auswählen

 TCNT2 := 240;
Jetzt blinkt die LED sehr schnell.


Logisch, jetzt zählt TCNT nur fon 240 bis 255 und löst den Interrupt aus.

Mathias hat geschrieben:Verstehe ich es richtig, das man mit TCNTx, die Feinseinstellung eines Timer regulieren kann.


Ja. Mit dem Prescaler kannst Du nur Werte vom Systemtakt div 2^n einstellen, und auch nicht für alle n. Mit TCNT - oder auch mit OCR0A, OCR0B und dem OutputCompare Interrupts - kannst Du Zwischenwerte einstellen. Aber auch nicht alle, ist halt digital. ;-)

Mathias hat geschrieben:Beim Timer1 ist TCNT1 16Bit breit und dies ist der Grund, wieso das dieser Timer viel genauer ist ?


Jaein. Die "Genauigkeit" hängt von vielen Faktoren ab. Zum Beispiel vom Quarz. Mit einem 16MHz Quarz kommst Du nur umständlich "genau" auf eine Sekunde, weil 16000000 sich schlecht in 2^n aufteilen läßt. Man braucht zusätzliche Zählvariablen. Mit einem 4.194MHz Quarz - ein beliebter Uhrenquarz - kommst Du allein mit 2^n-Teilern auf genau eine Sekunde.

Die 16bit-Timer spielen ihren hohen Wertebereich vor allem bei der Erzeugung von Frequenzen (Frequenzgenerator), hochauflösenden PWM (DA-Wandler, Motorsteuerung) oder der Messung von Freqenzen oder Pulsdauern aus.

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

Re: ATmega328p Timer

Beitrag von Mathias »

Die 16bit-Timer spielen ihren hohen Wertebereich vor allem bei der Erzeugung von Frequenzen (Frequenzgenerator), hochauflösenden PWM (DA-Wandler, Motorsteuerung) oder der Messung von Freqenzen oder Pulsdauern aus.
Wen ich das so lese, wen man den 16Bit-Timer für eigene Zwecke verwendet, dann ist fertig mit den Analogen-Ausgängen(PWM) ? :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Wen ich das so lese, wen man den 16Bit-Timer für eigene Zwecke verwendet, dann ist fertig mit den Analogen-Ausgängen(PWM) ? :roll:


Sachmal, meine beharrlichen Hinweise auf das Datenblatt ignorierst Du konsequent?

Der ATmega328 hat zwei 8..16-bit PWM Ausgänge an Timer1, zwei 8-bit-PWM-Ausgänge an Timer2 und zwei 8-bit-PWM-Ausgänge an Timer0. Welche davon man nutzt hängt unter anderem davon ab, welche Pins man sonst noch benötigt. So liegt OC2A zum Beispiel auf MOSI, verträgt sich also nicht mit einer SPI-Schnittstelle (wohl aber mit dem ISP Programmer am SPI), OC2B liegt mit INT1 auf PD3, geht also nicht wenn man beide externen Interrupts braucht.

Da die Anzahl der Pins begrenzt ist und die AVRs eine Menge Hardwarefunktionen bieten, muss man halt Kompromisse machen. So geht Hardware I2C an PC4/PC5 nicht, wenn man alle AD-Kanäle nutzen will, dafür gibt es dann Software-I2C.

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

Re: ATmega328p Timer

Beitrag von Mathias »

Jetzt verstehe ich langsam, wieso gewisse Kombinationen von Funktionen auf dem Arduino nicht funktionierten. Ich wollte mal einen Timer und gleichzeitig I²C nutzen, aber irgendwie ging es nicht. Jetzt weis ich, wieso du nicht so Fan von der Arduino-Software bist. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Jetzt weis ich, wieso du nicht so Fan von der Arduino-Software bist. :wink:


Naja, Du siehst halt nicht was drinnen passiert. Für Schüler die ein paar LEDs blinken lassen ist das erstmal ok. Aber es verschenkt eben sehr viele Möglichkeiten.

Ich hab früher auch mal so programmiert: AVR als State-Maschine, mache das, warte auf Ergebnis, mache das, warte auf Uart, mache das... Kann man machen, wird aber irgendwann langweilig. ;-)

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

Re: ATmega328p Timer

Beitrag von Mathias »

AVR als State-Maschine, mache das, warte auf Ergebnis, mache das, warte auf Uart, mache das... Kann man machen, wird aber irgendwann langweilig.

Der Arduino kennt auch Interrupts, immerhin bringe ich damit Multiplex hin.
Mit dem UART konnte ich immerhin mit 1'000'000 Baud kommunizieren. I²C klappt auch gut.
Aber eben wie du sagt, man weis nicht was wirklich passiert.

Gutes Beispiel ist digitalWrite(...), dies ist mindestens 10x langsamer als PORTB |= (1 << PB5);.

Ich hab früher auch mal so programmiert:
Bis vor kurzem kannte ich nur Arduino, immerhin kann, man damit auch ATtiny programmieren.
Aber so wie es aussieht ändert sich dies, da man jetzt Unterstützung von Lazarus hat. :lol: :wink:
Siehe UART-Thread, da hat mir Arduino auch ein Ei gelegt.

Mal gucke, ob Lazarus irgendwann auch den Arduino due unterstützt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: ATmega328p Timer

Beitrag von Mathias »

Ich habe gerade etwas ganze gemeines entdecke, was die Timer betrifft. Die Procedure-Namen sind unterschiedlich. :roll:

Code: Alles auswählen

// ATtiny2313
procedure Timer0_Interrupt; public Name 'TIMER0_COMPA_ISR'; interrupt;
// ATtiny44
procedure Timer0_Interrupt; public Name 'TIM0_COMPA_ISR'; interrupt;


Ich habe dazu einen Hinweis ins Tutorial geschrieben, nicht das noch wer anders wegen dies Zeit versaumt. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: ATmega328p Timer

Beitrag von Mathias »

Wen man ein Uhr mit einem Arduino bauen will, wird die einem nie genau laufen, weil der Arduino mit 16MHz getaktet ist.
Somit habe probiert den Timer Extern über den Pin T0 zu takten. Dort habe ich einen Oszilator mit 4.194304 MHz angeschlossen.

Somit habe ich es mit folgendem Programm probiert.

Code: Alles auswählen

var
  sekTakt: Boolean;
 
  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
  const
    zaehler: UInt16 = 0;
    cl = 4194304 shr 8 shr 1;
  begin
    Inc(zaehler);
    if zaehler = cl then begin
      PORTB := PORTB or (1 shl 5);
    end;
    if zaehler >= cl * 2 then begin
      PORTB := PORTB and not (1 shl 5);
      zaehler := 0;
      sekTakt:=True;
    end;
  end;
 
var
  zeit: Integer;
  s : String[10];
 
 
begin
  DDRB := DDRB or (1 shl 5); // Pin 13 Output
 
  TCCR0A := %00;               // Normaler Timer
  TCCR0B := %111;              // Clock / Externer Pin TO, steigende Flanke
  TIMSK0 := (1 shl TOIE0);     // enable timer2 overflow interrupt.
 
  UARTInit;
  sekTakt := False;
  asm sei end;                       // Interrupts einschalten.
 
  repeat
     if sekTakt then begin
       sekTakt:=False;
       Inc(Zeit);
       str(zeit:8, s);
       UARTSendString(s + #13#10);
     end;
  until 1 = 2;
end.

Auf dem ersten Blick scheint es zu funktionieren, über die UART-Schnittstelle kommt alle Sekunden einen Zeichen an.
Nun muss ich noch eine Externe-Anzeige basteln und gucken, ob die Uhr auch auf längere Zeit richtig geht. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Wen man ein Uhr mit einem Arduino bauen will, wird die einem nie genau laufen, weil der Arduino mit 16MHz getaktet ist.


Doch wohl:

Variante 1: Prescaler auf 1, OCR1A (16bit-Timer) auf 16000 / 32000 / 64000, CTC ein. Gibt Interrupt alle 1 / 2 oder 4msec. Mit einem Zähler im Interrupt jeweils bis 1000 , 500 oder 250 zählen und Du hast eine quarzgenaue Sekunde.

Variante 2: Prescaler auf 64, OCR0A (8bit-Timer) auf 250, CTC ein. Gibt Interrupt alle 1msec, Rest wie oben.

Variante 3: Prescaler auf 256 oder 1024, OCR1A (16-bit-Timer) auf 62500 oder 15625, CTC ein. Gibt Interrupt jede Sekunde. Sekunden-Interrupts sind aber meistens Quark, weil man sie nicht für andere Sachen wie Tasten entprellen zweitverwenden kann.

Die Frage ist eher, wie genau ist der Quarz auf dem Arduino. Wenn das ein China-Billigteil ist, wo Quarze verlötet werden, die beim Hersteller aus der Bauteilklassifizierung gefallen sind, können die schonmal ein paar Sekunden am Tag daneben liegen. Das kann Dir mit Deinem 4.194304 MHz Quarz aber auch passieren.

4.194304 MHz hat man früher gern als Uhrenquarz für hochwertige Uhren genommen, weil man die ihn so schneiden konnte, dass man eine hohe Genauigkeit erreicht hat und weil die 4.194304 MHz eben gut durch die damals verfügbaren Binärteiler teilbar waren.

Die 32.768 kHz "Uhrenquarze" waren einfach nur billig. Aber sie hatten einen enormen Vorteil: Bedingt durch die extrem niedrige Taktfrequenz waren sie sehr energiesparend und damit gut für Armbanduhren geeignet.

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

Re: ATmega328p Timer

Beitrag von Mathias »

Doch wohl:
Ein Kollege von mir, der Kanti-Lehrer ist, hatte mit seinen Schülern eine Arduino-Uhr gebaut, aber die Genauigkeit lässt zu wünschen übrig. Aber so wie es scheint, für 3 Varianten zum Ziel. Er hatte die Arduino-Bibliotheken für die Uhr verwendet, evtl. können die den Timer nicht so genau einstellen. Oder eben wie du sagst, der Quarz ist ungenau.
Aus diesem Grund bastel ich momentan mit einem externen Clock.

Das kann Dir mit Deinem 4.194304 MHz Quarz aber auch passieren.
Das könnte natürlich auch passieren, die Quarze habe ich bei Reichelt gekauft, aber dies ist keine Garantie.
Ich denke, das beste wird wohl ein Uhrenquarz sein, oder kann man da auch ins Fettnäpfchen treten,
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Das könnte natürlich auch passieren, die Quarze habe ich bei Reichelt gekauft, aber dies ist keine Garantie.


Oha, gerade bei Reichelt hatte ich schon Bauteile, bei denen alle gerade so an der Toleranzgrenze lagen. Das waren dann welche, die woanders aus der Sortierung fielen.

Kann man nur probieren und natürlich kann man auch Glück haben. Andererseits kann man bei einem Mikrocontroller im Gegensatz zu den früheren Schaltungen mit festen Binärteilern auch wunderbar in Software nachkalibrieren. Geht die Uhr um 1sec am Tag nach, muss man eben alle 86400 Zähltakte einen zusätzlichen Takt zählen. Früher musste man die Quarze dann mit einem Trimmkondensator "ziehen".

Ein Quarz mit einer Fertigungstoleranz von 50ppm kann bis zu 4sec am Tag vor oder nachgehen. Bei einem Temperaturgang von 100ppm eines BT-Quarzes können das bis zu 8sec sein - allerdings über einen Temperaturbereich von -20 bis 70°C.

Geht die Uhr stärker falsch, würde ich davon ausgehen, da stimmt was nicht: Entweder ist ein Fehler im Programm, ich hab einen grob falschen Quarz erwischt oder der Quarz ist falsch eingesetzt, z.B. Obertonquarz in Grundschwingung oder Reihenquarz in Parallelschaltung. Auch sollte man tunlichst vermeiden, die empfindlichen 32kHz-Quarze am normalen Quarzoszillator eines ATmega zu betreiben, die Spannung kann den Quarz zerstören. Der ATmega328 hat dafür einen eigenen 32kHz-Modus mit verringerter Signalamplitude.

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

Re: ATmega328p Timer

Beitrag von Mathias »

Bei den Timern habe ich noch etwas entdeckt. Beim ATtiny2313 wirf für die Aktivierung der Interrupts das gleiche Register TIMSK verwendet.
Der ATmega328 hat für jeden Timer ein eigenes Register TIMSK? .


Ein Quarz mit einer Fertigungstoleranz von 50ppm kann bis zu 4sec am Tag vor oder nachgehen. Bei einem Temperaturgang von 100ppm eines BT-Quarzes können das bis zu 8sec sein - allerdings über einen Temperaturbereich von -20 bis 70°C.
Wie sieht es mit richtigen Uhrenquarzen aus, dies müssten doch recht genau laufen, oder täusche ich mich da ?
Ich habe gerade gesehen, das auch dies Quarze +-20ppm haben. https://www.reichelt.de/index.html?ACTION=446&LA=446
Was werden in der Praxis für Quarze in den Uhren verbaut, schon 1Sek pro Tag wäre zu viel.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
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: ATmega328p Timer

Beitrag von Timm Thaler »

Mathias hat geschrieben:Bei den Timern habe ich noch etwas entdeckt. Beim ATtiny2313 wirf für die Aktivierung der Interrupts das gleiche Register TIMSK verwendet.
Der ATmega328 hat für jeden Timer ein eigenes Register TIMSK?


Ein übliches Vorgehen bei Atmel. Die Dinger sind ja nicht vom Himmel gefallen, sondern wurden immer weiter entwickelt. Man hat dabei versucht, die Register - jedes Register = 8 Speicherstellen benötigt ja Platz auf dem Chip - soweit es geht beizubehalten. Wenn es nicht mehr anders ging, wurden weitere Register eingefügt. Bei späteren Controllern mit kleineren Chipstrukturen wurde man dann großzügiger.

Mathias hat geschrieben:Wie sieht es mit richtigen Uhrenquarzen aus, dies müssten doch recht genau laufen, oder täusche ich mich da ?


Ein Quarz läuft a) so genau wie ihn der Hersteller gefertigt hat - siehe Datenblatt und b) so genau wie er betrieben wird. Das hängt von der Schaltung ab.

Die Genauigkeit eines Quarzes wird beeinflusst durch:
- Fertigungstoleranz, kann durch "Ziehen" oder digitales Kalibrieren kompensiert werden
- Temperaturgang, je nach Schnitt verschiedene Kennlinien, kann durch Temperaturmessung oder Kompensationsnetzwerke (Heissleiter, Kondensatoren mit gegenläufigem Temperaturgang) kompensiert werden
- Alterung, kaum kompensierbar, wird durch Voraltern und Nachkalibrieren minimiert
- falschen Betriebsbereich (Oberschwingungen durch Ansteuerung mit zu hoher Amplitude, Rechteckspannung statt Sinus)
- falsche Betirebsart (Oberschwingungsquarz im Grundton, Reihenschwingungsquarz in Parallelschaltung)

Selbst die Größe der Kondensatoren am Quarz hat einen Einfluss auf dessen Frequenz.

Mathias hat geschrieben:Was werden in der Praxis für Quarze in den Uhren verbaut, schon 1Sek pro Tag wäre zu viel.


Für billige Armbanduhren sind 1sec am Tag wenig.

Genauigkeit von Oszillatoren in aufsteigender Reihenfolge
- LC oder RC-Schwinger wie im ATmega intern verbaut
- Keramikresonator
- Schwingquarz in BT-Schnitt, um die 100ppm
- Schwingquarz in AT-Schnitt, um die 25..50ppm
- VCXO, spannungsgesteuerter Quarzoszillator, "Ziehen" durch eine Spannung von Außen
- TCXO, temperaturkompensierter Quarzoszillator, Kompensation durch eine analoge oder mittlerweile auch digitale Schaltung nach Temperatur, um die 1.5..3ppm
- OCXO, Quarzofen, Betrieb unter kontrollierten Bedingungen bei einer konstanten erhöhten Temperatur, um die 0.1..0.02ppm

So reizvoll der Betrieb in einem Quarzofen erscheinen mag: Du brauchst dafür spezielle Ofenquarze, die für die höhere Temperatur passend geschnitten sind, normale Quarze haben ihr Optimum um die 25°C. Und eine Quarzofen ist nur sinnvoll, wenn er ständig läuft, nach dem Einschalten ist er schlimmer als ein normaler Quarz (die Temperatur
ist ungleichmäßig verteilt), erst nach zwei Tagen ist er dann vielleicht stabil.

Und dann musst Du das ganze auch noch abgleichen können, dass heisst Du brauchst ein Normal, welches besser ist als Deine Uhr.

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

Re: ATmega328p Timer

Beitrag von Mathias »

Ich dachte immer, eine Quarzuhr sei sehr genau, aber so kann man sich täuschen. :oops:

Für billige Armbanduhren sind 1sec am Tag wenig.
Der Grund, das diesem einem nicht gross aufgefallen ist, wird sein, das man die Uhren 2 mal pro Jahr neu stellen muss. Bei 180 Tagen bei 1Sek. sind dies nur 3Min. So wie es scheint, habe ich bei meinem Backofen ein guter Quarz erwischt, diese läuft fast Zeit genau mit meiner Funkuhr.

Selbst die Größe der Kondensatoren am Quarz hat einen Einfluss auf dessen Frequenz.

Das wird wohl der Grund sein, wieso es hier ein Trimmkondensator hat.
Bild

- LC oder RC-Schwinger wie im ATmega intern verbaut
Immerhin hat der Arduino einen externen Quarz.

Nochmals zu den Timern zurück, hat das verstellen von OCR0A einen ähnlichen Einfluss, wie wen man in der Interrupt-Procdure TCNT0 verändert ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten