millis(), umrechnen ms in sekunde und dann auswerten

Hi, ich möchte die Zeitdifferenz in ms umrechnen in sekunde und dann mit dem Wert vergleichen. Ich hatte es schon irgendwo gelesen, vielleicht hier im Forum oder im Netz aber ich kann es nicht mehr finden. Bei größeren Zeit Werten, finde ich es übersichtlicher, wenn der Wert in sekunde ist. Ich möchte eine "Zeitschaltuhr" die nur einmal am Tag (besser Abends) eine Lampe einschatet und diese nach ca 2 Stunden wieder ausschaltet. ( keine zusätzliche Hardware! ) mehr nicht! Hier ein kleiner test Code: letzteMillis ist unsig long

  if ((millis() - letzteMillis) / 1000 > 2 )  // differenz geteilt durch 1000 (ms -> s ) größer 2s
  {                                           // leider geht es so nicht, wie ist richtig
      digitalWrite(led, HIGH);

  }
 if(millis() - letzteMillis >3000)      // das geht, aber größere Zeit werden dann unübersichtlich zB  2Stunden
{
    digitalWrite(led, LOW);
     letzteMillis = millis();
}

MfG Marco

ich sehe denn sinn nicht so richtig, aber Du könntest es mit defines machen. hier das blink-beispiel:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */
#define Sek *1000 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2 Sek);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(3 Sek);               // wait for a second
}

das kannst Du auch mit minuten und stunden machen und dann sogar zusammenzählen, etwa: 2 Std + 30 Min

gruß stefan

oh je, millis() durch delay ersetzen ist aber ein ganz schlechter Tip!!!!!!!!

@Marco ich erkenne auf Anhieb keinen Fehler sollte eigentlich laufen. Geht die LED gar nicht an oder was passiert?

hi,

keiner will hier millis durch delay ersetzen. da hast Du schlecht gelesen. er möchte nur die großen zahlen bei millis loswerden.

gruß stefan

Oder so:

if(millis() - previousMillis > 60000UL * 3)

60000 sind 1 Minute in ms. Dann sieht man an dem Faktor dahinter sofort die Minuten.

Nochmal mal 60 und man hat Stunden:

if(millis() - previousMillis > 60000UL * 60 * 2)

Kann man auch so machen (ähnlich wie das Makro oben):

const unsigned long MINUTE = 60000UL;
const unsigned long HOUR = MINUTE * 60;

if(millis() - previousMillis > MINUTE * 3)

Hallo,

Dein erstes if kann so nicht richtig funktionieren. Punktrechnung geht vor Strichrechnung. Da fehlt mindestens eine Klammer.

Zur Lösung gibt’s wohl mehrere Möglichkeiten.

Man könnte die aktuellen millis gleich in Sekunden umrechnen. Dann haste das wie schon gesagt, auch wieder nur für einen Bereich übersichtlicher.

unsigned long aktuelle_Sekunden;
unsigned long letzte_Sekunden;

aktuelle_Sekunden = millis() / 1000;

if(aktuelle_Sekunden - letzte_Sekunden > 3000)    
{
	digitalWrite(led, LOW);
	letzte_Sekunden = aktuelle_Sekunden;
}

ich hab da aber nochwas anzubieten. Hab mir eine Funktion gebaut, die die aktuellen ms ins h:mm:ss Format umwandelt.

Aufruf mit:   time_ms_vereinzeln (millis() );    // Millisekunden seit µC Reset zerlegen für hh:mm:ss Format

void time_ms_vereinzeln (unsigned long mSekunden)
{   // Zeit in ms seit µC Reset wird zerlegt für hh:mm:ss Format
 mSekunden = mSekunden/1000;         // Bsp. aus 8.000.000millis werden 8000sec
 LaufendeStunden = mSekunden/3600;   // 8000/3600=2,22 > 2h
 LaufendeMinuten = (mSekunden/60)-(LaufendeStunden*60);  // (8000/60)-(2*60)=13min
 LaufendeSekunden = mSekunden-(LaufendeStunden*3600)-(LaufendeMinuten*60); // 8000-7200-780=20sec
}

Damit hätte man die laufenden Stunden, Minuten und Sekunden einzeln seit letzten µC Reset. Alle 3 als unsigned long definieren.

Wenn ich keinen Denkfehler habe und das weiter ab ändere für Dich, könnte man die 3 Zahlen zu einer zusammenfassen.
Ohne Doppelpunkte. Zum Bsp. 2h:33:15sec. zu 23315 mittels kleiner Rechnung

zum Bsp. so
// eine Funktion meinetwegen
unsigned long Zeitstempel = 0;
Zeitstempel = LaufendeStunden * 10000; // aus 2h werden 20000
Zeitstempel = Zeitstempel + LaufendeMinuten*100; // 20000 + 3300 = 23300
Zeitstempel = Zeitstempel + LaufenSekunden; // 23300 + 15 = 23315

