PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitgeber



Zotti
16.10.2009, 23:13
Hallo Leute,
ich baue eine Zeitmessung für Rundenzeiten.
Ich hänge gerade an dem Timesignal. Als ich gestartet bin war das noch weit weg, aber so langsam muss ich mich damit auseinander setzten.

Kurz zu meinem Projekt:
Ein Atmel soll einen Zeitstempel generieren und pro Loop den Zeitstempel via eines ISM Modules senden. Die Antenne ist vergraben, so habe ich nur eine geringe Reichweite. Wenn ein Teilnehmer über die Antenne fährt bekommt er die Timestamps gesendet. Der Atmel speichert den ersten und den letzten.
So weiss ich genau wo die Mitte war. Ein Stück weiter sende ich dem Atmel eine Kennung worauf dieser unter seiner Adresse antwortet und die zwei Zeitstempel zurückschickt. Theoretisch funktioniert das schon, nur schaffe ich es nicht ein Zeitsignal zu bauen. Ursprünglich wollte ich einen PC dazu verwenden, un da gibt es ja in jeder Sprache die möglichkeit die Zeit in millisekunden seit 1970 auszugeben.

Hat mir hier jemand einen Tip. Der berühmte Wink mit dem Zaunpfahl fehlt. Mir fehlt der richtige Ansatz mit welchem Atmel ich ein Timestamp oder so was ähnliches generieren kann.

Ich bin für jeden Hinweis dankbar.

Viele Grüße

Olli

KingTobi
16.10.2009, 23:18
Du könntest eine Real Time Clock anschliessen. Die muss einmal eingestellt werden und läuft dann unabhängig vom µC und wenn du ne Batterie anschliesst, läuft sie auch ohne externe Spannungsquelle weiter. Die Zeit kannst du dann per I2C auf deinen µC holen.

Ich hab das mal mit einer DS1307 gemacht.

for_ro
17.10.2009, 00:11
Hallo,
ich habe mir dazu einen Timer gemacht, der im 1/1000s Takt überläuft.
So kannst du mit ms-Auflösung arbeiten.
Der DS1307 kann ja nur Sekunden zählen und ich sehe da keine einfache Möglichkeit, ihm ms beizubringen. Ich kenne auch sonst keine RTC die das kann.
Bei deiner Anwendung wird aber eh nicht das Problem sein, über Tage mit geringer Abweichung die Zeit zu bekommen, sondern eher, relativ kurze Zeiträume im Sekunden- oder Minutenbereich.

KingTobi
17.10.2009, 01:27
@for_ro
Dann guck dir mal die PCF8583 an.

oberallgeier
17.10.2009, 10:26
Hi Zotti,


... Zeitmessung für Rundenzeiten ... Atmel soll einen Zeitstempel generieren ...
Mir fehlt der richtige Ansatz mit welchem Atmel ich ein Timestamp oder so was ähnliches generieren kann ...Die zweite Frage zuerst: Das geht praktisch mit jedem Atmel. Ich habe eine Lösung, die ist noch von meiner Anfangszeit als C-Neuling geprägt - sprich: es geht sicher eleganter. Aber so geht es - mit der Genauigkeit von 50 µs bei meinem 20 MHz-Quarz. Der Timer wird wie folgt initialisiert (für einen anderen Atmel und/oder einen anderen Quarz brauchst Du andere Registernamen, und sicher auch andere Parameter):

/* ================================================== ============================ */
/* === Initialisierung fuer Timer2 mega328 ===================================== */
void TC2TMR_init(void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 124; // Preset 125 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ================================================== ============================ */
In einer ISR wird der Interrupt gezählt und bis zu einem Sekundensignal ausgewertet, denn 20000 mal 50 µs sind eine Sekunde:

/* ================================================== ============================ */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen ...... */
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < Izthrznt) //Interrupt-Timer (Zeithorizont derzeit = 20 000)
{
Izeit_1 ++; // Jede eine Sekunde wird 20000 erreicht
} // und Izeit_1 bleibt in der uint16-Grenze
else
{
Izeit_1 = 1; // ansonsten: Rückstellen 50µs-Zähler
I_sec_1 ++; // Sekundencounter, geht bis ca. neun Stunden
if (I_sec_1 > 32000) // Sekundenzähler-Maximum 9 Std. abprüfen
I_sec_1 = 1;
}
}
/* ================================================== ============================ */
Nun kannst Du in beliebigen Routinen die Variablen Izeit_1 - also die Anzahl der 50 µsec innerhalb einer Sekunde - und I_sec_1 - das ist der Sekundenzähler, der rund 9 Stunden bis zum Wiederstart läuft - auslesen. Diese Variablen sind volatile uint16 ! ! ! Das Auslesen solltest Du daher innerhalb einer sei();/cli();-Schranke machen, damit Dir die Timer-ISR nicht während des Auslesens die Werte verändert - DAS wäre sehr schlecht.

Aus dem 50µs-Zähler kannst Du im main bzw. einer geeigneten Routine den Sekundenbruchteil errechnen, die Sekunde bekommst Du ja frei Haus. Bei Rundenzeiten über 9 Stunden wäre ein Überlauf abzufangen. Du könntest natürlich auch einen Minuten- und/oder Stundenzähler bauen. Da der Interrupt nur alle Sekunden abläuft, wäre das praktischerweise ausserhalb der Timer-ISR zu erledigen. Aber wer braucht das schon - mit uint16 kann der controller gut umgehen.

Hilft Dir das?

ZottiFX
18.10.2009, 10:21
Hallo Leute,

vielen Dank für die vielen genialen Impulse!!
Muss mal ein paar Versuche starten.
Den PCF8583 kenne ich noch nicht, werde mich aber die Tage einmal damit auseinander setzten, zumal ich sowie so einen externen Zeitgeber wo anderst brauche.

An oberallgeier:
Der Ansatz wäre ideal, nur muss ich mich dazu erst mit C und Compiler auseinander setzten.
Für die Zukunft wäre das vermutlich sowieso besser, denn ich betreibe hier nur einen Windowsrechner für Bascom.

Vielen danke nochmal

Olli

Dirk
18.10.2009, 11:22
Den PCF8583 kenne ich noch nicht, werde mich aber die Tage einmal damit auseinander setzten,...
Hier ...
https://www.roboternetz.de/phpBB2/viewtopic.php?t=34467
... befindet sich in dem Zip auch ein Mini-Schaltplan und ein Prog für den RP6.

Gruß Dirk

Besserwessi
18.10.2009, 17:13
Die chip-internen Timer kann man natürlich auch unter BASCOM nutzen. Man kann das auch einfacher machen:
Der 16 Bit Timer läuft mit einem eher großen Vorteiler (z.B. 1024) einfach durch. Wenn die 16 Bit nicht reichen, kann man noch die Überläufe zählen. Aus dem Zähler kann man dann direkt die Zeit auslesen. Man muß dann nur noch die Zeit in den eher krummen Einheiten des Timers (z.B. (1024/16000) ms) umrechnen in Sekunden. Da der Timer mit mehr Auflösung laufen kann, als man eigentlich braucht, sind die Rundungsfehler da eigentlich kein Problem mehr, denn dafür hat man kaum noch Quantisierungsfehler.

Eine externe Echtzeituhr, ist vor allem Sinnvoll, wenn man eine Zeitmessung über lange Zeiten machen will, und der µC zwischendurch auch ausgeschaltet werden soll.