Hi,
Meiner einer baut sich eine Uhr. Nun ist meine Ausbildung (EGS) knapp 10
Jahre her und damals hatten wir "nur" ein PIC16F84, den wir mit
Assembler programmieren durften. Vor einigen Monaten habe ich von einem
Freund/Kollegen einen Arduino Nano bekommen. Nun benutze ich als
Anzeigeelemente für meine Uhr Nixie-tubes. Bedeutet: Wenn ich kein
Multiplexing betreiben will/kann(!) brauche ich einen Expander - etwa in
Form eines Schieberegisters. Ansteuerung läuft!
Da ich etwa vor 2 Wochen mit meinem Arduino angefangen habe zu spielen
und ein paar grundlegende Sachen erkundet und hoffentlich verstanden
habe, war es nun an der Zeit für meine SEHR primitive Uhr.
Hierzu sei gesagt, dass der "Code" meinen eigenen gedanken entsprungen
ist - und da es nur eine Uhr sein soll ist es wohl ziemlich egal wie
performant der Code ist oder was man mir sonst vorwerfen kann. Die
Routinen habe ich natürlich gegooglt und angepasst.
Jetzt kommt's! Mein Schieberegister wird ordentlich angesteuert ABER aus
meinem DataPin kommen offensichtlich nur 1-en raus. Habe im Code die
Gegenprobe gemacht und es kommen auch 0-en raus wenn ich meine
Ausgangsbedingung ändere.
Ich habe den verdacht, dass:
1. meine Zeit nicht hochzählt
2. meine kleine "Bibliothek" falsch programmiert ist
Ich gebe wie gesagt seriell auf ein Schieberegister aus. 38Sekunden
würden dann in 16Bit so aussehen:
Zehner Einer
0,1,2,3,4,5 / 0,1,2,3,4,5,6,7,8,9
0,0,0,1,0,0 / 0,0,0,0,0,0,0,0,1,0 Das sollte nach einem Durchlauf im
Schieberegister stehen.
Wie gesagt - Ich bekomme nur 1-en oder 0-en aus meinem DataPin.
Achja - Ich versuche BitShifting zu nutzen, um mein Muster seriell
ausgeben zu können!
Das würde erklären warum nur 1-en rauskommen wenn meine "Bibliothek"
nicht funktioniert und/oder der Counter nicht läuft
Code: (Bitte nicht kürschnern!)
1
intdata=10;// init declare pins for shift register
2
intclk=8;
3
intlatch=9;
4
intclr=7;
5
6
7
voidsetup(){
8
pinMode(data,OUTPUT);//set pin mode
9
pinMode(clk,OUTPUT);
10
pinMode(latch,OUTPUT);
11
pinMode(clr,OUTPUT);
12
13
digitalWrite(clr,LOW);//init clear all outputs of shift register
14
digitalWrite(latch,LOW);
15
digitalWrite(latch,HIGH);
16
digitalWrite(clr,HIGH);
17
delay(500);
18
}
19
20
voidloop(){
21
22
23
intsec;// Uhr Counter
24
intminu;
25
inthour;
26
intsec1;
27
intsec2;
28
intsech;
29
intminu1;
30
intminu2;
31
intminuh;
32
inthour1;
33
inthour2;
34
inthourh;
35
intdata1;
36
37
38
sec=sec++;
39
delay(100);
40
if(sec>=60){
41
sec=0;
42
minu++;
43
}
44
if(minu>=60){
45
minu=0;
46
hour++;
47
}
48
if(hour>=24){
49
hour=0;
50
}
51
52
// Sekunden
53
54
55
for(inti=0;i<6;i++){// 10er ins Register schieben (6 Stellen)
56
57
sec2=sec/10;//Zehner ausrechnen
58
sec1=sec-sec2*10;//Einer ausrechnen
59
60
switch(sec2){//Muster für 10er auswählen
61
case0:sech=1;
62
case1:sech=2;
63
case2:sech=4;
64
case3:sech=8;
65
case4:sech=16;
66
case5:sech=32;
67
}
68
69
digitalWrite(latch,LOW);
70
digitalWrite(clk,LOW);
71
data1=sech&&1;
72
if(data1=0){
73
digitalWrite(data,LOW);;
74
}
75
elsedigitalWrite(data,HIGH);
76
sech=sech>>1;
77
digitalWrite(clk,HIGH);
78
digitalWrite(latch,HIGH);
79
delay(500);
80
}
81
82
delay(1000);
83
84
switch(sec1){//Muster für 1er auswählen
85
case0:sech=1;
86
case1:sech=2;
87
case2:sech=4;
88
case3:sech=8;
89
case4:sech=16;
90
case5:sech=32;
91
case6:sech=64;
92
case7:sech=128;
93
case8:sech=256;
94
case9:sech=512;
95
}
96
for(inti=0;i<10;i++){// 1er ins register schieben (10 Stellen)
97
digitalWrite(latch,LOW);
98
digitalWrite(clk,LOW);
99
data1=sech&1;
100
if(data1=1){
101
digitalWrite(data,HIGH);
102
}
103
elsedigitalWrite(data,LOW);
104
sech=sech>>1;
105
digitalWrite(clk,HIGH);
106
digitalWrite(latch,HIGH);
107
delay(500);
108
}
109
delay(1000);
110
digitalWrite(clr,LOW);//init clear all outputs of shift register
111
digitalWrite(latch,LOW);
112
digitalWrite(latch,HIGH);
113
digitalWrite(clr,HIGH);
114
delay(500);
115
}
Die vielen und langen Delays sind zum Debuggen. Mein Shieberegister hat
an jedem Output eine LED.
*edit: Für Minuten und Stunden ist die Ausgabe-Routine die gleiche. Ist
aber im Moment im Code auskommentiert. Der Arduino lebt mit einem
AtMega328P.
Vielen Dank für die Aufmerksamkeit!
Gruß Micha (:
Ja, benutze ich. Ich habe schon Testprogramme, in denen ich Muster aus
Arrays auslese und übergebe. Das funktioniert. Selbst wenn der wert für
Einer und Zehner immer Null bleibt, sollte mein Register 0x0401
anzeigen. Es kommen aber nur 1-en aus dem DataPin und somit habe ich
immer 0xFFFF
Danke!
Jetzt bekomm ich für meine Einer-Stelle schon mal ne 0 raus. also auf
16Bit:
Zehner / Einer
1,1,1,1,1,1 / 0,0,0,0,0,0,0,0,0,1 Schieberegister
5,4,3,2,1,0 / 9,8,7,6,5,4,3,2,1,0
Was mich zu dem Schluss bringt, dass mein Zähler nicht läuft ;/
Micha W. schrieb:> void loop() {>> int sec; // Uhr Counter
Eine lokale Variable, die am Anfang einer Funktion deklariert wird, hört
am Ende derselben auf zu existieren.
Ich habe sie mal global gesetzt. Ändert aber nicht. Ich bleibe Ja im
"void loop ()" wenn ich das richtig sehe. das setup wird vom Controller
nur 1 mal ausgeführt.
Danke trotzdem für die Idee!
Micha W. schrieb:> Ich bleibe Ja im> "void loop ()" wenn ich das richtig sehe.
Ich sehe keinen Funktionsaufruf. Die Funktion muß ja einmal pro Sekunde
aufgerufen werden, damit die Zeit hochgezählt werden kann.
Micha W. schrieb:> switch (sec1) { //Muster für 1er auswählen> case 0: sech = 1;> case 1: sech = 2;> case 2: sech = 4;> case 3: sech = 8;> case 4: sech = 16;> case 5: sech = 32;> case 6: sech = 64;> case 7: sech = 128;> case 8: sech = 256;> case 9: sech = 512;> }
Warum machst du nicht einfach einen Linksshift?
1
sech=(1<<sec1);
Micha W. schrieb:> int data = 10; // init declare pins for shift> register> int clk = 8;> int latch = 9;> int clr = 7;
Konstanten definiert man in C über den Präprozessor.
Im moment arbeitet das Programm sequenziell alles ab und löscht am Ende
das Schieberegister.
So wie ich es sehe springt das Programm wieder nach
1
voidloop()
rein.
Sehe ich das falsch und mein Programm beginnt in Zeile eins und
initialisiert alle Variablen wieder mit 0?
Dann sollte trotzdem der Sekundenzeiger bei 1 und nicht 0 stehen. Und
ungeklärt ist, warum mein Zehner mir ständigen 1-en auswirft :/
das mit & und && habe ich berichtigt.
Das switch/case war "so ausgedacht". Ich bin mir bewusst dass es
eleganter geht.
Das Definieren habe ich so aus einem Beispiel übernommen. Ich benutze
wie gesagt einen Arduino und die damit verbundene Software und die
Beispiele. Trotzdem Danke für den Anstoß!
Ich habe Minuten und Stunden mal eingebunden und angepasst.
Was auf meinem Schieberegister nach vollem durchlauf passiert:
Zehner / Einer Sekunden
000000/0000000001
Zehner / Einer Minuten
000001/0000000001
Zehner / Einer Stunden
000001/0000000001
Mein Uhr würde jetzt anzeigen: 00:00:"nichts"0
Also habe ich noch ein Problem mit dem ersten Aufruf der Zehnerstelle
für die Sekunden.
Jetzt kommt der nächste Part. Ich traue mich noch nicht an DCF-77 und
RTC heran.
Ich habe einen 1Hz Counter gebaut der 2,3ppm hat - sind ca 6 Sekunden
Abweichung pro Monat (30Tage). Damit kann ich sehr wohl leben und ist ja
gar nicht schlimm.
Der Code ist performant genug um ihn in weniger als einer Sekunde
auszuführen und auf meine Anzeige auszugeben.
Kann ich meinen 1Hz Counter einfach an einen Digital Port anschließen
und Diesen als Interrupt deklarieren (mit Option auf Priorität, wegens
händischer Einstellung der Grund-Zeit)und damit meine Routine ein mal
ausführen (Sekunde++)?
loop() ist keine Endlosschleife, sondern eine normale Funktion, die vom
Arduino Framework aus einer Endlosschleife heraus aufgerufen wird.
Stelle Dir das Arduino Framework so vor:
Hi,
Bin mal wieder dazu gekommen an der Uhr zu arbeiten.
Hinzugekommen sind der 1Hz Counter und 4 Buttons zum Stellen. Die Uhr
wird mit einem Button angehalten und mit den 3 anderen gestellt. Das
Stellen wird auch direkt ausgegeben und man kann im Code die Druckdauer
zwischen einmaligem Hochzählen und dauerndem Hochzählen einstellen.
Jeweils für Stunden, Minuten und Sekunden ohne beim Überschreiten die
jeweils nächste Stelle zu beeinflussen (bei 59+ Sekunden bleiben die
Minuten stehen und die Sekunden fangen bei 0 wieder an).
Der 1Hz Counter ist realisiert mit einem 2,048MHz Oszillator, wessen
Signal dann durch einen HEF4060 läuft bis ich 500Hz (2^11 glaube ich :/
)habe und dann x2 74390 bis ich zu 1Hz komme ( (500 / 2x10) / 5). Der HP
Frequency Counter auf Arbeit hat mir 1,000.002.3 Hz ausgespuckt, was
ungefähr 6,2 Sekunden Ungenauigkeit auf 31 Tage einbringt.
Das 150V DC Netzteil für meine Anzeigeröhren ist fast fertig und dann
fehlt noch das MOSFET Array um sie anzusteuern. Bilder gibts dann davon
natürlich!
Schönen Abend noch,
Micha
Kann ein Moderator bitte den Titel Ändern in "Schon wieder ne Uhr!".
Habe damals den Thread in einem Falschen Forum gepostet und dann das
"Bitte Verschieben!" hinzugefügt. Lässt sich jetzt nicht mehr Ändern.
Danke!
Hi,
Uhr läuft 3h und ich hab 2min overclock.... also entweder muss ich die
Schaltung nochmal an den HP Counter hängen oder ich hab da 'nen harten
Glitch drin, den ich nicht sehe...
Dass die Uhr irgendwann mal was nicht mitbekommt und zu langsam wäre,
würde ich verstehen - wegen den willkürlich gewählten delays.
aber warum ist die schneller?
Mein Counter (2.048MHz+4060+74390+74390) 1Hz?
Ist der zu schnell weil mein USB (am Arduino, 6x 74595, 1x4060, 2x74390)
das alles treiben muss und der irgendwann zusammen bricht und dann
schneller wieder die 5V bringt und damit der Counter schneller ist wegen
power up?
gruß michi
Micha W. schrieb:> Uhr läuft 3h und ich hab 2min overclock....
Du erzeugst deinen Zeittakt immer noch mit Aufrufen von delay() an
diversten Stellen im Code? Oder hast du inzwischen deinen
DCF77-Empfänger dran?
Bei DCF77 darf das eigentlich nicht passieren.
Wenn du allerdings die Zeit aus dem CPU-Clock ableitest, bist du selbst
bei Verwendung des Zeitgebers vom Arduino-"Betriebssystem", i.e. milis()
auf die Genauigkeit der Taktfrequenz angewiesen, die mit Sicherheit
nicht auf 6 gültige Ziffern dem aufgedruckten Wert entspricht. Mit dem
delay() liegst du schnell völlig daneben, weil selbst die
Programmlaufzeit Fehler generiert. Wahrscheinlich geht deine Uhr nach
den 3 Stunden kräftig nach, sofern sich die delays in loop() auf genau
1000 Millisekunden aufsummieren ;-)
Lies dir mal diesen Thread von PeDa durch
Beitrag "Die genaue Sekunde / RTC"