Forum: Mikrocontroller und Digitale Elektronik Ausführen von Funktionen alle x ms


von timer (Gast)


Lesenswert?

Hi,

folgendes Problem:

Ich möchte, dass bestimmte Funktionen alle x ms ausgeführt werden. 
Beispiel:

Zeitstempel seit Start|Funktion
0    | A
150  | B
300  | A
450  | B
600  | A
750  | B
900  | A
1150 | C
1300 | B
1450 | A

usw. Also jeweils 150ms Abstand zwischen den Funktionen. C aber zB nur 
bei jedem 8ten Durchlauf. Das Ganze möchte ich ohne delays bauen.

Jemand eine Idee, wie man das machen kann?

von olaf (Gast)


Lesenswert?

Nutze deinen Namen Und die Funktion Brain.

von Olaf (Gast)


Lesenswert?

Du setzt einen Timer auf der alle 50ms eine Interruptfunktion mit einer 
Statemachine oder internen Zaehlen aufruft. Dort schaust du dann welche 
Funktion gestartet werden soll. Entweder ist die Funktionalitaet sehr 
banal, z.B einen Port setzen, dann fuehrst du sie direkt aus. Oder sie 
ist komplexer, dann setzt du ein Startflag welches in deinem 
Hauptprogramm beachtung findet.

Olaf

von Uwe (de0508)


Lesenswert?

Guten Morgen,

ja wurde "2003" von Peter Dannegger erfunden:

Beitrag "Wartezeiten effektiv (Scheduler)"

Damit lassen sich ohne Vorkenntnisse zeitabhängige Prozesse erstellen.

Wenn man das Prinzip mal erkannt und verstanden hat, geht es auch mit 
eigenem Code.

von Kermit (Gast)


Lesenswert?

Ich verstehe das Problem nicht. Das ist doch ein klassischer 
Timer-Interrupt. Alle 150ms löst der Timer-Interrupt aus. In der 
Interrupt-Routine wird halt ein Counter gezählt und bei erreichen von 8 
die gewünschte Funktion ausgeführt und Timer wieder zurückgesetzt.

von STK500-Besitzer (Gast)


Lesenswert?

Unter der Vorraussetzung, dass die Funktionen nicht länger als 150 ms 
brauchen, kannst du einfach alls 150ms einen Timer-Interrupt auslösen. 
Der setzt ein Flag, auf das eine Warteschleife in der Hauptroutine 
wartet.
Daraufhin wird eine der Funktionen in Abhängigkeit zu einer 
Zählvariablen gestartet. Danach wird die Zählvariable um 1 
inkrementiert.
Wenn sich die Geschichte bei jedem 8. Durchlauf wiederholt, kann man die 
Zählvariable auch auf den Bereich 0-7 reduzieren, indem man sie bei 8 
auf 0 zurücksetzt.

von Tom Thomsen (Gast)


Lesenswert?

Kermit schrieb:
> Alle 150ms löst der Timer-Interrupt aus.

Wie soll man damit auf 1150ms kommen?

von Dieter F. (Gast)


Lesenswert?

Tom Thomsen schrieb:
> Wie soll man damit auf 1150ms kommen?

Indem man 900 + 150 korrekt mit 1050 berechnet (und nicht mit 1150) :-)

Gesucht waren 150er Schritte ...

von STK500-Besitzer (Gast)


Lesenswert?

Tom Thomsen schrieb:
> Wie soll man damit auf 1150ms kommen?

Da ich auch den gleichen "Mist" geschrieben habe:
Einfach die Zeitbasis passend verringern und die Vergleichswerte der 
Zählvariable entsprechend anpassen. (50ms wurden ja schon 
vorgeschlagen).

von timer (Gast)


Lesenswert?

Habs jetzt so gelöst:

Das results array beinhaltet alle Funktionen, die im 150ms Takt 
aufgerufen werden könnten. #x gibt funktionen an, die nur bei jedem 
x-ten Durchlaufen kommen. Aufruflogik fehlt noch
1
#include <Metro.h> 
2
Metro ledMetro = Metro(250); 
3
4
#define ARRAYSIZE 10
5
char * results[]={
6
 "A",
7
 "B",
8
 "#8-C"
9
};
10
int lastValuePointer = 0;
11
int loopCount = 0;
12
13
void setup()
14
{
15
  Serial.begin(19200);
16
  delay(100);
17
}
18
19
void increaseLoopCounter() {
20
    lastValuePointer++;
21
    
22
    int arraySize = sizeof(results)/sizeof(char *);
23
    
24
    if(lastValuePointer == arraySize) lastValuePointer = 0;
25
    
26
    loopCount++;
27
    if(loopCount > 8) loopCount = 0;  
28
}
29
30
void loop()
31
{
32
  String valueToCheck;
33
  if (ledMetro.check() == 1) {
34
   
35
    while(true) {
36
      valueToCheck = results[lastValuePointer];    
37
    
38
      if(valueToCheck.indexOf("#") != -1) {
39
         String repeatIndex = valueToCheck.substring(1, valueToCheck.indexOf("-"));
40
         String delayedValue = valueToCheck.substring(valueToCheck.indexOf("-") + 1, valueToCheck.length());
41
       
42
         if(loopCount == repeatIndex.toInt()) {
43
           valueToCheck = delayedValue;
44
           break;
45
         }
46
         
47
         increaseLoopCounter();
48
         continue;   
49
      }    
50
      break;
51
    } 
52
    
53
    Serial.println(valueToCheck);
54
    increaseLoopCounter();
55
  }
56
  
57
  delay(13);   
58
}

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

das sieht alles recht kompliziert und schlecht erweiterbar aus, und dann 
noch die vielen Stringfunktionen.
Mach doch folgendes (hab ich schon für Animationen auf einem Display so 
ähnlich umgesetzt)

lege ein Struct an das folgende Informationen aufnimmt:
aktueller Zähler (AZ), Zählerreset (ZR), PTR auf Funktionsaufruf

In ein Array legst du nun die Structs die im Programm gerade gebraucht 
werden.
Ausgelöst vom Timer gehst du nun das Array durch und erhöhst (AZ),wenn 
(AZ) >= (ZR) dann setzt du (AZ) auf null und führst die Funktion aus. Um 
einen Zeitlichen versatz zu erreichen Initialisierst du halt (AZ) nicht 
mit null.
Würde bei Dir in etwa folgendermaßen aussehen:
struct a;  1, 2, *A
struct b;  0, 2, *B
struct c;  0, 8, *C

Was aus deiner Aufgabenstellung nicht klar hervorgeht ist, ob bei 
Ausführung von C die Bearbeitung von A/B ausgesetzt wird. Sieht in der 
Tabelle so aus klingt aber im Text nicht so.
Dafür könnte man im Struct natürlich noch einen Zähler unterbringen der 
alle x-Schritte ein Aussetzten der normalen Zählung von (AZ) bewirkt.
Die Möglichkeiten sind unbegrenzt.

Sascha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.