Zeitversetzt Ausgänge für variable Zeit steuern

Hallo,

mein Name ist Matthias und ich lese hier bereits eine lange Zeit mit.
Nun zu meinem ersten Problem bei dem ich anscheinend komplett ein Brett vor dem Kopf habe. Ich finde einfach keinen Einstig in die Lösung.
Daher habe ich auch hierzu leider noch keinen Code.

Hier zu meinem Problem:

Es geht darum vier Ausgänge für eine variable Zeit zu schalten dieses allerdings Zeitversetzt.
(Steuerung der Einspritzdüsen eines 4 Zylinder 4-Takt Motor).

Folgende Variablen:

Zykluszeit für alle 4 Zylinder 20 - 500ms
Einschaltdauer pro Zylinder 0-20ms

Zum Beispiel: Gesamt 100ms - Zylinder 10ms

Zeitpunkt und An Zeiten
0ms Zylinder 1 10ms an
25ms Zylinder 2 10ms an
50ms Zylinder 3 10ms an
75ms Zylinder 4 10ms an

100ms Zylinder 1 10ms an
125ms Zylinder 2 10ms an
150ms Zylinder 3 10ms an
175ms Zylinder 4 10ms an
... usw

Soweit noch kein Problem...

Aber bei z.B. Gesamt 40ms - Zylinder 20ms
0ms Zylinder 1 20ms an
10ms Zylinder 2 20ms an
20ms Zylinder 3 20ms an
30ms Zylinder 4 20ms an

40ms Zylinder 1 20ms an
50ms Zylinder 2 20ms an
60ms Zylinder 3 20ms an
70ms Zylinder 4 20ms an
... usw

Hier "überlappen" sich die Ausgänge und bei mir überlappt sich der Knoten im Gehirn... :confused:

Kann mir hier jemand auf die Sprünge helfen bitte?

Gruß
Matthias

Wo siehst du ein Problem?
Die Ausgänge kannst du doch Zeitversetzt ein und wieder ausschalten.

Wo ist denn dein Sketch?

Hallo,

zu diesem Teil gibt es noch keinen Code da ich nicht weiß wie ich anfangen soll.
Und genau dieses Zeitversetzte mit der überlappung ist mein Problem.

Hallo Knoten, ich hätte Lesestoff für Deine Auflösung: Anleitung: Endlicher Automat mit millis()
Wenn Du das Beispiel um zwei LEDs erweiterst, hast Du schon mal die halbe Miete, dann fehlt nur noch die Synchronisation. Soll "0 ms" ab Reset des Arduino zählen oder von einem Schalter oder Zustand abhängig sein?

HotSystems:
Wo ist denn dein Sketch?

Schreibt er doch, Knoten statt Sketch!

Doc_Arduino:
Hallo,

Deine Mühen sind sehr löblich. Aber Du mußt dir bewußt sein, dass der Thread irgendwann nach hinten rutscht und verschwindet. Ich hab schon ähnliches durch. Du kannst den für dich fertig machen und bei Gelegenheit rausholen. Oder Du schreibst irgendwann ein Buch.

Du siehst meine Strategie gegen das Vergessen: Immer wieder dran erinnern :slight_smile:

Dann lies dir die Basics in der IDE durch.
Da wird genau beschrieben, wie du Leds ein bzw. ausschaltest.
Du schaltest damit dann eben nur deine Ausgänge für die Steuerung der Zylinder. Was sich dahinter befindet hälst du ja geheim.

Beispiel:

Led1 ein;
Led2 ein;
Led1 aus;
Led3 ein;
Led3 aus;
Led2 aus;

usw.

o.s.ä.

agmue:
....
Schreibt er doch, Knoten statt Sketch!Du siehst meine Strategie gegen das Vergessen: Immer wieder dran erinnern :slight_smile:

Nur ein Knoten hilft hier keinem. :wink:

Hallo,