Und jetzt könnte man zwei Uhrzeiten vergleichen, Bsp. 2:33:15 Uhr gegen 3:45:30 Uhr
if (Zeitstempel >= 34530) … dann mach was sinnvolles

Hallo,

oder noch anders. Man rechnet die Zeit dezimal. Machen viele Firmen mit der Zeitabrechnung so. Man muß nur immer umdenken was nun was ist. 30min sind dann 0,5h und solcher Mist. Ist nicht so übersichtlich für Deinen Fall denke ich.

Hallo, ich weiß so recht nicht, was Du möchtest. millis() in Sekunden oder Stunden umrechnen, dass kann es ja wohl nicht sein? Wie möchtest Du denn, das es funktioniert- ohne Hardware? Nehmen wird einmal an, Du willst die Lampe um 18:00h einschalten. Wie willst Du denn wann starten. Du versorgst den Arduino um 13:00h mit Spannung und dieser "zählt" dann bis 18:00h seine millis() runter? Wenn er das gemacht hat, zählt er 22 Stunden weiter?

Deklariere Dir doch am Anfang des Sketch Deine Zeiten zum starten, ein- und ausschalten in einer Einheit Deiner Wahl, z.B. Std, Min und Sek.. Das umrechnen in millis() und zurück überläßt Du dann dem Arduino… Gruß und Spaß Andreas

Hallo,

hab mir das nochmal durchgelesen. Wenn Du wirklich mit "Zeitschaltuhr" eine Zeitschaltuhr meinst, dann kommst Du um eine RTC ( DS3231 RTC Modul, I2C Bus ) nicht drumherum. Sonst stimmen Deine millis hinten und vorne nicht mehr nach Stromwegnahme oder so. Dann kann der µC zu definierten Zeiten die Lampe selbstständig ein- und ausschalten.

Die millis machen nur Sinn, wenn Du den Arduino Strom gibts, die Lampe mit einem Taster einschaltest und der µC die Lampe nur selbstständig nach definierter Zeit ausschalten soll. Oder Arduino Strom geben, Lampe geht damit sofort an und nach Zeit x wieder aus. Dabei macht die gesamte Umrechnung der ms keinen Sinn mehr. Da Du ja nicht perment die Einschaltdauer änderst, die ist einmalig im Sketch hinterlegt. Da würde mir ein Kommentar reichen wieviel ms das in h:mm:sec sind.

Jetzt bist Du dran.

Alternativ wäre ein DCF77 Modul auch eine Lösung, dann spart er sich auch noch die Zeit einzustellen. Libraries dafür gibt es ja wie Sand am Meer. Und das Problem mit dem "Störnebel" im Haus ist mit meiner Library http://blog.blinkenlight.net/experiments/dcf77/dcf77-library/ auch kein Problem mehr ;)

Allerdings geht das nicht mit einem Uno, da muß schon was besseres her, also mein Blinkenlighty oder z.B. ein Olimexino.

Auf dem standard Uno kann man jedenfalls die millis() vergessen. Da sind Abweichungen von 1-10 Minuten pro Tag nicht selten.

Hallo,
DANKE erst mal für die vielen Tipps XD . Eigentlich wollte ich nur die Zeitdifferenz in Minuten oder Stunden, damit ich zB 2s schreibe und nicht 2000 ms oder eben für Stunden das gleiche. Es ist keine Schaltuhr, dafür hätte ich mehrere RTC´s .
Ich schalte das Licht über LDR ein und möchte das es nach 2h wieder aus geht.
Wie gesagt, ich hatte ein variante irgendwo gesehen, bei der der Differenzwert durch 1000 geteilt wurde und dann nur mit sekunde ( millis-letztemillis / 1000 > 2s , als Beispiel). Eure vorschläge werde ich test, Danke.
Hintergrund ist, das ich diese Variante im Code verwende, den ein Freund auch nutzt, so das er die Werte eben schneller erkennt unnd ändern kann.
Danke :smiley:

MfG Marco

Hallo Udo. Welches Board würde man für deine DCF77-Library verwenden können, wenn man mindestens 27 digitale I/O Pins benötigt? Ich habe hier zwei Mega 2560 liegen (Original und China Nachbau), die beide zu ungenau sind. Kann man den Crystal auslöten und statt dessen einen genaueren einlöten?

Ich weiß jetzt nicht ob sich das auf die DFC77 Bibliotehek von Udo bezieht oder auf die Ungenauigkeit der millis() da der Standart-Arduino UNO einen ziemlich ungenauen Resonator hat und keinen Quarz.

Grüße Uwe

