millis ; zählt nicht wie ich es möchte

Hi, ich habe ein Problem mit millis().
Ich zähle mit millis meinen eigenen Counter, nur leider ist er nicht so schnell. Bei einer Minute von millis, ist mein Counter gerade bei 30 sekunden. Ich habe selber kein delay verwendet und in den Lib´s sind auf den ersten Bilck auch keine.

if (millis() - altMillis >= 1000)                           //**Hier l�uft millis richtig
	{								  // aber sekunden z�hlt zu langsam
		altMillis = millis();		                         // ca. 30 sec hinterher
		sekunden++;					  //warum???????
	 }

Ich gebe es über Serial aus, also beide werte, einmal millis und meine sekunden und sie zählen unterschiedlich. Es sieht fast so aus, als ob der Code stoppt. Ich habe die Dallas_Lib im verdacht?!

Wenn Delay verwendet wird, bleibt dann auch millis stehen oder zählt der weiter?

Warum sind meine sekunden langsamer als millis()???

Wer kann mir hier bei helfen?

MfG Marco

bordcomputer_temp_test.ino (5.66 KB)

Dallas_Temp.ino (1.33 KB)

DRZ_Messer.ino (441 Bytes)

eeprom_service.ino (1008 Bytes)

sketch_apr03a.ino (2 Bytes)

Dir entgeht die Zeit, welche in anderen Routinen verplempert wird.

Die Aufholjagd ist eröffnet:

if (millis() - altMillis >= 1000)                        
{                               
        altMillis +=1000;                         
        sekunden++;                 
}

Hallo,

irgendwas dauert demzufolge länger wie 1sec. Dein >=1000 ist ja immer gültig ab 1000ms. Können auch 5678ms sein, funktioniert. Nur du weist nicht wie weit die Differenz von 1000 wirklich abweicht.

Lasse dir mal als Debugausgabe die aktuelle Differenz ausgeben.

Könnte auch sein das deine unteren vielen Seriellen Ausgaben dazu führen. Kannst auch probieren schneller als 9600 Baud zuverwenden. Bis 57600 sollte immer funktionieren. Oder nimmst mal >=2000 und addierst 2 statt 1.

Das Entfernen von detachInterrupt() und attachInterrupt() aus der ISR könnte auch dem Programmablauf helfen, beides ist zumindestens völlig überflüssig, da während der ISR die Interrupts sowieso gesperrt sind.

Die Sensoren laufen standardmäßig glaube ich mit 9 Bit. Damit blockiert requestTemperatures() 94ms. Das alleine erklärt das aber nicht.

Hi, ich lass mir beide Zeitwerte ausgeben und da sieht man, das millis "normal" läuft und nur meine zeit langsame ist. So, als würde der Code noch irgendwas anderes machen. Deswegen auch die Frage, ob millis weiter zählt, auch wenn man delay verwendet? Mir ist es nicht ganz klar. Ich würde sagen, das millis nicht von delay beeinflusst wird. :(

@Whandall : wie meinst du das? Soll ich detachInterrupt entfernen? Hast du einen Code zu testen/lesen?? :) :)

MfG Marco

Hallo,

das was du beschreibst ist DER ganz normale Vorgang was passiert. Völlig normal.
millis zählt immer weiter, egal was der Code macht.
Das ist quasi die µC eigene Uhr wenn man so will, Arduinoisches Feature.

Und jeder Code benötigt Zeit. Das geht nicht mit 0,000ms aus. Deswegen driftet das alles wie du schreibst völlig normal mit der Zeit auseinander.

Dein Dallas Code. Scheint nicht die Blockierungsfreie Variante zu sein. Oder?

Abhilfe schafft wie combie andeutete, den alten Zählerstand mit einem festen Wert nachzuziehen. Dann bleibt nur eine Startdifferenz übrig die immer gleich bleibt.

Oder du legst von Anfang an feste 1000er Additionsprünge fest für den Vergleichsmilliswert.
Dann bleibt es syncron. Nur wann deine Sekunde inkrementiert wird innerhalb der 1000ms bleibt dennoch variabel. Je nachdem was der restliche Code zu tun hat. Im dümmsten Fall benötigt der restliche Code mal länger wie 1sec. dann geht die dir für deine eigene Sekunde verloren.

Nochwas zu millis. Weis nicht wie genau die Uhr gehen soll. Mit der echten Uhr verglichen driftet millis sehr schnell ab. Weil das hängt von der Quarz/Resonator Genauigkeit ab.

Du kannst ja mal deine loop Zeiten vermessen.
Die Funktion “LoopTiming” wird jeweils ganz am Anfang und ganz am Ende aufgerufen.
Mit 200 Messungen wird die loop demnach 100mal vermessen und dann die Ergebnisse ausgespuckt.
Du wirst dann sehen ob min und max stark auseinander liegen etc.

