Arduino Uhr

Hallo, ich wollte mit arduino eine uhr bauen, die die startzeit vorgegeben hat und immer die sekunden höherzählt, dann ne minute bis zu stunden, bei 24:00 soll sie wd auf 0:00 und von vorne anfangen, hier mein coder der nicht richtig funktioniert:

#include <LiquidCrystal.h>

char inData[20] = "19:19:19";
char inChar;
byte index = 0;
bool ask = false;
int h,hh,m,mm,s,ss;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() { 
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
	delay(100);
	lcd.clear();

	if(ask) {
		
	} else {		

		if(s<6){
			if(ss<10){
				++ss;
				delay(1000);
			}else{
				ss = 0;
				++s;
			}
		}else{
			s = 0;
			ss = 0;
			++mm;
		}

		if(m<6){
			if(mm<10){
				++mm;
			}else{
				mm = 0;
				++m;
			}
		}else{
			m = 0;
			mm = 0;
			++hh;
		}

		if(h<=2){
			if(hh<10){
				++hh;
			}else{
				hh = 0;
				++h;
			}
		}else if(h<=2 && hh == 4){
			h = 0;
			hh = 0;
			++ss;
		}

		inData[0] = h;
		inData[1] = hh;

		inData[3] = m;
		inData[4] = mm;

		inData[6] = s;
		inData[7] = ss;

		for(int i = 0; i < 8; i++)
			lcd.write(inData[i]);
	}
}

Verrätst Du allen die nicht hellsehen können was genau nicht funktioniert? D.h. was geht wie schief? Was hast Du schon probiert um das Problem zu lösen?

Meine Vermutung wäre, daß Deine Uhr gewaltig nachgeht. Grund: "delay" ist das falsche Mittel weil der Rest des Codes ja auch Zeit zur Ausführung braucht.

Und wie ist deine Frage? :wink: Der Code ist Quark, von Anfang bis zum Ende. Ich würde dir eher zu einer Real Time Clock raten, entsprechende ICs zählen dir automatisch die Zeit weiter, batteriegepuffert auch dann, wenn der Arduino stromlos ist.

ja, ich weiß dass er müll ist, es funktioniert ja auch nicht, aber so ähnlich habe ich ihn schonmal gesehn wo er funktionierte, ich weiß blos nicht wie und finde im inet nichts, bitte helft mir

Schau doch in meinen Blog, der Uhrencode dort funktioniert. Allerdings brauchst Du dann noch ein DCF77 Modul.

Nehm ein DS3231 Modul. Kostet um die 5€. Wird einmal über die Serielle Verbindung eingestellt und läuft dann vor sich hin. Pins gehen dir dadurch nicht verloren, da das RTC Modul einfach mit an den IIC/I2C Bus angeklemmt wird.

Des weiteren ist delay() großer Humbuck wie bereits ein Vorredner schrieb. Bei delay(1000) stoppt im loop jedesmal das Programm für 1000ms. Nur ist es dann mit dem Code noch nicht getan. Der Sketch arbeitet nicht nur das delay ab. Das heißt, das Programm stoppt zwar für 1000ms, jedoch bis zum nächsten Durchlauf kommen da noch einige ms vom Sketch selber dazu. Somit wird das sehr ungenau.

ich glaube das mir dein blog nicht weiterhilft, sotoll dein shield auch ist, jedoch ist das nicht mein vorhaben

Dein Problem ist einfach: deine 6 Ziffern gehen von 0 bis 9,
was du mit write ausgeben willst sind aber Zeichen von '0' bis '9'.

( Zwischen '0' und 0 ist ein Unterschied )

