Hallo,
da ich es bislang noch nicht hinbekommen habe, die Kommunikation
zwischen Atmega328P(später Attiny85) und DS3231 zu realisieren,
habe ich den SQW des DS3231 auf 1024Hz eingestellt über die Register RS1
und RS2.
Nun habe ich die Zeit eine halbe Stunde laufen lassen mit einer
seriellen Ausgabe zur Kontrolle.
Was mir aufgefallen ist, dass die Zeit um 2min/30min nachgeht.
Im Datenblatt habe ich keine Infos gefunden, ob der Ausgang des RTCs
ebenfalls Temperaturkompensiert ist.
Der Atmega328P wird genutzt mit einem Resonator mit 5V bei 16MHz. Der
DS3231 nutzt auch die Vcc von 5V.
1
void time_init(void)
2
{
3
DDRD &= ~(1 << DDD2);
4
//PORTD |= (1 << PORTD2); // Pull-Up aktivieren
5
6
// (0 << ISCx1) | (0 << ISCx0) LOW-Level am Pin löst den Interrupt aus
7
// (0 << ISCx1) | (1 << ISCx0) Jede Änderung am Pin löst den Interrupt aus
8
// (1 << ISCx1) | (0 << ISCx0) Eine fallende Flanke löst den Interrupt aus
9
// (1 << ISCx1) | (1 << ISCx0) Eine steigende Flanke löst den Interrupt aus
Stefan S. schrieb:> da ich es bislang noch nicht hinbekommen habe, die Kommunikation> zwischen Atmega328P(später Attiny85) und DS3231 zu realisieren,> habe ich den SQW des DS3231 auf 1024Hz eingestellt über die Register RS1> und RS2.
Den Satz verstehe ich jetzt nicht wirklich.
Um den Ausgang SQW auf 1024Hz einzustellen, muß die I2C-Kommunikation
zwischen dem µC und dem DS3231 doch funktionieren! Was hast du dann
nicht hinbekommen?
> Was mir aufgefallen ist, dass die Zeit um 2min/30min nachgeht.
Da liegt ein generelles Problem vor...
Sperrst du im Hauptprogramm an irgendeiner Stelle mal die Interrupts für
mehr als maximal ein paar Hundert µs?
Das wäre im Zweifelsfalle tödlich, weil du dann Interrupts verpaßt, was
naturgemäß zu einem Nachgehen deiner Interrupt-Uhr führt.
Achja: Wenn du eh nur an Sekunden interessiert bist, warum setzt du dann
den SQW Ausgang nicht auf 1Hz auf (RS1 = 0, RS2 = 0) und sparst dir 1023
Interrupts pro Sekunde?
Davon abgesehen würde ich für die Uhrzeit einfach die Echtzeit-Register
des DS3231 auslesen, die muß man Dank der Pufferbatterie auch nicht nach
jedem Power Up neu stellen, dafür ist so'ne RTC schließlich da! ;-)
> Im Datenblatt habe ich keine Infos gefunden, ob der Ausgang des RTCs> ebenfalls Temperaturkompensiert ist.
Selbstverständlich ist er das, geht auch aus dem Blockschaltbild im
Datenblatt (S. 8) hervor. Alles andere wäre ja auch sinnbefreit.
> Der DS3231 nutzt auch die Vcc von 5V.
5V-Betrieb ist laut Datenblatt zwar noch zulässig, aber der DS3231 ist
für nominell 3V3 ausgelegt.
Der SQW-Ausgang des DS3231 ist Open Drain. Daher die fallende Flanke
nehmen, dann paßt die Flankensteilheit auf jeden Fall.
1
voidtime_init(void)
2
{
3
DDRD&=~(1<<DDD2);
4
//PORTD |= (1 << PORTD2); // Pull-Up aktivieren
5
6
// (0 << ISCx1) | (0 << ISCx0) LOW-Level am Pin löst den Interrupt aus
7
// (0 << ISCx1) | (1 << ISCx0) Jede Änderung am Pin löst den Interrupt aus
8
// (1 << ISCx1) | (0 << ISCx0) Eine fallende Flanke löst den Interrupt aus
9
// (1 << ISCx1) | (1 << ISCx0) Eine steigende Flanke löst den Interrupt aus
10
EICRA|=(1<<ISC00)|(0<<ISC01);// Fallende Flanke von SQW nehmen!
11
EIMSK|=(1<<INT0);
12
sei();
13
}
Zeig mal deine komplette Schaltung! Was hast du als Pullup an SQW dran?
Toggel doch mal einen Port-Pin in der ISR, und hänge ein Scope an SQW
vom DS3231 sowie an diesen Toggle-Pin. Trigger auf SQW.
Dann siehst du recht schnell, ob der µC jeden Interrupt bearbeitet.
Achja, nur der Vollständigkeit halber: Keramische Abblock-Kondensatoren
sind doch wohl hoffentlich an jedem VCC/GND Pin-Paar direkt an jedem IC
verbaut?
Der DS3231 braucht unbedingt einen guten Abblock-C, laut Datenblatt von
100n bis 1µ. Fehlt der, geht die Uhr komplett falsch.
Thorsten S. schrieb:> Stefan S. schrieb:>> da ich es bislang noch nicht hinbekommen habe, die Kommunikation>> zwischen Atmega328P(später Attiny85) und DS3231 zu realisieren,>> habe ich den SQW des DS3231 auf 1024Hz eingestellt über die Register RS1>> und RS2.> Den Satz verstehe ich jetzt nicht wirklich.> Um den Ausgang SQW auf 1024Hz einzustellen, muß die I2C-Kommunikation> zwischen dem µC und dem DS3231 doch funktionieren! Was hast du dann> nicht hinbekommen?
Habe noch einen anderen Sketch vom Arduino gehabt, mit dem ich die SQW
Frequenz einstellen kann.
>> Was mir aufgefallen ist, dass die Zeit um 2min/30min nachgeht.> Da liegt ein generelles Problem vor...> Sperrst du im Hauptprogramm an irgendeiner Stelle mal die Interrupts für> mehr als maximal ein paar Hundert µs?> Das wäre im Zweifelsfalle tödlich, weil du dann Interrupts verpaßt, was> naturgemäß zu einem Nachgehen deiner Interrupt-Uhr führt.
Im Einsatz kommt die LightWeight WS2812B Libary. Die hat soweit dieses
Verhalten :(
> Achja: Wenn du eh nur an Sekunden interessiert bist, warum setzt du dann> den SQW Ausgang nicht auf 1Hz auf (RS1 = 0, RS2 = 0) und sparst dir 1023> Interrupts pro Sekunde?
Ich brauche die 1024 Hz nicht, jedoch benötige ich diese, um ein 64Hz
Signal zu erzeugen. Soll heißen die Leds werden alle 64 bzw 32mal pro
Sekunde aktualisiert.
Die Zeit zwischen jeder Sekunde zu nehmen und daraus die 64 Hz zu bilden
brachte mir immer mal wieder Probleme, dass der Fade nicht ganz sauber
verlief.
> Davon abgesehen würde ich für die Uhrzeit einfach die Echtzeit-Register> des DS3231 auslesen, die muß man Dank der Pufferbatterie auch nicht nach> jedem Power Up neu stellen, dafür ist so'ne RTC schließlich da! ;-)
Ja, ist der Sinn von dem IC ;) Wenns gehen würde. Problem ist aber dann
die Synczeit, das in dme Moment die Uhr falsch bzw. Leds falsch
angezeigt werden und es zu einem Sprung kommt.
>> Im Datenblatt habe ich keine Infos gefunden, ob der Ausgang des RTCs>> ebenfalls Temperaturkompensiert ist.> Selbstverständlich ist er das, geht auch aus dem Blockschaltbild im> Datenblatt (S. 8) hervor. Alles andere wäre ja auch sinnbefreit.
Ja, das war die Frage. Das Schaltbild habe ich gesehen, wusste aber
nicht,
ob die Control Logic/Divider diesen dann auch entsprechend anpasst. Nun
gut, jetzt weiß ichs.
>> Der DS3231 nutzt auch die Vcc von 5V.> 5V-Betrieb ist laut Datenblatt zwar noch zulässig, aber der DS3231 ist> für nominell 3V3 ausgelegt.
Habe derzeit keine Spannungsversorgung mit 3V3 auf dem Board, bzw.
keinen passenden Spannungsregler. Ein großen Stepdown-Regler wollte ich
dafür jetzt nicht umbedingt verwenden. Später werde ich schauen, wie ich
das löse.
Vermutlich ein kleinen Linearregler und den Attiny/Atmega mit 3V3 und
8MHz betrieben sowie einen Pegelwandler (Transistor) an einem Ausgang
für 5V DATA Signal der WS2812B
> Der SQW-Ausgang des DS3231 ist Open Drain. Daher die fallende Flanke> nehmen, dann paßt die Flankensteilheit auf jeden Fall.>>
1
>voidtime_init(void)
2
>{
3
>DDRD&=~(1<<DDD2);
4
>//PORTD |= (1 << PORTD2); // Pull-Up aktivieren
5
>
6
>// (0 << ISCx1) | (0 << ISCx0) LOW-Level am Pin löst den Interrupt
7
>aus
8
>// (0 << ISCx1) | (1 << ISCx0) Jede Änderung am Pin löst den
9
>Interruptaus
10
>// (1 << ISCx1) | (0 << ISCx0) Eine fallende Flanke löst den
11
>Interruptaus
12
>// (1 << ISCx1) | (1 << ISCx0) Eine steigende Flanke löst den
13
>Interruptaus
14
>EICRA|=(1<<ISC00)|(0<<ISC01);// Fallende Flanke von SQW
15
>nehmen!
16
>EIMSK|=(1<<INT0);
17
>sei();
18
>}
>> Zeig mal deine komplette Schaltung! Was hast du als Pullup an SQW dran?
Schaltbild müsste ich Eagle anfertigen, jedoch lohnt sichs vielleicht
kaum, weil derzeit wenig extern Beschaltet ist.
Ich habe am SQW einen 10k Pull-Up gesetzt.
> Toggel doch mal einen Port-Pin in der ISR, und hänge ein Scope an SQW> vom DS3231 sowie an diesen Toggle-Pin. Trigger auf SQW.> Dann siehst du recht schnell, ob der µC jeden Interrupt bearbeitet.
Ein Osziloskop fehlt mir ;(, steht noch auf der Nice-To-Have-Liste.
Wobei die Interupts dauerhaft gezählt wurden, wenn ich die WS2812B nicht
eingebunden hab.
> Achja, nur der Vollständigkeit halber: Keramische Abblock-Kondensatoren> sind doch wohl hoffentlich an jedem VCC/GND Pin-Paar direkt an jedem IC> verbaut?> Der DS3231 braucht unbedingt einen guten Abblock-C, laut Datenblatt von> 100n bis 1µ. Fehlt der, geht die Uhr komplett falsch.
Am DS3231 hängt wie auch beim Atmega pro Vcc/Gnd ein Kerko mit 0,1µF
// (1 << ISCx1) | (0 << ISCx0) Eine fallende Flanke löst den Interrupt aus
2
// (1 << ISCx1) | (1 << ISCx0) Eine steigende Flanke löst den Interrupt aus
3
EICRA |= (1 << ISC01) | (0 << ISC00);
An der Auswertung, wie erwartet, ändert es bei mir nichts. Die Interrupt
Lösung hat ja auch bereits als steigende Flanke genauso funktioniert.
Das Problem bei mir ist die WS2812B Ansteuerung. Die Ansteuerung der
WS2812B erfolgt sobald meine ISR 16mal durchlaufen ist.
1
#define FREQ_64 freq_1024/16
1
while (1)
2
{
3
static int last_minute;
4
if(minute != last_minute)
5
{
6
last_minute = minute;
7
printf("%02d:%02d:%02d\n", hour, minute, second);
8
}
9
10
static int last_freq_64;
11
if(FREQ_64 != last_freq_64)
12
{
13
last_freq_64 = FREQ_64;
14
leds_clock3(hour12, minute, second, FREQ_64);
15
}
16
}
Würde es eventuell Sinn machen, einen zB. Attiny85 (wäre der kleinste
den ich daheim liegen hab) zu nutzen, um die Interupts zu zählen und nur
alle 16Takte einen Ausgang zu toggeln, sodass der eigentliche
Attiny/Atmega nur noch 64 mal in der Sekunde in den Interupt geht? Das
beschreiben der Leds erfolgt ja zeitnah nach der ISR. Ansonsten ist da
nichts blockierendes im Code, der der die loop verzögert.
Jedoch ist die Zeit von ~1ms scheinbar nicht ausreichend, um den Led
Strip (60Leds) zu beschreiben. Was für Optionen stehen mir hier zur
Verfügung? Gibt es einfache Bausteine,