//LoopTiming();  // Loop Time Messung Start

//LoopTiming();  // Loop Time Messung Ende


/*********************************************************************************
** LoopTiming() v06 by GuntherB & Doc_Arduino @ german Arduino Forum        	**
**********************************************************************************
** Funktion um die Dauer der Loop-Zeiten zu ermitteln				**
** wird in der Loop am Anfang und Ende aufgerufen				**
** benötigt ca (AL * 4 + 16) Byte RAM						**
*********************************************************************************/

void LoopTiming()
{
  const int AL = 200;        // Arraylänge, NUR GERADE Zahlen verwenden!
  static unsigned long LoopTime[AL];
  static unsigned int Index=0, Messung=0, Min=0xFFFF, Max, Avg;
  
  if (Messung % 2 == 0)     // wenn Messung X gerade (0,2,4,6 usw.), entspricht immer Anfang der Loop
    {
     LoopTime[Index] = millis();
     Messung++;
     Index++;    
     return;	            // Funktion sofort beenden, spart bestimmt Zeit
    }

  if (Messung % 2 == 1)     // wenn Messung X ungerade (1,3,5,7 usw.), entspricht immer Ende der Loop
    {
     LoopTime[Index] = millis();
     LoopTime[Index-1] = LoopTime[Index] - LoopTime[Index-1];  	// Loopdauer einen Index niedriger einspeichern wie aktuell
     Messung++;
    }	
	    
  if (Index >= AL) 	// Array voll, Daten auswerten
    {  
     for (int i = 0; i<AL; i++)
       {
        Min = min(Min, LoopTime[i]);
        Max = max(Max, LoopTime[i]);
        Avg += LoopTime[i];
       }
	
     Avg = Avg / AL;
     Serial.print(F("Minimal       "));Serial.print(Min);Serial.println(" ms");
     Serial.print(F("Durchschnitt  "));Serial.print(Avg);Serial.println(" ms");
     Serial.print(F("Maximal       "));Serial.print(Max);Serial.println(" ms");
     Min = 0xFFFF;
     Max = 0;
     Avg = 0;
     Messung = 0;
     Index = 0;
    }
}

Hi, Danke für die Anregungen, werde nachher es versuchen.

@Doc_Arduino "Dein Dallas Code. Scheint nicht die Blockierungsfreie Variante zu sein. Oder?"

Nein, meine Version hat noch unterbrechungen! Welche Version meinst du? Welche Lib?

MfG Marco

Hallo,

was machen denn deine loop Zeiten?

Ich nehme sicherlich die gleiche wie du. https://github.com/milesburton/Arduino-Temperature-Control-Library Wobei es hier wieder ein Update gab wie ich sehe zu der Version die ich noch habe. Egal. Darin sind Bsp. enthalten ohne zu blockieren. Es wird ein Request rausgeschickt. Dann müßte man ja warten, 100ms bis 750ms je nach Sensor und Auflösung, dann werden die Temps abgefragt. Ohne Blockierung mittels millis, innerhalb der 100...750ms kann die loop andere Dinge erledigen. Schau dir die Bsp. Meine Grundlage ist und war "WaitforConversion2".

So nun habe ich einiges Versuch und mir raucht der Kopf und ich bin auf 180!!!!! >:( >:( >:( >:(

Ich habe die Zeit gemessen und das sind die Werte : min 0ms;durchschnitt 166ms; max 24991ms die anderen Werte liegen so in der Nähe. Aber irgendwie kommt die Ausgabe nur sehr selten. Ist das so richtig oder falsch?

Ich habe aber auch einen Fehler von mir gefunden und zwar hatte ich die Dallas abfrage, in die LCD Ausgabe getan und so hat es sich beides beeinflusst. Keine Ahnung was mich da geritten hat :confused: Jetzt schreibe ich es in eine Variable und nun funktioniert mein Zeit Zählung auch so in etwa ( +/- sekunde) aber damit kann ich erst mal leben.

Nun gibt es aber ein neues größeres Problem, aber dazu mache ich einen neuen Post auf.

Danke

MfG Marco

Hallo,

das Ausgabeintervall der loop-Messung hängt natürlich von den Duchlaufzeiten der loop selbst ab. Logisch. Es werden mit Setting AL=200, dann 100 Messungen gemacht, also 100 mal muß die loop durch sein. Wenn die mehrfach nahe 24sec liegt, dann dauert das entsprechend. AL kannste auch auf 100 setzen. Nur selten sinnvoll. Anhand des Maximums von 24sec, sagt dir allerdings auch, dass hier etwas heftig blockiert bzw. blockierte. Was sind jetzt deine Zeiten? Über 100ms sollte das max. nicht liegen. Selbst mit paar seriellen Ausgabe nicht.