Wenn Du den Timercode anpasst und sowieso einen Lötkolben in die Hand nimmst ist das Board egal. Einfach auf das gewünschte Board einen Quarz statt Resonator löten. Fuses anpassen und Timercode ggf. anpassen fertig.

Allerdings frage ich mich was das für eine Schaltuhr ist die 27 digitale IO Kanäle brauchen soll. Bei Zeiträumen um die 2h schaltet man doch eher auf Minuten oder auf Sekunden genau. Bei der langsamen Schalthäufigkeit kann man doch locker hunderte von Ausgängen per Schieberegister bedienen.

Mega Board mit Quarz:
http://www.komputer.de/zen/index.php?main_page=product_info&cPath=21&products_id=191
Die Buchsenleisten sind etwas krumm verlötet aber ansonsten ist alles ok

Ein UNO mit I2C Port Expandern käme aber auch infrage

Der UNO gerade eben nicht, der UNO hat einen Resonator. Mein Blinkenlighty oder ein Olimexino haben einen Quarz.

Ok, ich meinte auch eher ein UNO-ähnliches Board mit Quarz :p

oder ein paar 74HC595 - pro Stück 8 Ausgänge, macht mein vieren 32 ;)

[quote author=Udo Klein link=topic=253546.msg1836113#msg1836113 date=1407574826] Einfach auf das gewünschte Board einen Quarz statt Resonator löten. Fuses anpassen und Timercode ggf. anpassen fertig. [/quote] Gibt es dafür eine Anleitung im Netz? Welchen Quarz würde man dafür nehmen?

[quote author=Udo Klein link=topic=253546.msg1836113#msg1836113 date=1407574826] Bei der langsamen Schalthäufigkeit kann man doch locker hunderte von Ausgängen per Schieberegister bedienen. [/quote] OK. Schieberegister kannte ich bisher nicht. Werde ich dann wohl mal angehen. Vielen Dank!

krl: [quote author=Udo Klein link=topic=253546.msg1836113#msg1836113 date=1407574826] Bei der langsamen Schalthäufigkeit kann man doch locker hunderte von Ausgängen per Schieberegister bedienen.

OK. Schieberegister kannte ich bisher nicht. Werde ich dann wohl mal angehen. Vielen Dank! [/quote] Theoretisch schon. Praktisch solltest du dann ab ca. 10 Schieberegistern für alle Pins, die parallel von allen Registern liegen, Bustreiber spendieren. Das wären zumindest SH_CP Shiftregister Clock input, ST_CP Storageregister Clock input, falls nicht fest verschaltet, Output Enable auch noch. Aber den wirst du nicht benötigen. Der ist bei Anzeigen zum gemeinsamen dimmen nützlich. Theoretisch wird ein CMOS Eingang leistungslos angesteuert und ein Ausgang könnte unbegrenzt viele davon schalten. Statisch betrachtet, stimmt das so. Dynamisch sieht die Sache dann etwas anders aus. Jeder Eingang hat eine Eingangskapazität von wenigen Picofarad. Die müssen bei jedem Pegelwechsel umgeladen werden. Liegen davon sehr viele parallel, dann hat der Ausgang ganz schön zu ackern. Deshalb würde ich aus dem Bauch heraus ab 10 zu treibenden Eingängen einen Treiber spendieren. Das kann ein einfaches Gatter eines Logik-IC sein. Entweder gleich ein IC mit nichtinverterenden Treibern suchen, oder zwei Inverter in Reihe schalten - oder beim Code schreiben einfach den Pegel auf der Leitung invertieren :) Weiterhin sollte jedes Schieberegister einen Keramikkondensator so dicht wie irgendmöglich auf der Stromversorgung haben. So 33-100nF, was man gerade da hat. Weiterhin sollten ca. alle 4 IC ein kleiner Elko (ich nehme 47µF) kommen. Dies dient der Siebung der Betriebsspannung, da bei Schaltvorgängen im IC kurzzeitig für wenige Nanosekunden Lastspitzen auftreten, ode gänzlich ohne Pufferung ein Einbrechen der Versorgungsspannung und im Extremfall "wunderliches Verhalten" der Schaltung zur Folge haben. Weiterhin sollte die Versorgungsspannung sternförmig zu den IC's verlegt werden und nicht in Reihe, wie eine Lichterkette. Wenn 3-4 an einem Strang hängen und E-förmig verdrahtet wird, gibt es auch noch keinen Ärger, aber wenn 10 und mehr ICs so in Reihe verkabelt sind, kann's u.U. komisch werden. Früher, in den Einführungsbüchern über Digitaltechnik, als man logische Funktionen aus einzelnen Zählern, Flipflops, Gattern und Schieberegistern aufbaute, wurden jedem Einsteiger diese Designregeln regelrecht eingeimpft. Je komplexer eine Schaltung wird, umso wichtiger wird es, auf derartige Designregeln zu achten.

Gruß Gerald