Abhilfe a) nimm print statt write
oder b) nimm write('0' + ss);
oder c) da du nur ++ und =0 machst, kannst du auch mit Text rechnen

		if(s<'6'){
			if(ss<='9'){
				++ss;
				delay(1000);
			}else{
				ss = '0';
				++s;

Das (c) hat vermutlich noch nie jemand gemacht, das wäre cool 8)

Um eine Zeit ab Start von "00:00:00" hochzählen zu lassen, ist Udos SuperDCF natürlich ziemlich daneben, auch wenn die irgendwann später nebenbei fehlerfreie Sekundenpulse liefert, und andere Echtzeit-Uhren auch nur bedingt brauchbar.

delay() liefert dir unnötige Ungenauigkeit rein, da wäre millis umrechnen schon besser. Ein Arduino mit Quarz wäre hübsch.
Du könntest auch die Netzfrequenz mitzählen, die ist langfristig gesehen erstaunlich genau (jedenfalls im Vergleich zum UNO-Resonator, Udo ist konkurrenzlos).

Aber du willst vermutlich bloss eine lebendige LCD Anzeige, die zeigt wie lange dein Arduino schon läuft, und auf eine Minute am Tag kommt es weniger an als dass das Ding erstmal was anzeigt.

michael_x:
Du könntest auch die Netzfrequenz mitzählen, die ist langfristig gesehen erstaunlich genau (jedenfalls im Vergleich zum UNO-Resonator, Udo ist konkurrenzlos).

Die Netzfrequenz ist nicht nur erstaunlich genau sondern auf lange Zeit gesehen sehr genau. Vergleichbar genau zu DCF77:

Netzzeit

Die Netzfrequenz im europäischen Verbundnetz eignet sich wegen der geringen Abweichungen von der Nennfrequenz als Zeitgeber für Uhren. Trotz der geringen Abweichungen können sich dabei Fehler von einigen Sekunden pro Tag ergeben. Um den Zeitfehler gering zu halten, wird die Netzzeitabweichung als Differenz zwischen Koordinierter Weltzeit und der auf Basis der Netzfrequenz ermittelten Zeit zentral[5] erfasst und korrigiert. Überschreitet die Netzzeitabweichung +/-20 Sekunden, dann wird die Nennfrequenz für die Frequenzregler bei vorauseilender Netzzeit um 10 mHz auf 49,990 Hz reduziert, bei nacheilender Netzzeit um 10 mHz auf 50,010 Hz erhöht[6]. Dadurch passt sich die Netzzeit langsam wieder an die Koordinierte Weltzeit an. Die Netzzeit stellt damit eine langfristig sehr genaue Zeitbasis mit kurzfristigen Schwankungen im Sekundenbereich dar.

In Europa erfasst Swissgrid im Auftrage des Stromverbundes UCTE die Abweichungen und koordiniert die Korrekturen.

Grüße Uwe

@michael, ich weiß nicht genau wie ich deinen vorschlag anwenden muss, kannst du pls coden sagen?

Wenn dir michael den fertigen Code gibt hast du nix gelernt.

Fang doch einfach und in kleinen Schritten an:

  1. Irgendwass auf dem LCD darstellen.
    geht? Gut, dann:
  2. eine Zahl darstellen, die langsam (egal wie langsam) hochgezählt wird.
    geht? Gut, dann:
    wie 2. aber ohne delay()! (Siehe Beispiel "Blink without delay")
    geht? Gut, dann:
  3. Eine Zahl bis 10, dann wieder von 0 an zählen lassen.
    geht? Gut, dann:
  4. ....

Nur so wirst du verstehen, wie es funktioniert.

a) nimm print statt write

Vergleiche

lcd.write(48);
lcd.print(48);

( Beide sollten etwas lesbares ausgeben. )

Und das ist schon jenseits von guntherb's "damit du was lernst" - Grenze :wink:


Falls du auch b) probieren willst, füg noch lcd.write('0'+9); hinten dran.

</sub> <sub>0489</sub> <sub>

guntherb:
Wenn dir michael den fertigen Code gibt hast du nix gelernt.

Lernen kann er vom reinen "Code übergeben" natürlich nichts.
Aber natürlich kann er sich übergebenen "Code ansehen und verstehen".

guntherb:
Nur so wirst du verstehen, wie es funktioniert.

Mit "ohne Ahnung Herumpfriemeln" lernt er weder "good programming practices" noch lernt er damit sinnvoll verwendbare Funktionen kennen.

Solange jemand null Ahnung hat, kann er sich von beispielhaftem Code erfahrener Programmier eine Menge abschauen.
Und zwar sowohl "good programming practices".
Als auch nützliche Funktionen.

Wenn er beispielhaften Code nicht gleich versteht, kann er sich anhand der Namen unbekannter Funktionen wenigstens ergoogeln, was das für eine Funktion ist. Aber wenn er nur völlig ahnungslos vor einem leeren Editorfenster sitzt, dann sollen ihm die passenden Funktionen einfallen? Z.B. "atol" um die Zahlenwerte aus seinen Startdaten herauszuziehen oder sprintf/snprintf zum Formatieren von Textausgaben auf LCD-Display? Das kann ja gar nicht funktionieren!