erstmal danke für die Antworten. Wie ich Ausgänge schalte, wie ich millis ohne Delay einsetzte das ist mir schon klar....

Was ich mit "Zylinder" schalte steht oben (Benzineinspritzventile mit 1Ohm Spulen).
Vielleicht zu meinem Hintergrund: Ich bin Elektroniker. Zwar lange aus dem Beruf raus aber die Hintergründe und auch wie ein Mikrocontroller funktioniert ist mir klar.

Agmue: Vielen Dank für den Link zum endlichen Automaten. Um bei dem Beispiel aus dem Link zu bleiben ist bei mir nur so das auch zwei Zustände gleichzeitig sein können.

Im Anhang habe ich mal zwei Zeitabläufe skizziert.
Der obere wäre einfach mit dem Automaten zu machen.

Aber bei Beispiel zwei überlappen sich die Zustände.

Und da isser wieder der Knoten :wink:

Ich werde morgen mal einen Sketch mit einem endlichen Automaten bauen und in hier zur Diskussion stellen. Vielleicht löst sich der Knoten ja beim tippen :wink:

HotSystems:
Nur ein Knoten hilft hier keinem. :wink:

Du bist doch der exzellente Knotenlöser :wink:

Matze7779:
Aber bei Beispiel zwei überlappen sich die Zustände.

Bei meinem Link läuft die Ampel nach den vorgegebenen Zeiten (bei Dir Zylinder eins), dazu in anderem Takt blinkt die blaue LED (Zylinder zwei). Ampel und blaue LED überlappen sich wie unten in Deinem Zeitdiagramm.

Ab wann soll 0 ms zählen?

Ab wann soll 0 ms zählen?

Tasterdruck. Dann laufen die Zyklen bis zur erneuten Betätigung des Tasters.

Hier "überlappen" sich die Ausgänge und bei mir überlappt sich der Knoten im Gehirn...

Das zweite versteh ich nicht :wink:
Da du kein delay verwendest, braucht loop() deutlich weniger als eine ms, und hat viel Zeit entweder festzustellen dass nichts zu tun ist, oder das gleiche wie beim vorigen mal zu machen. ( Was bei digitalWrite in diesen Zeitdimensionen ziemlich wurscht ist. )

Ganz selten ergibt es sich, dass einer der vier Ausgänge anders gesetzt wird als beim vorigen Mal, aber das hat ja erstmal mit den anderen Zylindern nicht viel zu tun.

Ich mag die "endliche Automaten" - Denkweise eigentlich auch nicht, aber ich weiss, dass man alles so sehen kann und damit in den Griff kriegt.
Wenn es dir hilft, denk an 4 "Automaten" gleichzeitig mit je zwei Zuständen. Zusätzlich brauchst du wohl einen Gesamt-Zyklus, der die aktuelle Drehzahl und die Referenz-Zeit für jeden Zylinder ergibt.

Hallo Michael,

was verstehst Du beim zweiten nicht?

Aber ich denke du hast das Problem gut verstanden welches ich meine.
Es ist gut wenn man darüber redet anstatt immer nur zu Grübeln :wink:

Mittlerweile denke ich das ich einen Automaten mit 4 Zustanden brauche. Und dazu 4 Automaten mit zwei Zustanden.

Hier nochmal der Ablauf aus dem zweiten Beispiel im Diagramm:

Zeitpunkt   :   Ausgänge
0ms     Zylinder 1 EIN
5ms     Zylinder 4 AUS
15ms   Zylinder 2 EIN
20ms    Zylinder 1 AUS
30ms  Zylinder 3 EIN
35ms    Zylinder 2 AUS
45ms  Zylinder 4 EIN
50ms Zylinder 3 AUS
usw....

Also Gesamtzyluszeit 60ms (Zylinder 1-4). alle 15ms "startet" ein Zylinder kann aber 20ms laufen...

