Bitte verschieben! Schon wieder ne Uhr!

#4754056
Lesenswert?

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
int data = 10;                      // init declare pins for shift register
2
int clk = 8;
3
int latch = 9;
4
int clr = 7;
5

6

7
void setup() {
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
void loop() {
21

22

23
int sec;                        // Uhr Counter
24
int minu;
25
int hour;
26
int sec1;
27
int sec2;
28
int sech;
29
int minu1;
30
int minu2;
31
int minuh;
32
int hour1;
33
int hour2;
34
int hourh;
35
int data1;
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 (int i=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
    case 0: sech = 1;
62
    case 1: sech = 2;
63
    case 2: sech = 4;
64
    case 3: sech = 8;
65
    case 4: sech = 16;
66
    case 5: 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
      else digitalWrite(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
    case 0: sech = 1;
86
    case 1: sech = 2;
87
    case 2: sech = 4;
88
    case 3: sech = 8;
89
    case 4: sech = 16;
90
    case 5: sech = 32;
91
    case 6: sech = 64;
92
    case 7: sech = 128;
93
    case 8: sech = 256;
94
    case 9: sech = 512;
95
}
96
  for (int i=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
      else digitalWrite(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 (:
Angehängte Dateien:
#4754088
Lesenswert?

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
#4754191
Lesenswert?

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.
1
#define DATA 10
2
#define CLK 8
3
#define LATCH 9
4
#define CLR 7
#4754194
Lesenswert?

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
void loop()
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.
#4754213
Lesenswert?

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.
#4754309
Lesenswert?

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++)?
Gast #4754533
Lesenswert?

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:
1
int main()
2
{
3
   interne_initialisierungen;
4
   setup();
5
   while (1)
6
   {
7
       interne_Aufgaben;
8
       loop();
9
   }
10
}
#4763653
Lesenswert?

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
Angehängte Dateien:
#4763998
Lesenswert?

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
Gast #4764252
Lesenswert?

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"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren