Mengenlehre - Uhr oder auch Berlin - Uhr

gerd51

Mitglied
18. Jan. 2013
43
0
6
Sprachen
  1. BascomAVR
Hallo Forumsfamilie!

Ich bin dabei eine Mengenlehreuhr zu bauen. Das Teil funktioniert auch (fast). Zwei Dinge bringen mich zur Verzweifelung:
1. Ich habe den 1HZ-Takt der DS3231 aktiviert. Dadurch zappelt die Sekunden LED. Allerdings nur solange, bis die RTC durch das DCF-Signal syncronisiert wird. Im selben Moment ist Ruhe im Schacht.
2. Die RTC wird zu Beginn ausgelesen und angezeigt. Allerdings nicht die Veräderungen während der Suche nach dem DCF-Signal. Ist klar, da die Anzeigeanweisung nicht im Hauptprogramm erfolgt. Mach ich das aber, funktioniert zwar die Anzeige, aber das Ganze scheint jetzt so zeitkritisch zu sein, dass die Suche nach dem DCF-Signal nur sporadisch erfolgt. Hat jemand eine Idee.
Gruß Gerd
Hier der unaufgeräumte Entwicklungs-Code


CodeBox BascomAVR


$regfile = "m16def.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 40

$lib "i2c_twi.lbx"  ' we do not use software emulated I2C but the TWI
$lib "glcdKS108.lbx"
$lib "mcsbyte.lbx"  ' for smaller code
$lib "ds1307clock.lib"  ' modified lib


Dim Min_Anzeige As Byte , 5_min_Anzeige As Byte , Std_Anzeige As Byte , 5_Std_Anzeige As Byte , Sec_Anzeige As Byte, Neue_sekunde as bit

' ----- DCF77 -----
Dim Dcf77_hour As Byte  ' Globale Stundenvariable
Dim Dcf77_min As Byte  ' Globale Minutenvariable
Dim Dcf77_sec As Byte  ' Globale Sekundenvariable
Dim Dcf77_weekday As Byte  ' Globaler Wochentag
Dim Dcf77_day As Byte  ' Globale Tagvariable
Dim Dcf77_month As Byte  ' Globale Monatsvariable
Dim Dcf77_year As Byte  ' Globale Jahresvariable


Const Rtc_address_write = &B11010000  ' Adresse des DS3231 = &HD0 (schreiben)
Const Rtc_address_read = &B11010001  ' Adresse des DS3231 = &HD1 (lesen)
Const Rtc_address_seconds = &H00
Const Rtc_address_minutes = &H01
Const Rtc_address_hours = &H02
Const Rtc_address_day = &H03
Const Rtc_address_date = &H04
Const Rtc_address_month = &H05
Const Rtc_address_year = &H06
Const Rtc_address_control = &H07



Dim Temp_byte_1 As Byte  ' Temporäre Byte Variable
Dim Temp_integer_1 As Integer  ' Temporäre Integer Variable




'
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Ds3231
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Einstellen der TWI (I2C) Schnittstelle in BASCOM
Config Sda = Portc.1
Config Scl = Portc.0
Twcr = &B00000100
Config Portc.2 = Output  'Fuer Signaltest-LED
Signal_kontroll_led Alias Portc.2
config portc.3=Output
Signal_empfangs_LED alias Portc.3
config portc.4=Output
Sekundentakt alias portc.4
Config Portc.0 = Output
Config Portc.1 = Output
config PORTA =OUTPUT
config PORTD =OUTPUT
config PORTB=OUTPUT




Config Dcf77 = PinD.7 , Timer = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Timer1sec = 1 , Debug = 1 , Gosub = Sectic
Config Date = Dmy , Separator = .  ' Datumsformat einstellen

enable interrupts

Gosub Rtc_set_softclock  'RTC auslesen und Softclock stellen
Gosub anzeige

I2cstart
I2cwbyte Rtc_address_write  ' 1Hz Signal der DS3231 aktivieren
I2cstart
i2cwbyte &H0E
i2cwbyte &H80
I2cstop
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Hauptprogramm
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Do

  Signal_kontroll_led = Dcf_status.0  'Als Test: Blinkt bei Empfang

  If dcf_status.7 = 1  Then
  Signal_empfangs_LED=1
  Gosub Rtc_set_rtc_clock
  Gosub anzeige
  Else
  Signal_empfangs_LED=0  'DCF nicht o.k.
  End If


