ATtiny814 RTC Abweichung

Gast #6169799
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?
#6170078
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.
Gast #6170553
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.
#6170564
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
Gast #6170596
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.
Gast #6170605
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.
Gast #6170616
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?
Gast #6170732
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.
Gast #6171137
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 */
Gast #6171146
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
Gast #6171195
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 ;-)
Gast #6171225
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

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