Forum: Mikrocontroller und Digitale Elektronik ATtiny814 RTC Abweichung


von _justified (Gast)


Lesenswert?

Servus,

der interne RTC des ATtiny (betrieben vom 32kHz Ultra Low Power Crystal) 
bringt mir auf 60 Sekunden ca 1 Sekunde Abweichung. Laut Spezifikation 
im Datenblatt ist das aber total ok.
Um genauer zu werden habe ich eine 32kHz Quarz an TOSC1/TOSC2 mit 2x 
22nF Caps gepackt.
Konfiguriert wurde wie folgt:
1
void initRtcClock(void)
2
{
3
  uint8_t temp;
4
5
  /* Initialize 32.768kHz Oscillator: */
6
  /* Disable oscillator: */
7
  temp = CLKCTRL.XOSC32KCTRLA;
8
  temp &= ~CLKCTRL_ENABLE_bm;
9
  _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
10
  
11
  while(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm)
12
  {
13
    ; /* Wait until XOSC32KS becomes 0 */
14
  }
15
16
  /* SEL = 0 (Use External Crystal): */
17
  temp = CLKCTRL.XOSC32KCTRLA;
18
  temp &= ~CLKCTRL_SEL_bm;
19
  _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
20
21
  /* Enable oscillator: */
22
  temp = CLKCTRL.XOSC32KCTRLA;
23
  temp |= CLKCTRL_ENABLE_bm;
24
  _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
25
26
  while(RTC.STATUS > 0)
27
  {
28
    ;
29
  }
30
  
31
  RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc;
32
  RTC.PITINTCTRL = RTC_PI_bm;
33
  RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm;
34
  RTC.DBGCTRL = RTC_DBGRUN_bm;
35
}

Setup des XOSC32KCTRLA habe ich aus dem Beispiel von dem 
tinyAVR1-RTC-example von Microchip entnommen.

Das Programm rennt und wenn ich den Quarz abziehe steht das Programm. 
Scheint also über den externen Quarz zu laufen. (Hab leider kein Oszi)

Nur habe ich keinerlei Verbesserung der Genauigkeit. Auf 60 Sekunden 
gesehen verschiebt sich der Tick wieder um 1 Sekunde. Sollte beim 
externen Quarz doch genauer sein? Übersehe ich hier etwas?

von Peter D. (peda)


Lesenswert?

_justified schrieb:
> der interne RTC des ATtiny (betrieben vom 32kHz Ultra Low Power Crystal)
> bringt mir auf 60 Sekunden ca 1 Sekunde Abweichung. Laut Spezifikation
> im Datenblatt ist das aber total ok.

Nö, mit Quarz muß das viel genauer sein (wenige s je Tag).
1,7% schafft ja schon der RC-Oszillator.

_justified schrieb:
> Um genauer zu werden habe ich eine 32kHz Quarz an TOSC1/TOSC2 mit 2x
> 22nF Caps gepackt.

Das ist um den Faktor 1000 falsch.

von Stefan F. (Gast)


Lesenswert?

_justified schrieb:
> auf 60 Sekunden ca 1 Sekunde Abweichung

Das wären ja 12 Minuten pro Monat! Ich wäre damit höchst unzufrieden.