Loop

End

'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Rtc_set_softclock:
  ' RTC DS3231 auslesen
  I2cstart  ' START-Sequenz senden
  I2cwbyte Rtc_address_write  ' Daten schreiben initiieren
  I2cwbyte Rtc_address_seconds  ' Adresse übertragen = &H00
  I2cstart  ' START-Sequenz erneut senden
  I2cwbyte Rtc_address_read  ' Daten lesen initiieren
  I2crbyte Dcf77_sec , Ack  ' Byte 1 lesen
  I2crbyte Dcf77_min , Ack  ' Byte 2 lesen
  I2crbyte Dcf77_hour , Ack  ' Byte 3 lesen
  I2crbyte Dcf77_weekday , Ack  ' Byte 4 lesen
  I2crbyte Dcf77_day , Ack  ' Byte 5 lesen
  I2crbyte Dcf77_month , Ack  ' Byte 6 lesen
  I2crbyte Dcf77_year , Nack  ' Byte 7 lesen und fertig (NACK)
  I2cstop  ' STOP-Sequenz
  ' ausgelesene Daten in SoftClock Variablen übernehmen
  _hour = Makedec(dcf77_hour)
  _min = Makedec(dcf77_min)
  _sec = Makedec(dcf77_sec)
  _weekday = Makedec(dcf77_weekday)
  _day = Makedec(dcf77_day)
  _month = Makedec(dcf77_month)
  _year = Makedec(dcf77_year)
Return
'-- End Rtc_set_softclock -----------------------------------------------------


Rtc_set_rtc_clock:
  ' Daten zum Speichern in BCD Format aufbereiten
  Dcf77_hour = Makebcd(_hour)
  Dcf77_min = Makebcd(_min)
  Dcf77_sec = Makebcd(_sec)
  Dcf77_weekday = Makebcd(_weekday)
  Dcf77_day = Makebcd(_day)
  Dcf77_month = Makebcd(_month)
  Dcf77_year = Makebcd(_year)
  ' RTC DS3231 synchronisieren
  I2cstart  ' START-Sequenz senden
  I2cwbyte Rtc_address_write  ' Daten schreiben initiieren
  I2cwbyte Rtc_address_seconds  ' Adresse übertragen = &H00
  I2cwbyte Dcf77_sec  ' Byte 1 übertragen
  I2cwbyte Dcf77_min  ' Byte 2 übertragen
  I2cwbyte Dcf77_hour  ' Byte 3 übertragen
  I2cwbyte Dcf77_weekday  ' Byte 4 übertragen
  I2cwbyte Dcf77_day  ' Byte 5 übertragen
  I2cwbyte Dcf77_month  ' Byte 6 übertragen
  I2cwbyte Dcf77_year  ' Byte 7 übertragen
  I2cstop  ' STOP-Sequenz
  ' STOP-Sequenz
Return
'-- End Rtc_set_rtc_clock ----------------



sectic:
toggle sekundentakt
return


anzeige:
'+++++++++++++++++++++++++++++++++++++++++++++++
'Umrechnung der Uhrzeit in LED-Anzeige
'+++++++++++++++++++++++++++++++++++++++++++++++

  Min_anzeige=_min

  min_anzeige= min_anzeige mod 5

  5_Min_Anzeige = _min/5
  Std_Anzeige=_hour

  std_anzeige = std_anzeige mod 5
  5_Std_Anzeige=_hour/5