Dabei ist der Gesamtzyklus (hier 60ms) variablel bis 500ms. Und die Laufzeit für jeden Zylinder auch 0-20ms.

Ich grübel mal weiter....

Aber vielen Dank für eure Zeit! Ist nicht selbstverständlich...

Matze7779:
Mittlerweile denke ich das ich einen Automaten mit 4 Zustanden brauche. Und dazu 4 Automaten mit zwei Zustanden.

Das ist zu kompliziert gedacht. Ein endlicher Automat mit zwei Zuständen für den Taster und eine for-Schleife über alle vier Ausgänge genügt. Die Grafik aus #6 ist eine gute Hilfe :slight_smile:

Ein mehr mathematischer Ansatz wäre, sich ein 60 ms Zeitfenster iMicros=(aktMicros - startMicros) % gesamtMicros zu erzeugen, um dann mittels Relationen eine HIGH- oder LOW-Bedingung zu beschreiben:

digitalWrite(pinZylinder2, (iMicros > 15000UL && iMicros < 35000UL));

Dann ist der Hauptteil mit vier Zeilen erledigt :slight_smile:

Hier mein Vorschlag für "überlappendes Blinken" von LEDs. Lässt sich sicher auch für dein Zylinderproblem anpassen.
Die Idee dahinter ist ein Bit-Pattern pro LED/Ausgang, welches zyklisch durchgetaktet wird. Damit lassen sich auch andere Muster darstellen, aber immer nur auf Basis der Grundtaktes (hier z. B. 20 ms) für ein Bit.

// overlapping LED pattern (bit = 1 means ON)
#define PATTERN1    0x0FFFF000 
#define PATTERN2    0x00FFFF00
#define PATTERN3    0x000FFFF0

// LED pins
#define LED1        4
#define LED2        5
#define LED3        13

// Macro returns HIGH, if addressed bit is set, otherwise LOW. 
#define TEST(idx, pattern)      ((pattern & (1 << idx)) ? HIGH : LOW)


// bit position counter
byte index = 0;

void setup()
{
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
}


void loop()
{
   digitalWrite(LED1, TEST(index, PATTERN1));
   digitalWrite(LED2, TEST(index, PATTERN2));
   digitalWrite(LED3, TEST(index, PATTERN3));
   
   index = (index + 1) % 32;
   delay(20);
}

/Joe

Hallo,

hat ein paar Tage länger gedauert aber kann mal jemand darüber gucken ob ich einen Denkfehler habe?

Ich habe hier das Beispiel von agmue mit dem endlichen Automaten aufgegriffen....

Habe leider kein Oszi da um das zu überprüfen.

Hier mal der Codeschnippsel:

zykluszeit = Gesamtzyklus / 4
Und Einblaszeit ist die Zeit der einzelnen Zylinder...

  if (micros() - previousZyklus >= zykluszeit) {
    switch (zylinderReihenfolge) {
      case 1:
        zylinder1Status = 1;
        previousZyklus = micros();
        zylinderReihenfolge = 2;
        break;
      case 2:
        zylinder2Status = 1;
        previousZyklus = micros();
        zylinderReihenfolge = 3;
        break;
      case 3:
        zylinder3Status = 1;
        previousZyklus = micros();
        zylinderReihenfolge = 4;
        break;
      case 4:
        zylinder4Status = 1;
        previousZyklus = micros();
        zylinderReihenfolge = 1;
        break;
    }
  }

  if (zylinder1Status == 1) previousZylinder1 = micros();
  if((micros() - previousZylinder1 < einblaszeit_micros) ) {
    zylinder1Status = 0;
    digitalWrite(zylinder1pin,LOW);
  } else {
    digitalWrite(zylinder1pin,HIGH);
  }

  if (zylinder2Status == 1) previousZylinder2 = micros();
  if((micros() - previousZylinder2 < einblaszeit_micros) ) {
    zylinder2Status = 0;
    digitalWrite(zylinder2pin,LOW);
  } else {
    digitalWrite(zylinder2pin,HIGH);
  }

  if (zylinder3Status == 1) previousZylinder3 = micros();
  if((micros() - previousZylinder3 < einblaszeit_micros) ) {
    zylinder3Status = 0;
    digitalWrite(zylinder3pin,LOW);
  } else {
    digitalWrite(zylinder3pin,HIGH);
  }

  if (zylinder4Status == 1) previousZylinder4 = micros();
  if((micros() - previousZylinder4 < einblaszeit_micros) ) {
    zylinder4Status = 0;
    digitalWrite(zylinder4pin,LOW);
  } else {
    digitalWrite(zylinder4pin,HIGH);
  }