von Herbert (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> _justified schrieb:
>> auf 60 Sekunden ca 1 Sekunde Abweichung
>
> Das wären ja 12 Minuten pro Monat! Ich wäre damit höchst unzufrieden.

Rechnen kannst du also auch nicht.

von Stefan F. (Gast)


Lesenswert?

Herbert schrieb:
> Rechnen kannst du also auch nicht.

Hoppla, es sind 12 Stunden, nicht Minuten.

von Stefan F. (Gast)


Lesenswert?

Für welche Lastkapazität ist denn dieser
> 32kHz Quarz an mit 2x 22nF Caps
vorgesehen? Und wie sieht der Aufbau aus, mit welchen parasitären 
Kapazitäten ist dort zu rechnen?

von _justified (Gast)


Lesenswert?

Peter D. schrieb:
> Das ist um den Faktor 1000 falsch.

Sorry habe mich vertippt. Das sind natürlich pF.

Stefan ⛄ F. schrieb:
> Für welche Lastkapazität ist denn dieser
>> 32kHz Quarz an mit 2x 22nF Caps
> vorgesehen? Und wie sieht der Aufbau aus, mit welchen parasitären
> Kapazitäten ist dort zu rechnen?

Verwendet wird in der Schaltung:
2x 22pF Keramikkondensator
1x AB26T Quarz (https://www.mouser.de/datasheet/2/3/AB26T-39673.pdf)

Aufgebaut ist das wie folgt:
Zwischen TOSC1 und TOSC2 hängt der Quarz. Zusätzlich an jedem Beinchen 
vom Quarz noch ein 22pF Kondensator auf Ground.

von Teo D. (teoderix)


Angehängte Dateien:

Lesenswert?

_justified schrieb:
> Verwendet wird in der Schaltung:
> 2x 22pF Keramikkondensator
> 1x AB26T Quarz (https://www.mouser.de/datasheet/2/3/AB26T-39673.pdf)

Scheint immer noch  2-4x zu hoch zu sein1

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

also 32kHz Quarze gibts i.d.R. mit 6pF oder 12.5pF (bei deinem 12.5) da 
sind die 22pF extern viel zu groß. Meist ist die interne Kapazität und 
die der Leiterbahn so groß das überhaupt kein Kondensator extern 
angeschlossen wird.
Die 22pF sind für Quarze im MHz Bereich.

Sascha

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> Auf 60 Sekunden gesehen verschiebt sich der Tick wieder um 1 Sekunde.

Wie wird das festgestellt? Oder anders gefragt, liegt vielleicht 
schlicht ein Additions- oder Rechenfehler vor?

von S. Landolt (Gast)


Lesenswert?

PS:
Auch bei mir hatte die Minute schon mal 59 oder 61 Sekunden.

von _justified (Gast)


Lesenswert?

Teo D. schrieb:
> Scheint immer noch  2-4x zu hoch zu sein1

Sascha W. schrieb:
> also 32kHz Quarze gibts i.d.R. mit 6pF oder 12.5pF (bei deinem 12.5) da
> sind die 22pF extern viel zu groß. Meist ist die interne Kapazität und
> die der Leiterbahn so groß das überhaupt kein Kondensator extern
> angeschlossen wird.
> Die 22pF sind für Quarze im MHz Bereich.

Danke, das werde ich heute mal versuchen!

S. Landolt schrieb:
> Wie wird das festgestellt? Oder anders gefragt, liegt vielleicht
> schlicht ein Additions- oder Rechenfehler vor?

Ich nutze den PIT um eine LED blinken zu lassen. Der verwendet den 32kHz 
Oszi und ist auf 32k Clock-Cycles eingestellt = 1s. In der Routine zähle 
ich eine Variable bis 60 hoch und toggle die LED. Ein Rechenfehler ist 
hier leider ausgeschlossen.

von m.n. (Gast)


Lesenswert?

_justified schrieb:
> Der verwendet den 32kHz
> Oszi und ist auf 32k Clock-Cycles eingestellt = 1s.

Mit welchem Takt Du den Timer laufen läßt, sehe ich jetzt nicht. Sicher 
ist jedoch, daß mit ext. Quarz der Teiler auf 32768 eingestellt werden 
muß, um 1 s Intervalle zu erhalten.

Wenn Du die genaue Zeit haben willst, mußt Du auch mit genauen 
Zahlenangaben arbeiten.

von S. Landolt (Gast)


Lesenswert?

Ein Quarzoszillator, der aufgrund der Kapazitäten um 1.7 % danebenliegt? 
Kann ich mir nur schwer vorstellen.

von _justified (Gast)


Lesenswert?

m.n. schrieb:
> Mit welchem Takt Du den Timer laufen läßt, sehe ich jetzt nicht. Sicher
> ist jedoch, daß mit ext. Quarz der Teiler auf 32768 eingestellt werden
> muß, um 1 s Intervalle zu erhalten.

Das ist hier ersichtlich:

_justified schrieb:
> RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc;
>   RTC.PITINTCTRL = RTC_PI_bm;
>   RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm;
>   RTC.DBGCTRL = RTC_DBGRUN_bm;

Über CLKSEL wird der externe 32.768kHz Quarz selektiert. Mit 
RTC_PERIOD_CYC32768 wird der Teiler auf exakt die Quarzgeschwindigkeit 
gestellt. Das "sollte" so auf 1s herauslaufen.

S. Landolt schrieb:
> Ein Quarzoszillator, der aufgrund der Kapazitäten um 1.7 % danebenliegt?
> Kann ich mir nur schwer vorstellen.

Gibt es noch andere Gründe warum der dann so viel danebenliegt?

von S. Landolt (Gast)


Lesenswert?

> Gibt es noch andere Gründe ...

Ich glaube nicht, dass es am Quarz liegt. Vielleicht ein 
Konfigurationsfehler, aber ich kenne diese ATtiny-Reihe leider nicht.

von 2 Cent (Gast)


Lesenswert?

_justified schrieb:
> auf 60 Sekunden ca 1 Sekunde Abweichung
32000/32768*60 = 58.59 #in jeder Minute mehr als eine Sekunde
Zufall?
Oder hast du (Umkehrfall) einen Quarz mit 32000 Hz am Start?

Du könntest über 10 (100) Minuten messen, um die Nachkommastellen zu 
überprüfen.

: Wiederhergestellt durch Moderator
von Stefan F. (Gast)


Lesenswert?

_justified schrieb:
>> Für welche Lastkapazität ist denn dieser vorgesehen?
> Verwendet wird in der Schaltung 
https://www.mouser.de/datasheet/2/3/AB26T-39673.pdf

Dann mache die Kondensatoren mal etwas kleiner. Wenn du die parasitären 
Kapazitäten der Schaltung nicht kennst, versuche es mal mit 2x 12pF. 
Wenn du ohnehin einkaufen musst, bestelle gleich noch 2x 4,7pF dazu.

von m.n. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Dann mache die Kondensatoren mal etwas kleiner. Wenn du die parasitären
> Kapazitäten der Schaltung nicht kennst, versuche es mal mit 2x 12pF.
> Wenn du ohnehin einkaufen musst, bestelle gleich noch 2x 4,7pF dazu.

Die Kondensatoren sind zunächst völlig wurscht.
Beim ATtiny817 Xplained Board habe ich einfach einen Quarz an PB2 und 
PB3 gesteckt - ganz ohne Cs. Als Ausgangsfrequenz nach Teilung erhalte 
ich 0,9999977 mHz. Die 2,3 ppm Abweichung zu 1 Hz könnte ich durch 
Abgleich noch reduzieren ;-)

@TO: Deine Initialisierung funktioniert.

von m.n. (Gast)


Lesenswert?

Ein "m" war zuviel:
0,9999977 Hz

von Peter D. (peda)


Lesenswert?

m.n. schrieb:
> Die Kondensatoren sind zunächst völlig wurscht.

So ist es, Quarze kann man nicht um 1,7% ziehen.

von Peter D. (peda)


Lesenswert?

_justified schrieb:
> Ich nutze den PIT um eine LED blinken zu lassen. Der verwendet den 32kHz
> Oszi und ist auf 32k Clock-Cycles eingestellt = 1s. In der Routine zähle
> ich eine Variable bis 60 hoch und toggle die LED.

Ooch nöö, Code in Prosa!

_justified schrieb:
> Ein Rechenfehler ist
> hier leider ausgeschlossen.

Na wenn Du das sagst.

von avr (Gast)


Lesenswert?

temp = ...;
temp &= ...;

sieht seltsam aus .......

versuche mal
1
while (RTC.STATUS > 0) { /* Wait for all register to be synchronized */
2
  }
3
4
  // RTC.CMP = 0x0; /* Compare: 0x0 */
5
6
  // RTC.CNT = 0x0; /* Counter: 0x0 */
7
8
  RTC.CTRLA = RTC_PRESCALER_DIV1_gc   /* 1 */
9
              | 1 << RTC_RTCEN_bp     /* Enable: enabled */
10
              | 0 << RTC_RUNSTDBY_bp; /* Run In Standby: disabled */
11
12
  // RTC.PER = 0xffff; /* Period: 0xffff */
13
14
  RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc; /* 32.768kHz External Crystal Oscillator (XOSC32K) */
15
16
  // RTC.DBGCTRL = 0 << RTC_DBGRUN_bp; /* Run in debug: disabled */
17
18
  // RTC.INTCTRL = 0 << RTC_CMP_bp /* Compare Match Interrupt enable: disabled */
19
  //     | 0 << RTC_OVF_bp; /* Overflow Interrupt enable: disabled */
20
21
  // RTC.PITCTRLA = RTC_PERIOD_OFF_gc /* Off */
22
  //     | 0 << RTC_PITEN_bp; /* Enable: disabled */
23
24
  // RTC.PITDBGCTRL = 0 << RTC_DBGRUN_bp; /* Run in debug: disabled */
25
26
  // RTC.PITINTCTRL = 0 << RTC_PI_bp; /* Periodic Interrupt: disabled */

von avr (Gast)


Lesenswert?

mit pit
1
while (RTC.STATUS > 0) { /* Wait for all register to be synchronized */
2
  }
3
4
  // RTC.CMP = 0x0; /* Compare: 0x0 */
5
6
  // RTC.CNT = 0x0; /* Counter: 0x0 */
7
8
  RTC.CTRLA = RTC_PRESCALER_DIV1_gc   /* 1 */
9
              | 1 << RTC_RTCEN_bp     /* Enable: enabled */
10
              | 0 << RTC_RUNSTDBY_bp; /* Run In Standby: disabled */
11
12
  // RTC.PER = 0xffff; /* Period: 0xffff */
13
14
  RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc; /* 32.768kHz External Crystal Oscillator (XOSC32K) */
15
16
  // RTC.DBGCTRL = 0 << RTC_DBGRUN_bp; /* Run in debug: disabled */
17
18
  // RTC.INTCTRL = 0 << RTC_CMP_bp /* Compare Match Interrupt enable: disabled */
19
  //     | 0 << RTC_OVF_bp; /* Overflow Interrupt enable: disabled */
20
21
  while (RTC.PITSTATUS > 0) { /* Wait for all register to be synchronized */
22
  }
23
24
  RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc /* RTC Clock Cycles 32768 */
25
                 | 1 << RTC_PITEN_bp;   /* Enable: enabled */
26
27
  // RTC.PITDBGCTRL = 0 << RTC_DBGRUN_bp; /* Run in debug: disabled */
28
29
  RTC.PITINTCTRL = 1 << RTC_PI_bp; /* Periodic Interrupt: enabled */
30
31
32
ISR(RTC_PIT_vect)
33
{
34
  /* Insert your PIT interrupt handling code here */
35
36
  /* The interrupt flag has to be cleared manually */
37
  RTC.PITINTFLAGS = RTC_PI_bm;
38
}

ohne garantie

von m.n. (Gast)


Lesenswert?

avr schrieb:
> ohne garantie

Auf die Schnelle:
1
#include <stdint.h>
2
#include <iotiny817.h>
3
4
#define PB1_BIT 2
5
6
void initRtcClock(void)
7
{
8
  uint8_t temp;
9
10
  /* Initialize 32.768kHz Oscillator: */
11
  /* Disable oscillator: */
12
  temp = CLKCTRL.XOSC32KCTRLA;
13
  temp &= ~CLKCTRL_ENABLE_bm;
14
  CCP = CCP_IOREG_gc;           // IO Register Protection
15
  CLKCTRL.XOSC32KCTRLA = temp;
16
// Wait until XOSC32KS becomes
17
  while(CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm);
18
  
19
  /* SEL = 0 (Use External Crystal): */
20
  temp = CLKCTRL.XOSC32KCTRLA;
21
  temp &= ~CLKCTRL_SEL_bm;
22
  CCP = CCP_IOREG_gc;           // IO Register Protection
23
  CLKCTRL.XOSC32KCTRLA = temp;
24
25
  /* Enable oscillator: */
26
  temp = CLKCTRL.XOSC32KCTRLA;
27
  temp |= CLKCTRL_ENABLE_bm;
28
  CCP = CCP_IOREG_gc;           // IO Register Protection
29
  CLKCTRL.XOSC32KCTRLA = temp;
30
  while(RTC.STATUS > 0);
31
  
32
  RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc;
33
  RTC.PITINTCTRL = RTC_PI_bm;
34
  RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc | RTC_PITEN_bm; // 500 ms Intervall
35
  RTC.DBGCTRL = RTC_DBGRUN_bm;
36
}
37
38
int main(void)
39
{
40
  CCP = CCP_IOREG_gc;           // IO Register Protection
41
  CLKCTRL_MCLKCTRLB = 0x00;     // kein Vorteiler
42
  initRtcClock();               // init RTC mit ext. 32768 Hz
43
  PORTB_DIR |= PB1_BIT;         // PB1 als Ausgang
44
  while (1) { 
45
    while(RTC.PITINTFLAGS == 0);// gesetztes Flag abwarten
46
    RTC.PITINTFLAGS = 1;        // löschen
47
    PORTB.OUT ^= PB1_BIT;       // PB1 alle 0,5 s togglen => 1 Hz
48
  }
49
}
Mit Garantie aber ohne Interrupt ;-)

von avr (Gast)


Lesenswert?

> Mit Garantie aber ohne Interrupt ;-)

dann viel besser :)

>  CCP = CCP_IOREG_gc;           // IO Register Protection

kannte ich noch nicht , ersetzt den aufruf von _PROTECTED_WRITE ?!

- muss mal im DB blättern war mir nicht bewust das dieses für die RTC 
notwendig ist

mfg

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.