'+++++++++++++++++++++++++++++++++++++++++++++++
'LED´s aktivieren
'+++++++++++++++++++++++++++++++++++++++++++++++

  select case Min_Anzeige

  case 0:
  Portd.0=0
  Portd.1=0
  Portd.2=0
  Portd.3=0

  case 1:
  Portd.0=1
  Portd.1=0
  Portd.2=0
  Portd.3=0

  case 2:
  Portd.0=1
  Portd.1=1
  Portd.2=0
  Portd.3=0

  case 3:
  Portd.0=1
  Portd.1=1
  Portd.2=1
  Portd.3=0

  case 4:
  Portd.0=1
  Portd.1=1
  Portd.2=1
  Portd.3=1


  end select

  select case 5_Min_Anzeige


  case 0:
  Portd.4=0
  Portd.5=0
  Portd.6=0
  Portb.0=0
  Portb.1=0
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 1:
  Portd.4=1
  Portd.5=0
  Portd.6=0
  Portb.0=0
  Portb.1=0
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 2:
  Portd.4=1
  Portd.5=1
  Portd.6=0
  Portb.0=0
  Portb.1=0
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 3:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=0
  Portb.1=0
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 4:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=0
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 5:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=0
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0
  case 6:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=0
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0

  case 7:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=1
  Portb.4=0
  Portb.5=0
  Portb.6=0
  Portb.7=0


  case 8:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=1
  Portb.4=1
  Portb.5=0
  Portb.6=0
  Portb.7=0


  case 9:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=1
  Portb.4=1
  Portb.5=1
  Portb.6=0
  Portb.7=0

  case 10:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=1
  Portb.4=1
  Portb.5=1
  Portb.6=1
  Portb.7=0


  case 11:
  Portd.4=1
  Portd.5=1
  Portd.6=1
  Portb.0=1
  Portb.1=1
  Portb.2=1
  Portb.3=1
  Portb.4=1
  Portb.5=1
  Portb.6=1
  Portb.7=1

  end select

  select case Std_Anzeige

  case 0:
  Porta.0=0
  Porta.1=0
  Porta.2=0
  Porta.3=0

  case 1:
  Porta.0=1
  Porta.1=0
  Porta.2=0
  Porta.3=0

  case 2:
  Porta.0=1
  Porta.1=1
  Porta.2=0
  Porta.3=0

  case 3:
  Porta.0=1
  Porta.1=1
  Porta.2=1
  Porta.3=0

  case 4:
  Porta.0=1
  Porta.1=1
  Porta.2=1
  Porta.3=1

  end select

  select case 5_Std_Anzeige

  case 0:
  Porta.4=0
  Porta.5=0
  Porta.6=0
  Porta.7=0

  case 1:
  Porta.4=1
  Porta.5=0
  Porta.6=0
  Porta.7=0

  case 2:
  Porta.4=1
  Porta.5=1
  Porta.6=0
  Porta.7=0

  case 3:
  Porta.4=1
  Porta.5=1
  Porta.6=1
  Porta.7=0

  case 4:
  Porta.4=1
  Porta.5=1
  Porta.6=1
  Porta.7=1
  end select
Return
 
Zuletzt bearbeitet von einem Moderator:
Hallo Gerd!

Das scheint ein ganz interessantes Projekt zu sein,
so eine "Berlin-Uhr".

Hast du den Aufbau denn schon fertig?
Kannst ja mal ein Bild einstellen, damit man von der Hardware einen besseren Überblick bekommt.

Ich gehe mal nicht davon aus, dass du tatsächlich mit Wasser arbeitest sondern die LED`s dies nur simulieren sollen. ;)


Eine Frage zu deinem Code....
Ist das jetzt nur erst mal ein erster Testcode, oder hast du ihn eingekürzt um ihn hier einzustellen?

Um alles gedanklich zu überprüfen fehlt mir jetzt leider die Zeit und das Datenblatt deiner RTC muss ich mir auch noch erst durchsehen.
Obendrein habe ich zwar schon mit RTC`s gearbeitet, aber nicht mit der "DS1307clock.lib" !
Ich kann dir also nicht sagen was die genau macht.....


Wenn du dich noch etwas gedulden kannst, dann ziehe ich mir bei Gelegenheit das Datenblatt deiner RTC und schaue mir das mal an.
Meistens ist dann aber ein anderer User hier schneller und du musst nicht extra auf mich warten. ;)

Was ich allerdings nicht verstehe ist das hier:
I2cstart
I2cwbyte Rtc_address_write ' 1Hz Signal der DS3231 aktivieren
I2cstart
i2cwbyte &H0E
i2cwbyte &H80
I2cstop

Das &H0E ist das Control-Register! Passt schon.
Allerdings deaktivierst du mit &H80 jetzt den Oscillator! :eek:
Meinst du, dass dies so richtig ist?


