Datum:
Angehängte Dateien:Hallo, ich bin gerade dabei in die C-Programmierung für Mikrocontroller einzusteigen und habe mir als erstes Projekt eine DCF77-Uhr ausgewählt. Sicherlich ist mein Programmcode noch nicht so ausgefeilt wie von erfahrenen Programmierern, ich könnte mir aber vorstellen das andere Einsteiger/Anfänger durch meinen primitiven Code durchsteigen :-) Meine bisherigen Programmierkenntnisse beschränken sich auf etwas PIC-Assembler (vor ~3 Jahren in der Ausbildung) und einem Semester Java, also bitte nicht gleich steinigen wenn da ein paar grobe Schnitzer drin sind. Also jetzt ein paar Infos zu dem was ich fabriziert habe: Programmiert im AVR Studio (mit AVR-GCC) Hardware: STK500 ATmega16 16MHz Quarz 20x4 Zeichen LCD (HD44780 kompatibel) DCF77-Empfangsmodul von Conrad (641138) (PullUp-Widerstand 10k zwischen Anschluß 2 und 4) Die LCD-Ansteuerung habe ich aus dem Tutorial übernommen, vielen Dank an den Autor an dieser Stelle Ansteuerung Hardware/Software entsprechend dem AVR-GCC-Tutorial: http://www.mikrocontroller.net/articles/AVR-GCC-Tu... Nun zu meinem Programm Abtastung erfolgt mit einem 1ms Trigger. Die Synchronisation zum DCF-Signal erfolgt durch einen High-Pegel zwischen 1750-1950ms, das ist das 59Bit einer Minute, welches nicht abgesenkt wird. Danach beginnt die Auswertung der Datenbits, dabei habe ich folgende Werte angenommen Pegel-Absenkung von 60-140ms entspricht einer logischen 0 Pegel-Absenkung von 160-240ms entspricht einer logischen 1 keine Absenkung für 1750-1950ms entspricht dem Beginn einer neuen Minute Abbruchkriterien (bzw. Start einer neuen Synchronisation) ...wenn mehr oder weniger als 59Bits pro Minute erkannt werden. ...Pegel-Zeiten die außerhalb der oben genannten Toleranzen (für 0/1/neue Minute) liegen ...Überprüfung der Minuten-, Stunden- und Datums-Parität Über einen externen Quarz wird ein 1ms Takt erzeugt, damit läuft die Uhrzeit/das Datum auch weiter, wenn keine korrekten DCF-Daten empfangen werden. Abgleich zwischen der internen Uhr und den DCF-Daten bei korrektem Empfang (hier plane ich noch eine Plausibilitätsüberprüfung einzubauen) Auf das LCD werden folgende Daten ausgegeben: Wochentag (Mo/Di/Mi/Do/Fr/Sa/So) Datum (dd.mm.yyyy) (Meine Lösung für die Jahreszahl ist noch etwas rudimentär, ob in 90 Jahren noch jemand DCF77-Uhren benutzt? ;-) ) Zeitzone (MEZ/MESZ) Zeit (hh:mm:ss) Status der Synchronisation (?/!) ToDo's: Behandlung der Schaltsekunde (DCF-Auswertung "case 19") Behandlung der angekündigten Zeitumstellung (DCF-Auswertung "case 16") Anpassung für die zweistelligen Jahreszahlen Geplante Erweiterungen: Grafik-LCD (320x240) damit ich später noch andere Dinge anzeigen kann Zum Einstieg war das bisher eine tolle Sache und ich habe viel über die Eigenheiten/das Eigenleben der Hardware und Software gelernt, mal schauen wie es weitergeht. vg Johannes Edit: Eigentlich sollte der Anhang nur einmal dran, ist aber beides das Gleiche.
Datum:
Johannes M. schrieb: >... > Edit: Eigentlich sollte der Anhang nur einmal dran, ist aber beides das > Gleiche. Habe einen der Anhänge gelöscht.
Datum:
Ich zähle mal die Sekunden bis der Herr Dannegger seinen Code hier verlinkt.
Datum:
Angehängte Dateien:Martin Thomas schrieb:
> Habe einen der Anhänge gelöscht.
Danke
Andere Beispielprogramme die man hier im Forum bzw. im Netz finden kann
sind mir natürlich auch bekannt. Aber es macht doch viel mehr Spaß etwas
selbst zu machen und dabei dazuzulernen.
Im Anhang noch ein Foto mit der Darstellung auf dem LCD.
Datum:
Marius S. schrieb: > Ich zähle mal die Sekunden bis der Herr Dannegger seinen Code hier > verlinkt. Immerhin hat er die Abtastung in einem Timer-Interrupt (1ms Trigger) gemacht und nicht per Interrupt. Das ist schon löblich!
Datum:
Angehängte Dateien:Mir sind gerade eben beim Datumswechsel ein paar Fehler aufgefallen. Fälschlicherweise hatte ich beim Datumsübergang schon beim 28.02. direkt auf den nächsten Monat umgeschaltet und der Monat begann bei Tag 0. Sollte nun behoben sein, noch nicht schön aber es funktioniert :)
Datum:
Hallo, verstehe deine Routine "void dcf_sync(void)" nicht ganz. Habe sie versucht im Simulator zu testen aber selbst bei dem Versuch If(counter_high>=2) laüft der Simulator nicht weiter.(counter_high wurde auf 2 hochgezaehlt). Liegt das am Simulator oder wie kann das sein? Gruss Bernd
Datum:
Hi, im Simulator habe ich das noch nicht getestet, aber ich kann ja mal versuchen die Anweisungen in der "void dcf_sync(void)" etwas genauer zu beschreiben. Als Randbedingung noch zu beachten: die Variable counter_high wird in der ISR erhöht, also alle 1ms um +1.
if(!(dataPC & (1<<PINC1))) //ist am Eingangspin ein Low-Pegel wird dieser Zweig ausgeführt { if(counter_high>=1750 && counter_high<=1950) //ist der Wert der Variable counter_high zwischen 1750 und 1950 so kennzeichnet dies den Anfang einer neuen Minute (alle Counter, das DCF-Datum/Uhrzeit werden zurückgesetzt und es geht zurück in den normalen Programmablauf) { //LCD-Ausgabe: Synchronisation erfolgreich set_cursor(19,1); lcd_data('!'); counter_reset(); //setzt sowohl counter_high, counter_low und die bit_number auf 0 dcf_date_reset(); //setzt nach erfolgreicher Synchronisation den Datumswert auf 0 dcf_time_reset(); //setzt nach erfolgreicher Synchronisation den Uhrezeitwert auf 0 } else //ist der Wert counter_high kleiner als 1750 oder größer als 1950, liegt entweder ein Übertragungsfehler des DCF-Moduls vor oder es ist der ganz normale High-Pegel zwischen den Sekunden-Absenkungen. { counter_high=0; //hier wird wieder der counter_high zurückgesetzt, sonst ist bei mehrmaligem durchlauf der Wert immer >1950. dcf_sync(); } } else //ist am Eingangspin ein High-Pegel wird wieder dcf_sync() aufgerufen. Es werden keine Counter zurückgesetzt. { dcf_sync(); } |
Ich hoffe das hat mehr geholfen als verwirrt, bin ja selbst noch am lernen. :)
Datum:
Hallo, ja, so hatte ich das auch verstanden. Problem schein zu sein, das ich A) einen anderen PIN nehmen, und B) den gesamten Port im Interupt einlesen. Die und Verknüpfung klappt dann wohl nicht mit dem (1<<PINC5). Also muss ich auch beim einlesen nur das eine BIT einlesen. Mal sehen ob das klappt. Danke Bernd
Datum:
Angehängte Dateien:Guten morgen... Habe den Code übernommen und versucht ihn für nen Atmega 2560 anzupassen. Bekomme auch keine Fehlermeldungen mehr raus. Die Anzeige auf dem Display passt auch, nur leider krieg ich das DCF-Signal nich rein. Hab schon alles mögliche ausprobiert... Vielleicht ist ja doch noch nen Fehler im Code? Danke im Vorraus...
Datum:
Hallo, habe mein Problem erkannt. Da ich den Code in ein extra File (clock.c) gespeichert habe und auch die Variablen in clock.h muss ich wohl die counter_xx und die millisecond mit "volatile" versehen, dann geht es auch im Simulator. Vorher wurde der Befehl if(counter_high<=xxx && counter_high>=xxx) nicht im Simulator ausgeführt.. Mein Datenlogger läuft jetzt (anscheinnend?!). Bernd
Datum:
Kann es vielleicht sein das ich bei der Timer init nen fehler gemacht habe?
Datum:
Hi, habe mal über die Timer Einstellungen geschaut (mit dem 2560 habe ich noch nicht gearbeitet), die sehen auf den ersten Blick aber richtig aus. Ansonsten würden mir spontan folgende Fehlerquellen einfallen: Läuft der mega2560 mit 16 MHz? (Fuses) Welches DCF-Modul verwendest du? An PinC1 Angeschlossen? Beim Conrad Modul habe ich den invertierten DCF-Ausgang mit einem Pull-Up Widerstand verwendet. Hast du schon mal direkt die Signale am DCF-Modul angeschaut? Ist der Empfang i.O.?
Datum:
Hi... Erstmal danke das du mir helfen möchtest. Also die Taktfrequenz des mega2560 ist auch 16MHz, wie beim mega 16. Kann es sein das ich doch was an den fuses machen muss? Benutze auch das DCF-Modul von Conrad, hab aber die Pullups wie im Datenblatt gezeigt angeschlossen. (d.h. an den Klemmen 3 und 4 jeweils einen 10k, die Enden kurzgeschlossen und dann von da ne Brücke auf Klemme 2) Du hast nur am negierten Ausgang nen Pullup benutzt? Den Empfang hab ich mit nem Multimeter überprüft. (5V angelegt und die Ausgänge gemessen. Da hab ich ne Spannung gemessen die zwischen 0 und 5V geschwankt hat) Kann man das überhaupt so machen? Gruss Fabian
Datum:
Angehängte Dateien:Habe mal ein Foto gemacht und beschriftet. Die Pegel mit einem Multimeter zu messen ist natürlich etwas "ungenau", beim DCF-Signal kommt es ja hauptsächlich auf die Zeiten zwischen den Pegeländerungen an. Dazu habe ich zwei Bilder (im pdf) vom Oszi angehängt, so müsste es in etwa aussehen. Auf der 1ten Seite die Abbildung einer kompletten Minute, auf der 2ten Seite noch mal als Detail die "fehlende" Absenkung für die Kennzeichnung einer neuen Minute und die Unterscheidung zwischen der logischen 0 und 1 ist auch gut zu erkennen.
Datum:
Hi... Vielen Dank erstmal für die Bilder. Das die Sache mit dem Multimeter ziemlich ungenau ist war mir ja klar, hab aber leider kein oszi zur Verfügung. So konnte ich wenigstens sehn ob überhaupt was rauskommt. Also ich hab jetzt das DCF so beschaltet wie du es auch gemacht hast. Hab den Ausgang des DCF`s auch an PC1 gehängt. In der "main" von "dcf-clock.c" definierst du PB0 als Ausgang. Mir ist leider nich ganz klar wofür genau. Bitte nich auslachen, steh noch ziemlich am Anfang. Zu meiner Hardware: Benutze das MK3 von myAVR, da sollte doch eigentlich alles notwendige drauf sein. (Quartz für den Takt des Timers, usw.) Gruss Fabian
Datum:
PB0 ist noch eine "Leiche" von meinem Testaufbau, hat keine Funktion. Die Zeilen können beide gelöscht werden:
DDRB |= (1<<PB0); //PB0 Ausgang (1) PORTB &= ~(1<<PB0); //PB0 auf low gesetzt (0) |
Ich bin auch gerade dabei den Programm-Code zu überarbeiten, das wird sich aber aus Zeitgründen noch ein paar Tage/Wochen hinziehen. Der aktuelle Stand hier im Forum sollte aber ohne Probleme laufen.
Datum:
Vielen dank für deine Hilfe... Wünsch dir weiterhin viel Erfolg und Spass bei deinem Projekt. Werds mal beobachten Gruss Fabian
Datum:
hallo johannes, gute entwicklung die du gemacht hast. zu meiner frage: ich will dieses projekt auch umsetzen. allerdings ohne dem empfangsmodul. Anstatt dem empfangsmodul, kommt mein dcf signal direkt von einer rs232 schnittstelle. sollte kein unterschied sein, oder? mfg HansDampf
Datum:
Simon K. schrieb: > Immerhin hat er die Abtastung in einem Timer-Interrupt (1ms Trigger) > gemacht und nicht per Interrupt. > Das ist schon löblich! Da man ja immer gerne was dazulernen will: Ich dachte eigentlich, das die Abtastung per Interrupt der Normalfall wäre. Was bringt die Abtastung im Timer-Interrupt denn für Vorteile?
Datum:
so jetzt hab ich hier ein Atmega8 + 2x16 LCD und was muss ich am code ändern (von 16bit auf 8bit). cya
Datum:
Nabend, HansDampf schrieb: > zu meiner frage: > ich will dieses projekt auch umsetzen. allerdings ohne dem > empfangsmodul. Anstatt dem empfangsmodul, kommt mein dcf signal direkt > von einer rs232 schnittstelle. sollte kein unterschied sein, oder? doch, du brauchst einen Pegelwandler. Die nächste Frage ist ob das Empfangsmodul die Uhrzeit als String übergibt, oder an einer Handshakeleitung rumzappelt. Hanna schrieb: > Da man ja immer gerne was dazulernen will: > Ich dachte eigentlich, das die Abtastung per Interrupt der Normalfall > wäre. Was bringt die Abtastung im Timer-Interrupt denn für Vorteile? Du kannst jeden x-beliebigen Pin nehmen. Voraussetzung ist natürlich das dein Programm diesen rechtzeitig prüfen (Pollen) kann. Ein delay_ms(500) irgendwo in der Hauptschleife geht dann nicht mehr. MfG
Datum:
Sauger schrieb: > Voraussetzung ist natürlich das > dein Programm diesen rechtzeitig prüfen (Pollen) kann. Ein delay_ms(500) > irgendwo in der Hauptschleife geht dann nicht mehr. ist natürlich mist, habe Timer-Interrupt überlesen MfG
Datum:
Hi, ich habe hier ebenfalls (wie ein paar Beiträge zuvor) einen ATMega 8. Ich verwende einen externen Quarz mit 8MHz. Die Frequenz habe ich umgestellt sowie ein paar weiter Änderungen vorgenommen, allerdings wirft der Timing-Absatz der Hauptmethode 4 Errors. Ist das irgendwie ATMega16 spezifisch? Kann ich mir kaum vorstellen:
../dcf-clock.c:566: error: 'TCCR0A' undeclared (first use in this function) ../dcf-clock.c:566: error: (Each undeclared identifier is reported only once ../dcf-clock.c:566: error: for each function it appears in.) ../dcf-clock.c:566: error: 'WGM01' undeclared (first use in this function) ../dcf-clock.c:567: error: 'OCR0A' undeclared (first use in this function) ../dcf-clock.c:568: error: 'TIMSK0' undeclared (first use in this function) ../dcf-clock.c:568: error: 'OCIE0A' undeclared (first use in this function) |
Gruß, Julian
Datum:
Hallo!! Wer kann mir den Schritt für Schritt erklären wie man dieses Projekt mit Avr Studio umsetzt. Bin Anfänger, habe das Tutorial durch, bekommer aber beim Build ständig Fehler, habe bisher nur leds zum blinken und an-aus gebracht.. Ich weiss nicht genau was in AVR Studio geaddet werden soll. Habe dcg-clock.c drin, lcd-routines.c und lcd routines.h. Habe das Evaluationsboard von pollin mit LCD, benutze zum Übertragen Ponyprog. Suche nach Problemlösung hier in den Foren seit über 6 std ohne Erfolg. /*Fehler*/ lcd-routines.o:D:\Dokumente und Einstellungen\Bandit_1200\Eigene Dateien\Downloads\DCF-Clock_2010-02-28\DCF-Clock\default/../lcd-routines.c:134: first defined here make: *** [dcf-clock.elf] Error 1 Build failed with 1 errors and 4 warnings... Bitte keine Links zu anderen Freds, habe sie alle durch. Wer hilft mir? BITTE!!!
Datum:
Hi, habe gerade mal getestet mit den 3 genannten Dateien das Projekt aufzusetzen, hat bei mir funktioniert. Ich schreibe mal mein Vorgehen auf, vielleicht hilft dir das: Im AVR Studio: - New Project -> AVR GCC -> Project name: dcf-clock - AVR Simulator -> Device ATmega16 - Bei den Source Files die angelegte Datei dcf-clock.c aus dem Projekt entfernen - Nun die 3 Dateien (dcf-clock.c, lcd-routines.c und lcd-routines.h) im Explorer in das Projektverzeichnis kopieren (hier liegt schon "dcf-clock.aps") - Wieder im AVR Studio die beiden c-Dateien bei den Source Files adden und die h-Datei bei den Header Files - Menü Projekt -> Configuration Options -> Frequency: 16000000 Hz -> OK - F7 drücken -> fertig
Datum:
Hallo Julian Kannst du mal den Code für der Mega8 posten ? Gruss und Danke Bernd
Datum:
Hallo Johannes, erst mal vielendank für des Code. Ich versuche gerade ihn zu verstehen und hätte eine Frage. Wie springst du aus der Routine dcf_sync()heraus dcf_sync() wird ja wieder von sich selbst aufgerufen? Danke Dieter
Datum:
Dieter Hagl schrieb: > Hallo Johannes, > > erst mal vielendank für des Code. > Ich versuche gerade ihn zu verstehen und hätte eine Frage. > Wie springst du aus der Routine dcf_sync()heraus dcf_sync() wird ja > wieder von sich selbst aufgerufen? > > Danke > Dieter Hallo, im Falle das die Bedingung der if-Anweisung in der dcf_sync() zutrifft, also "Synchronisation erfolgreich", ist das Ende der Funktion erreicht und es geht zurück zur Adresse, die auf dem Stack liegt. Also zur while-Schleife in main. Gruß Johannes