Deshalb hier ein beispielhafter Code, zum Verstehen, Lernen, Verstehen und Herumspielen:

#include <LiquidCrystal.h>
// LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

char inData[20] = "19:19:19";

byte stunden, minuten, sekunden;

void setup() {
//  Serial.begin(9600);
  // Anfangswerte setzen aus dem Vorgabewert
  stunden=atol(&inData[0]);
  minuten=atol(&inData[3]);
  sekunden=atol(&inData[6]);
  lcd.begin(16,2);
}

void tickTack()
{
  static unsigned long prevMillis;
  while( millis() - prevMillis >= 1000) // jeweils 1000 ms zählt um 1 Sekunde weiter
  {      
    sekunden++;
    if (sekunden>=60)
    {
      sekunden=0;
      minuten++;
    }  
    if (minuten>=60)
    {
      minuten=0;
      stunden++;
    }  
    if (stunden>=24) stunden=0;
    prevMillis += 1000;	
  }
}

void updateDisplay()
{
  char linebuf[17]; // Zeilenpuffer für max. 16 Zeichen
  static byte letzteSekunde; // zum Merken, wann LCD zuletzt aktualisiert
  if (sekunden==letzteSekunde) return; // in derselben Sekunde nicht mehrfach aktualisieren
  letzteSekunde=sekunden;
  snprintf(linebuf, sizeof(linebuf), "%02d:%02d:%02d", stunden, minuten, sekunden);
  lcd.setCursor(0,0);
  lcd.print(linebuf);
}


void loop() {
  tickTack();
  updateDisplay();
}

guntherb:
Wenn dir michael den fertigen Code gibt hast du nix gelernt.

Fang doch einfach und in kleinen Schritten an:

  1. Irgendwass auf dem LCD darstellen.
    geht? Gut, dann:
  2. eine Zahl darstellen, die langsam (egal wie langsam) hochgezählt wird.
    geht? Gut, dann:
    wie 2. aber ohne delay()! (Siehe Beispiel "Blink without delay")
    geht? Gut, dann:
  3. Eine Zahl bis 10, dann wieder von 0 an zählen lassen.
    geht? Gut, dann:
  4. ....

Nur so wirst du verstehen, wie es funktioniert.

Das halte ich auch für sinnvoll!

Eine Uhr nur mit millis() zu bauen, funktioniert schon.
Meine läuft mit einem PRO MINI 8MHz auf einen Tag mit 3s genau.
Zu Sicherheit mache ich stündlich trotzem ein resync mit der DS1307. (BTW: Aus Gründen des Stromverbrauchs, bis mit jmd eine RTC mit 3,3V präsentiert :wink: )

dankeschön, ich finde diese methode sehr sinnvoll und habe auch gleich funktionen die ich nicht kenne nachgeguckt, wie zb atol, danke dir

Hallo mde110,

wie wäre es mit einer PCF8583?

Die läuft lt. Herstellerangabe mit 1 - 6V.

Wenn Du allerdings genaue Zeit haben willst, dann muss das Ding noch mit einem Trimmer zum 'ziehen' des Uhrenquarzes versehen werden.

Gruß

Martin

hi,

der batterie-eingang einer zb. ds1307 läuft mit bis 3,5V. spricht was dagegen, den zu verwenden?
ist hat dann nicht gepuffert.

gruß stefan

mde110:
Zu Sicherheit mache ich stündlich trotzem ein resync mit der DS1307. (BTW: Aus Gründen des Stromverbrauchs, bis mit jmd eine RTC mit 3,3V präsentiert :wink: )

Ein DS3231 kostet etwa 3€, ist deutlich genauer als ein DS1307 und funktioniert prima mit 3,3V (habe ich sowohl am DUE als auch am MEGA im Einsatz)

Viele Grüße, paulinchen

Wo gibts den PCF8583 und wo den DS3231 für 3€?

mde110:
Wo gibts den PCF8583 und wo den DS3231 für 3€?

DS3231 Modul für 3,99€

PCF8583 IC für 3,28€