Zykluszeiten messen

Hallo zusammen,

in einem anderem Thread läuft ja grad ein gespräch über Zykluszeiten usw. Da wollte ich jetzt mal nicht dazwischen funken, aber eins interessiert mich trotzdem:

Wie kann man (sinnvoll) die Zykluszeit ermitteln? Weil am Codeanfang millis() speichern und am Codeende zum akt. millis() abziehn und das dann im Serialmonitor ausgeben schleudert einen ja nur mit zahlen zu, die zudem ja auch sehr Unterschiedlich sein können.

Wär es da sinnvoll, die Zeit von z. B. 100 Zyklen zu messen, den Durchschnittswert berechnen und das dann ausgeben?

Oder wie ermittelt ihr eure Zykluszeit?

LG

Fipsi

hi,

ja, so würde ich das machen, eventuell auch noch höchst- und mindestzeit für einen zyklus festhalten, um eventuelle "ausreißer" zu erwischen. wichtig ist, nicht dauernd, also bei jedem zyklus seriell zu senden, weil das dauert meist am längstan.

gruß stefan

Fipsi: Wär es da sinnvoll, die Zeit von z. B. 100 Zyklen zu messen, den Durchschnittswert berechnen und das dann ausgeben?

Oder wie ermittelt ihr eure Zykluszeit?

Wenn die Zykluszeiten durchschnittlich immer gleich lang sind, kannst Du natürlich die Zeit über 100, 1000 oder 10000 Zyklen messen und von Zeit zu Zeit über Serial ausgeben lassen:

unsigned long cycleTime;
unsigned int cycleCount;
void loop() {
  // Zuerst die ganz normalen Funktionen aufrufen
  eingabe();
  verarbeitung();
  ausgabe();
  // Dann die Zeiterfassung hinten dran hängen
  cycleCount++;
  if (cycleCount>=10000)
  {
    Serial.print("Cycle Time: ");
    Serial.print((micros()-cycleTime)/cycleCount);
    Serial.println(" microseconds");
    cycleCount=0;
    cycleTime=micros();
  }
}

Wobei man relativ kurze Zeiten besser mit micros() als mit millis() erfasst.

Natürlich kannst Du so etwas auch noch aufbohren, und zum Beispiel in der Zeiterfassung auch die Zeiten für - den kürzesten Zyklus - den längsten Zyklus - die durchschnittliche Zyklusdauer ermitteln Das würde natürlich aufschlußreich sein, wenn der durchlaufene Zyklus nicht jedesmal gleich lange dauert, sondern unterschiedliche Zyklen durchlaufen werden, also z.B. mal im Zyklus ein "analogRead()" oder eine Sensorabfrage drin ist, und in anderen Zyklusdurchläufen nicht.

Aber je mehr Du hinten an Statistiken hintendranstrickst, desto mehr verfälscht natürlich die Messung an sich auch die gemessenen Werte, d.h. die gemessenen Zeiten werden durch die Zusatzfunktionen länger.

So ungefähr hatte ich mir das vorgestellt.

Das man das besser mit micros() macht, war mir klar, aber reference war da grad Offline und ich wusste nicht mehr genau, wie der Befehl hieß, da ich nur mit millis() arbeite.. Danke^^.

Danke für eure beiden Antworten. Ich war mir eben nicht sicher, ob das so klappen könnte.

Aber wo du das grad mit analogRead() erwähnst: braucht dieser Befehl so ewig lang oder wie?

LG

Fipsi

P.S.: Wobei ich jetzt ehrlich sagen muss, "lang" ist immer relativ. Wenn ich überleg, wie lang mein Hirn für einen solchen Durchlauf brauchen würde... hust.

Wie kann man (sinnvoll) die Zykluszeit ermitteln?

Ich mache mir in loop() einen zyklus++ Und alle Sekunde (oder länger) lasse ich mir den anzeigen, und setze ihn wieder auf 0

Damit habe ich nicht direkt die Zykluszeit, aber aus der Anzahl Durchläufe lässt sich auch schön auf die Last schließen. Und natürlich auch die durchschnittliche Zykluszeit berechnen.

Fipsi: Wobei ich jetzt ehrlich sagen muss, "lang" ist immer relativ.

Tatsächlich ist "lang" immer relativ.

Wie lange ein "analogRead()" zum Beispiel im Vergleich zu einem "digitalRead()" benötigt, kannst Du mit diesem Sketch leicht austesten.

void setup() {
  Serial.begin(9600);
}

#define PIN A2
int messwert;

void eingabe()
{
  messwert= analogRead(PIN);
//  messwert= digitalRead(PIN);
}

unsigned long cycleTime;
unsigned int cycleCount;

void loop() {
  eingabe();
  // Dann die Zeiterfassung hinten dran hängen
  cycleCount++;
  if (cycleCount>=10000)
  {
    Serial.print("Cycle Time: ");
    Serial.print((micros()-cycleTime)/cycleCount);
    Serial.println(" microseconds");
    cycleCount=0;
    cycleTime=micros();
  }
}

Einfach in der eingabe()-Funktion mal entweder die eine Funktion auskommentieren und mit der anderen messen, oder umgekehrt. Dann siehst Du, wie sich die Zykluszeit verändert, wenn Du einen Pin per analogRead oder per digitalRead abfragst.

Okay.. das ist nicht nur relativ gesehen ein unterschied wie Tag und Nacht o,O

Analog: 112 µs Digital: 7 µs

Mein USB-Konverter geht grad als Discokugel durch (wegen der TX-LED).

Muss ich bei meinen Temrinals dann auch mal aufspielen. Dürfte dann aber theoretisch nicht über 500 µs liegen, weil bei mir auch alles in if's ist.

LG

Fipsi

Wow. Das überrascht mich jetzt echt:

Ein Zyklus, ohne, dass was besonders ausgeführt wird, also "im Normalbetrieb": 18 µs. Heißt: gut gemacht? :D

LG

Fipsi

Hallo,

wenn ich dafür etwas beisteuern darf. Das Forum lebt davon. ;) Das Grundgerüst und Grundidee stammt von unserem GuntherB, muß ich fairerweise dazu sagen. Wird am Anfang und Ende der loop mit LoopTiming(); aufgerufen. Mit der Anzahl der Messungen [AL] sollte man es nicht übertreiben, wegen dem RAM Verbrauch. Gerade beim Uno. millis() kann man durch micros() ersetzen.

/*********************************************************************************
** 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 = 100;        // 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

Joar, so ungefähr hatte ich mir das vorgestellt^^. Wusst bloß nicht, dass es das schon fertig gibt. Muss aber dazu sagen, solang meine Schaltung keinen Tastendruck oder Daten verpennt, ist das Ding ausreichend schnell genug. Und mit 18 µs, ist es das ganz sicher^^.

Was meinst du mit "Das Forum lebt davon. ;)"? Wovon lebt es? dass Funktionalitäten nachgefragt werden? Oder was meinst du?^^

LG

Fipsi

Hallo,

ich meine, das Forum lebt von Fragen und Antworten und eben auch von funktionierenden Code Beispielen die jemand hier und da zur Verfügung stellt. Es muß ja keine umfangreiche Funktion sein, aber ein Denkansatz der funktioniert und den man dann für seine Zwecke abändern und ausbauen kann. Meistens fehlt ja nur der erste Anstoß.

Jez hab ich verstanden, was du für nen Zusammenhang gemeint hast.

Aber ansonsten wär das Forum sinnlos, ja^^ Bin aber dankbar für das Forum und die Hilfe, die ich hier bekomm^^.

LG

Fipsi