Gruß
Matthias

Nachtrag: Ausgänge sind Low Aktiv.

Gruß
Matthias

Matze7779:
Habe leider kein Oszi da um das zu überprüfen.

Wenn Du den kompletten Sketch zeigst, lasse ich mein Programm malen.

Ist das Hobby oder wird das benotet? Ich frage nur, weil ich Dir Deine Note nicht durch zu viel Hilfe kaputtmachen will. Auch Lehrer und Ausbilder lesen im Forum :slight_smile:

Der komplette Sketch ist noch nicht fertig da die Eingaben für die Zeiten (drehzahl und Einblaszeit) über den Drehencoder noch nicht komplett fertig sind.

Zum Hobby oder Aufgabe: Ich glaube mit 39 Jahren benotet mich nur meine Frau wie lange ich im Keller bin :slight_smile:

Ein working example schicke ich dir die nächsten Tage per PN. Ist das ok?

Gruß
Matthias

Matze7779:
Der komplette Sketch ist noch nicht fertig da die Eingaben für die Zeiten (drehzahl und Einblaszeit) über den Drehencoder noch nicht komplett fertig sind.

Mit "komplett" meinte ich nur die Variablendefinitionen, setup und loop wie es jetzt ist.

Matze7779:
Zum Hobby oder Aufgabe: Ich glaube mit 39 Jahren benotet mich nur meine Frau wie lange ich im Keller bin :slight_smile:

Woher kommt mir das nur bekannt vor ::slight_smile:

Dann kann ich Dir ja "gefahrlos" meine Überlegungen zeigen:

const byte pinZ[] = {3, 4, 5, 6};
const byte pinT = 2;
const byte AnzZ = sizeof(pinZ) / sizeof(pinZ[0]);
const unsigned long anausMicros[] = {20000, 40000}, startMicros = 15000;
unsigned long altMicros[AnzZ], intervall[AnzZ];
bool zustand, aktTaster, altTaster;

void setup()
{
  Serial.begin(9600);
  Serial.println("Anfang");
  pinMode(pinT, INPUT_PULLUP);
  for (byte j = 0; j < AnzZ; j++)
  {
    pinMode(pinZ[j], OUTPUT);
  }
  aktTaster = digitalRead(pinT);
  altTaster = aktTaster;
}

void loop()
{
  altTaster = aktTaster;
  aktTaster = digitalRead(pinT);
  if (!altTaster && aktTaster) {
    zustand = !zustand;
    delay(30); // Entprellen fuer Arme
    if (zustand) {
      for (byte j = 0; j < AnzZ; j++) {
        altMicros[j] = micros();
        intervall[j] = startMicros * j;
      }
    }
  }
  if (zustand) {
    for (byte j = 0; j < AnzZ; j++) {
      if (micros() - altMicros[j] >= intervall[j]) {
        intervall[j] = anausMicros[digitalRead(pinZ[j])];
        digitalWrite(pinZ[j], !digitalRead(pinZ[j]));
        altMicros[j] = micros();
      }
    }
  } else {
    for (byte j = 0; j < AnzZ; j++)
    {
      digitalWrite(pinZ[j], LOW);
    }
  }
}