Ach so, nur mal nebenbei.....
Das "Dcf_Status.7 Bit" muss manuell wieder zurück gesetzt werden, sonst hat es nach dem ersten Sync immer eine 1 ! :rolleyes:


Das war es jetzt erst mal von meiner Seite...... auf die Schnelle zu dieser Stunde! :)

Viele Grüße,
Cassio
 
Abgesehen davon daß mir nicht klar ist, was das für'ne Uhr sein soll, steig ich irgendwie nicht hinter Dein Konzept.
Du hast 'ne RTC, einen Funkuhrempfänger und zusätzlich noch die timerbasierte Sectic-Softclock von Bascom? Möglicherweise sieht das einer der Bascom-Experten ja anders, aber ich würde das eher so angehen:

Du bastelst Dir Dein eigenes Uhrwerk (also geeignete Veriablen für die anzuzeigenden Sekunden-/Minuten-/Stundenschritte usw. Angetrieben wird die Uhr über das Ausgangssignal der RTC (falls Du Deine Anzeige multiplexen mußt, mit dem nötigen Takt, ansonsten halt im Sekundentakt) - als externer Interrupt.
Nach einem Reset/beim WakeUp wird erstmal die Zeit aus der RTC in Dein Uhrwerk geladen, bei Bedarf die RTC über DCF gestellt.

Das Problem ist, daß auch der DCF-Empfang jede Sekunde Aufmerksamkeit verlangt - es müssen sogar Pulslängen gemessen werden. Wie Bascom das konkret macht, weiß ich nicht.
Nur um ab und zu mal die RTC zu syncen (gibt ja inzwischen sehr genaue), reicht es sicher, die Bits selbst mittels Timer mit ICP zu ermitteln. Oder während des syncens auf die RTC und eine brauchbare Anzeige zu verzichten.

Wenn der DCF-Empfang hinreichend gut ist, kannst Du ebenso auf die RTC verzichten, und den Takt aus der DCF ableiten - bei mir ist der Empfang eher ... schlecht.

Edit: mit Cassio hat sich ja bereits ein Bascom-Experte gemeldet...
 
So, mal gegurgelt... sowas?

Da läßt sich übrigens sehr schön das ganze "Uhrwerk" direkt in den Rechenregistern mit ein paar Bitoperationen abwickeln - unter Hochsprachen dann aber eher im SRAM (oder vielleicht eleganter stattdessen in den Port-Registern geparkt...

Wenn das "Sekundenlicht" nicht nötig wäre, bzw direkt aus dem Signal der RTC verwendet werden könnte, könnte man die RTC auf einen Timer/Countereingang legen, der dann im CTC jede Minute überläuft (das Timerregister ist dann sozusagen der interne Sekundenzeiger).
Im Prinzip ist das ein vierstelliges Unäres Display - Einerminuten, Fünferminuten, Einerstunden, Fünferstunden. Beim "Increment" kommt immer eins dazu bis alle an sind.
Das entspricht quasi einer Schiebeoperation (wobei 'ne Null dazugeschoben wird - wenn man die LED mit der Anode an Vcc legt, und die Kathode an das AVR-Bein, paßts).
Jede Minute werden die Einerminuten einmal rechtsgeschoben (nur einen TimerüberlaufIRQ pro Minute), wird dabei die fünfte Null eingeschoben, wird dabei zum ersten Mal nicht(!) das Halfcarry gesetzt. Das ist die Bedingung, die Einerminuten zurück auf 0xFF zu setzen, und Mit den Fünferminuten weiterzumachen. Da das 11 sind, benötigt man zwei Bytes, außerdem ist das hier mit dem Halfcarry nicht so trivial. (geht aber trotzdem, oder man vergleicht).

Usw mit den Stunden, Idee klar?

Die Zeit wird gar nicht in BCDs oder so abgelegt, sondern direkt in diesen Unären Stellen. Nur wenn Du das Display nach der RTC oder dem DCF stellen willst, mußt Du das umrechnen.
 
i2cwbyte &H0E
i2cwbyte &H80
I2cstop

Allerdings deaktivierst du mit &H80 jetzt den Oscillator! :eek:
Meinst du, dass dies so richtig ist?



Hallo Gerd!

Ich habe vorhin erst bemerkt, dass wir das Thema mit der RTC und dem Control-Register ja schon mal ausgiebig besprochen hatten.
Ergo passt es dann schon mit dem &H80 wenn das Signal auch bei Batteriebetrieb ausgegeben werden soll.

Das Dumme ist nur, dass es daher nicht falsch sein kann und es auch nicht zu deiner "Fehlerbeschreibung" passt. :rolleyes:


Ähnlich wie LotadaC überlege ich aber auch, was du eigentlich genau machen möchtest. :hmmmm:
Sobald du in BASCOM das "Config DCF77" verwendest wird auch die Softclock eingestellt und aktiviert.
Mit dieser Softclock kannst du nun deine Uhr "steuern".

Dann hast du noch das DCF77-Signal, welches du zum Stellen der Softclock verwenden kannst.

Deine RTC soll ja eigentlich nur dafür sorgen, dass du nach einem "Stromausfall" gleich wieder die aktuellen Zeitdaten hast,
oder bei einem schlechten DCF-Empfang hin und wieder die genaueren Zeitdaten aus der RTC holst.


Wenn ich dich nun richtig verstanden habe, dann möchtest du aber auf die Funktion der Softclock verzichten und lieber nur mit den Daten der RTC arbeiten......
weil die ja sooooo genau ist. ;)
Habe ich das jetzt so richtig interpretiert?

Ich denke mal, du solltest dich von zwei Dingen im Programm verabschieden:
$lib "mcsbyte.lbx" ' for smaller code
$lib "ds1307clock.lib" ' modified lib

Mit der mcsbyte.lbx habe ich selber schon einige "seltsame" Erfahrungen gemacht und verwende sie daher nur seeeehr selten.
Dann würde ich die ds1307clock.lib auch erst mal wieder heraus nehmen.
Ich bin mir nicht sicher was genau passiert, wenn du die LIB verwendest und gleichzeitig DCF77 einbindest.
DCF77 nimmt automatisch auch ein "Config Clock = Soft" vor, während du zum Nutzen der DS1307clock.lib die Softclock von Hand nach deinen Wünschen einstellst ( Config Clock = User).

Eine Frage noch:
Hast du zusätzlich noch ein separates Display an deiner Berlin-Uhr, oder warum hast du die LIB eingebunden? :hmmmm:
$lib "glcdKS108.lbx"


Ach so, eines noch....
Hast du auch mal einen aktuellen Schaltplan für uns?
Manche fehlerhafte Effekte verbergen sich nicht immer in der Programmierung. :dirol:


Wenn der Schaltplan soweit passt (und der Realität entspricht) und wir diese ersten fehlerhaften Effekte beseitigt haben, dann können wir ja bei Lust und Laune den Programmaufbau und die Ansteuerung der LED`s mal angehen. ;)

Grüße,
Cassio
 
Also im Code wird nur einmal die Zeit der RTC zum Stellen der Softclock verwendet und ausgegeben(*).
Danach wird dann ununterbrochen (?) die (vom DCF als BCD empfangene und nach dezimal gewandelte??) DCF-Zeit nach BCD gewandelt und in die RTC geschrieben anschliessend wird die dezimale Zeit mit Hilfe von vier Divisionen in das vierstellige Unärsystem gewandelt, und die vier Stellen dann mittels switch-Case nacheinander auf die Ports gelegt. Egal ob sich da überhaupt was geändert hat.

Letztlich wird die Zeit also nur auf dem Unär-Display ausgegeben, wo sich abgesehen vom Sekundenstrobe nur jede Minute was ändert.
Im Programm wird die eigentliche (dezimale und BCD-) Zeit sonst nie gebraucht.

Letztlich werden nacheinander erstmal nur die vier Minuten-LEDs angeschaltet
Code:
....
°...
°°..
°°°.
°°°°
laufen die über
Code:
....
, zählen die Fünf-Minuten-LEDs eins weiter
Code:
...........
°..........
°°.........
usw

Statt da jetzt irgendwo rumwandeln zu müssen, kann man einfacher direkt Unär speichern - bzw ist das ja in den AVR-Beinen bereits gespeichert, es muß nur jede Minute einmal der Zustand der Beine eins weiter getickt werden.

Wie man oben sieht, sind das gaaaanz einfache Schiebeoperationen (wenn man die LEDs auf den Ports entsprechend anordnen kann - für 'nen AVR das einfachste/schnellste der Welt).

Und mit'nem RTC oder DCF-IC hat man 'nen Sekundentakt gratis - legt man den auf'n Timer/Counter, der alle 60 Ticks überläuft, hat mn IRQs im Minutentakt, ohne irgendwelche weitere Laufzeitlast im Vordergrund.
 
Und mit'nem RTC oder DCF-IC hat man 'nen Sekundentakt gratis
DCF stimmt nur eingeschränkt. Haste guten Empfang jain (1 Bit wird ausgelassen, also statt 60 nur 59 pro Minute). Haste schlechten Empfang kannste Werte von 0 bis sonstwohin bekommen. Ist also nicht zuverlässig.

RTC, ja, die meisten geben ein Clock aus (oder können so programmiert werden). Den zu verwenden ist auch sinnvoll, weil würde man einen Timer nehmen (1sec) und darin den RTC abfragen könnte man Sprünge drin haben durch die Unterschiede im Timing (Crystal Toleranzen). So sagt dir der RTC Hey, ich hab n neuen Wert und du holst ihn dann ab.
 
Ja, beim DCF ohne gutem signal ist's klar, das mit der Minutenlücke auch... (und ich hab hier in der Wohnung quasi gar keinen Empfang)

Bei meinem Vorschlag würde ja die RTC den Timer/Counter takten, und damit 'nen 1min-IRQ erzeugen - theoretisch könnte man auch 'nen Timer direkt den 1min-IRQ generieren lassen, aber nur mit'nem 16er Timer (oder 'nem seeeehr geringen Basistakt), und eben nur so exakt, wie die Taktquelle des AVR ist. So übernehme ich die Genauigkeit der RTC, mit dem schwächsten Timer (mit externem Takteingang - beim Mega16 ist das Timer0).
So, hab mal ins DB des M16 gesehen,
4 komplette Ports (A, B, C, D)
C0 und C1 sind TWI (für die RTC)
B0 ist T0 (mit der RTC die Unruh des Uhrwerks)
im unteren Nibble von D liegt der UART und die beiden INTs (gut geeignet für DCF, wenn man auf ICP verzichtet)

A wäre komplett frei
von den anderen dreien je das obere Nibble
in B zusätzlich 1, 2 und 3

meine Empfehlung wäre:
die "1min-LEDs" an eins der oberen Nibbles (zb D4..D7) - dann kann man beim schieben auf das Carry reagieren -> "5min-LEDs"
die ersten 8 "5min-LEDs" an A0..A7 - auch hier signalisiert das Carry
die restlichen drei "5min-LEDs" an B1..B3, hier signalisiert das Halfcarry den "Überlauf" -> "1h-LEDs"
die "1h-LEDs" an eins der oberen Nibbles (zB B4..B7) - Carry -> "5h-LEDs"
die "5h-LEDs" an das letzte obere Nibble (zB C4..C7) - da der Tag nicht 25 Stunden hat, muß man hier leider mit zwei Vergleichen prüfen, durch das letzte schieben alle LEDs angegangen sind (was ja die 24 wäre) - das Carry reagiert ja erst bei 24->25
(Für den DCF und weitere Funktionen blieben C2, C3 und D0..D3 frei, also inklusive UART und die beiden INTs)

Da beim Schieben Nullen eingeschoben werden, sollen die LEDs bei Null leuchten, also Anoden an Vcc, Kathoden an den AVR (Rs jetzt mal vernachlässigt). Die meiste Zeit benötigt der Wechsel von 23:59 auf 00:00, da da alle durchklackern müssen. Ohne das jetzt konkret durchgerechnet zu haben würde ich da 60 bis 70 Takte schätzen - bei 8Mhz über den Daumen 7-10µs ...
 
Da beim Schieben Nullen eingeschoben werden, sollen die LEDs bei Null leuchten, also Anoden an Vcc, Kathoden an den AVR
Müsste (etwas uneleganter) doch auch mit Rotate gehen wenn man vorher das Carry setzt, oder nicht? Falls die Hardware schon fest verdrahtet ist und 1en erwartet statt wie in deinem Beispiel 0en.
… wobei … es ist Bascom, ich weiß nicht ob das da so möglich ist.
 
klar geht das andersrum auch mit rollen, nur dann muß man aber beim ersten Schritt vor dem rollen das Carry setzen. Sonst hat man ja das Carry vom vorherigen "Überlauf", nur bei den drei Bits im LowNibble von B nicht, dieweil da ja das Halfcarry kommt, und ein Rotate Right through Halfcarry oder so gibts nicht (Halfcarry->B7->B6->...->B1->B0->Carry)...
Die Maskierungsoperationen zur Wiederherstellung der nicht/anderweitig genutzten Beine des Ports vor dem Sprung manipulieren das Carry ja nicht.

In Bascom kannst Du doch wunderbar ASM einbetten, hier dann die ganze Timer-ISR.
Willst Du in einem ASM-Block eine vorher von Bascom alloziierte Variable nutzen (also zB mit LDS die Variable laden), setzt Du die Variable einfach in geschweifte Klammern "LDS Rechenregister, {Bascom-Variablenname}".
 
Zuletzt bearbeitet:
Ja, in ASM Block klar. Aber in Bascom (Basic) selbst… Das meinte ich :)
 
Hallo ihr lieben Helferlein,
leider kann ich mich erst heute melden, da ich nur am Wochenende Zeit habe.
Vielen Dank für die guten Ideen, aber.....
Dies ist ein Schulprojekt im Rahmen des Physikunterrichtes und eure wirklich guten Ideen ist dem Klientel - nun ja- schwer zu vermitteln.:(
Der Code muss also nicht unbedingt genial, sondern für jeden verständlich sein.
Die Vorgehensweise war folgende:
1. Haben wir überhaupt ein DCF - Signal? (Versuch mit Anzeige auf Display)
2. Berechnung der Anzeigewerte (Modulo, Division etc.)
3. Ansteuerung der LED´s in der Anzeige (Daher der case - Krempel)
4. Was ist bei Stromausfall? (RTC)
usw., usw.
Jeder einzelne Teilabschnitt funktioniert. Nur am Schluss treten die oben geschilderten Fehler auf.
Es wäre schön, wenn ihr mir bei der Beseitigung der Fehler in genau diesem Code helfen könntet. Eure Ideen werde ich mal in einem privaten Projekt aufgreifen.

Für die Hardware habe ich mal auf die Schnelle eine Schaltung entworfen. Die Betonung liegt auf schnell, also bitte keine silberne Zitrone für das Layout.

Gruß Gerd
 

Anhänge

  • Berlin Uhr.png
    Berlin Uhr.png
    29,2 KB · Aufrufe: 17
Sorry falsches Bild!!
 

Anhänge

  • Berlinuhr_neu.png
    Berlinuhr_neu.png
    38,9 KB · Aufrufe: 21
Dies ist ein Schulprojekt im Rahmen des Physikunterrichtes und eure wirklich guten Ideen ist dem Klientel - nun ja- schwer zu vermitteln
Wäre da für den Einstieg nicht vielleicht eine BCD (fälschlicherweise auch Binär-) Uhr etwas geeigneter?
Ganz ehrlich, den Code kann ich verstehen, aber wie man die Uhr liest … das steht auf einem anderen Blatt ^^
Aber das ist vielleicht auch Wohnort bedingt. Berliner können das bestimmt besser als ich;)
 
Hmm...

Du hast nicht gesagt, daß Du damit irgendwelche didaktischen Ziele verfolgst, und schon gar nicht, welche. Ich zB finde es einfacher ein paar Bytes zu verschieben, als 'ne binäre Integerdivision und Restbestimmung (was eigentlich genau derselbe Algoritmus ist und nur ein anderes Register als Ergebnis liefert) zu programmieren.
Gut, das laßt Ihr die gewählte Hochsprache machen, aber offensichtlich wird das ganze zeitkritisch, und jetzt müßt Ihr vielleicht doch nachvollziehen, wielange 'ne Division oder Modulo braucht. Bascom setzt das ja auch nur in assembleräquivalenten Maschinencode um.
Meine Vorgehensweise wäre eher andersrum gewesen:
Wie funktioniert denn so'ne (digitale) Uhr?
Du hast mehrere Stellen. Läuft eine über (bzw bei Deiner Uhr: springt sie von voll auf leer), wird die nächste eins weitergesetzt. Läuft diese über, die nächste usw usw.
Bei Thomas Vorschlag wären das dann die einzelnen digits - eine für die Minuteneiner (0..9), die Minutenzehner (0..5), Stundeneiner (0..9) und Stundenzehner (0..2).
Wenn man das ganze zusammengesetzt hat, braucht man eine genaue Taktquelle, die das ganze (an der kleinsten Stelle) antreibt. Da das bei Dir die Minuten(einer) sind, halt einen Minutentakt. Wenn später das ganze durch eine RTC ergänzt werden soll, kann man die hier schon mal einbeziehen, und deren genauen Takt als Antrieb nutzen.
Die RTC liefert Sekunden also eine weitere Stelle (die eben nicht angezeigt wird) - ob Du die nun auch in einer Variable zählen läßt, oder eleganter im Timer, ist für den Algoritmus egal.
Wenn das Uhrwerk läuft, kann man sich Gedanken darüber machen, wie man die in der RTC laufende übernimmt, wie man die Zeit in der RTC stellt, und als letztes den DCF hinzunehmen.
(Für die DCF-Geschichte scheint Bascom den Compare-Interrupt (A) von Timer1 zu nutzen und regelmäßig auf den DCF-Pin zu schauen. (Das sollte mMn unter Verwendung des InputCapture oder eines externen Interruptes wesentlich sparsamer gehen - aber darum gehts hier nicht).

Bei Deinem Programm schreibst Du unnötig oft die Anzeige neu (inklusive Berechnung der vier Divisionen) - Sinn macht es, den Sekundeninterrupt (sectic) zu nutzen, und im Hauptprogramm abzufragen, ob die Anzeige überhaupt zu ändern ist.
 
Bei Thomas Vorschlag wären das dann die einzelnen digits - eine für die Minuteneiner (0..9), die Minutenzehner (0..5), Stundeneiner (0..9) und Stundenzehner (0..2).
Nicht ganz, das wäre so eine Art Digitaluhr (oder Dezimaluhr wenn man so will). Ich meinte echtes BCD, also 2 LEDs für Stunden Zehner, 4 LEDs für Stunden Einer, 3 für Minuten Zehner, 4 für Minuten Einer, 3 für Sekunden Zehner, 4 für Sekunden Einer.
Das hätte dazu auch noch den netten Nebeneffekt dass verdeutlicht wird wie in der digitalen Welt wirklich gezählt wird – was ich persönlich als lehrreich sehe.
 
Nicht ganz, das wäre so eine Art Digitaluhr (oder Dezimaluhr wenn man so will). Ich meinte echtes BCD, also 2 LEDs für Stunden Zehner, 4 LEDs für Stunden Einer
Doch, genau so meinte ich es. Für die Berlin-Uhr hätte er in jedem Digit halt mehr oder weniger LEDs an (indem das Uhrwerk bei jedem Tick der Stelle eine An-LED hinzuschiebt, und beim Überlauf alle löscht), bei Deiner Empfehlung (richtiges BCD) würde der Inhalt des Digits bei jedem Tick regulär inkrementiert werden, und beim "Überlauf" auf Null gesetzt werden. Bei entsprechender Anordnung der LEDs kann die Variable dann recht einfach direkt auf den Port ausgegeben werden (bei 19 Uhr steht in den Zehnerstunden halt 'ne dezimale neun, also in Wirklichkeit 00001001binär. Legt man das auf den Port, leuchten die LEDs für 8 und 1, also zusammen 9.

In beiden Fällen hat man aber für jede Stelle 'ne eigene Variable, und alle Stellen zählen als Uhrwerk durch. Ob nun binary coded (BCD) oder biertischnotiert (Unärsystem/Strichliste) ist dann nur'ne Sache der Umsetzung...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)