parallel Ablauf von Programm-Codes

Hallo , mal wieder.

Ich Kämpfe gerade an einem Problem, zweier Programm-Codes in einen Code umzusetzen.

Ich habe ein Programmablauf, in dem ich 10 Temperaturfühler auslese und ab einen festgelegten Wert hier

if(aktuelleTemp >= 50)
{
if(fanOut == 1)

50 Grad einen PWM-Ausgang temperaturgesteuert zu erhöhen und abzusenken. Dieser Ausgang steuert eine KSQ, die wiederum 10 Lüfter drehzahlabhängig steuert.

Ich wollte nun beide Codes zusammenführen und in einem Programm ablaufen lassen.

Leider passiert nun folgendes:

Der Farbverlauf des RGB-LED-Strip beginnt in seiner Funktion erst, wenn alle Werte im Display angezeigt wurden und setzt auch erst jedesmal nach einem Displaydurchlauf seine Funktion fort. D.h. es dauert Stunden bis ein kompletter Farbverlauf durchgeführt ist.

Mir ist irgendwie klar, dass der Farblauf durch den Programmablauf der Temp./Display-Anzeige verzögert abläuft, finde aber keine Lösung, dieses zu ändern.

Gibt es eine Möglichkeit und wenn ja welche, die beiden Programmabläufe parallel ablaufen zu lassen oder mache ich nur einen Gedanken/Umsetzungsfehler?

Vielen Dank schon mal. :slight_smile:

Gruß Jens

LedStripDriverLibrariesforArduino1.0+.zip (3.21 KB)

Hier die Codes:

Temp_Display.ino (13.8 KB)

Fade_RGB_LEDStrip_ohne_delay.ino (1.87 KB)

Beide_Codes_zusammen.ino (15.4 KB)

Moin,
im Grunde kannst du deine beiden Codes natürlich zusammenführen und als ein Sketch laufen lassen... Aber nur solange die beiden Programme sich nicht gegenseitig behaken und blockieren!

Ein Blick allein in die "Temp_Display" zeigte mir, dass innerhalb "while(u <= 10)" ein allgemein bekanntes und hochgiftiges "delay(500)" drin ist. Das ist absolut niederschmetternd für dein Programm. Hier solltest du deine Sketch-Philosophie evtl. komplett überdenken und vollkommen neu zusammenbauen.

Sorry für diese Antwort, aber ich habe anfangs auch extrem viele Probleme damit gehabt, und dann hatte mir dieses Tutorial die Augen geöffnet, wie man (fast) echte Parallel-Verarbeitung programmiert:

Gruß, Rudi

du aktualisierst dein LCD bei jedem Loopdurchlauf. Es würde reichen, zu aktualisieren, wenn sich etwas ändert.
Edit: z.B. das Datum nur einmal je Tag, dann kannst du dir auch das delay sparen

Ich würde eine HSV Tabelle für den Regenbogen-Farbwechsel benutzen. Z.B. die von FastLED. Diese würde ich mit millis() verknüpfen.

CRGB led = CHSV( millis() / 2, 255, 255)

led.r, led.g und led.b kannst Du an 3 Pins via PWM ausgeben.

Vorteil davon: Egal, wie oft und egal wie zeitlich ungleichmäßig (wg. mal LCD schreiben, mal nicht) Du diese Zuweisung machst - der Farbverlauft läuft immer mit konstanter Geschwindigkeit.

Gruß, H.

Vielleicht könnte einer der Administratoren einmal die drei Codes in der Code-Box im Thread zur Anzeige bringen.

Bei mir kam es immer zu einer Fehlermeldung:

The message exceeds the maximum allowed length (9000 characters).

Danke.

Gruß Jens

Vielleicht könnte einer der Administratoren einmal die drei Codes in der Code-Box im Thread zur Anzeige bringen.

Nein, kann ich auch nicht.
Grüße Uwe

Hallo,

danke für eure Antworten.

@RudiDL5:

Ein Blick allein in die "Temp_Display" zeigte mir, dass innerhalb "while(u <= 10)" ein allgemein bekanntes und hochgiftiges "delay(500)" drin ist. Das ist absolut niederschmetternd für dein Programm. Hier solltest du deine Sketch-Philosophie evtl. komplett überdenken und vollkommen neu zusammenbauen.

Das ist ja mein Problem. Ich probiere es mittlerweile seit Tagen und zerbreche mir den Kopf und komme zu keinem Ergebnis.

Warum ist die "while(u <= 10)" Funktion mit dem sehr kleinen delay-Wert von (500) so ein Problem?

Die Anzeigen des Datum und die Temperaturen, sollen schon 1-1,5 sec. im Display ablesbar bleiben. Nur wie kann denn die RGB-LED-Stripe Funktion parallel ablaufen, bzw. wie müssen die Display-Anzeigefunktionen umgeschrieben werden, dass die RGB-LED-Stripe Funktion trotzdem ablaufen kann.

Gruß Jens

500ms sind nicht "sehr klein".

500ms sind nicht "sehr klein".

Das verzögert die RGB-LED-Funktion von Minuten auf Stunden?

Die Anzeigen des Datum und die Temperaturen, sollen schon 1-1,5 sec. im Display ablesbar bleiben.

solange du sie nicht löscht oder überschreibst bleiben sie lesbar

Es ist ja eine Routine, die nach einem Durchlauf wieder von vorne startet und die Werte mit neuen Werten zur Anzeige gebracht wird.

500ms sind nicht "sehr klein".
.
.
.
Das verzögert die RGB-LED-Funktion von Minuten auf Stunden?

Ohne deinen Code jetzt "genau" analysiert zu haben behaupte ich dennoch einfach mal : JAA!!!

Denn:
Im 2. Sketch "Fade_RGB_ ..." ist eine wunderbare Routine, die das Faden mittels millis() regelt. Keine Ahnung wie die "fadeZeit" dort gesetzt ist. Aber das Programm geht an dieser Stelle mit einer "affenartigen" Geschwindigkeit drüber und nur alle paar Millisekunden (je nach fadeZeit) wird eine andere Aktion ausgelöst. Es setzt also an DER Stelle vorraus, dass die Haupt-loop mit ca. 2 Mhz darüber jagt.

Nun machst du aber bei JEDEM einzelnen Fade-Schritt im oberen Teil 1 - 1,5 Sekunden Pause... DORT liegt doch dann der Hase im Pfeffer.

Dreh doch den Spieß einfach um: Lass die "Fade-Geschichte" mit ihrer HighSpeed durch den µC rauschen und aktualisiere das Display ebenfalls in einer eigenen "millis"-Routine. Dort kannst du dann alle paar Sekunden bei z.B. "negativer Flanke" einer "BetriebsLED" kurz das Display ansprechen.

Ich mache das immer nach folgendem Muster:

void loop()
{
  if( millis() - mS >= 1000 )
    {
      mS = millis();                        // mS = irgendwo oben unsigned long
      digitalWrite( 13, !digitalRead(13) ); // 13 ist meine "BetriebsLED"
      if( !digitalRead(13) )
        { /* aktualisiere Display (z.B.) */ }
    }
  // Hier dann alles andere...
}

das is nur meine bescheidene Meinung
Rudi

Nachbrüller
Ich selbst "zwinge" mich generell (!) zu dieser "BetriebsLED". Dadurch erkenne ich sofort, ob alles rund läuft oder ob der µC irgendwo in den Streik getreten ist...
:wink:

Noch einer... Ich sehe gerade, dass "fadeZeiten" durch "zeiten[]" gesteuert wird. Dort sind Werte mit 1000 und so. Multipliziere mal diese Zeiten mit deinen Display-Delays ...

Dann kann ja nur das Problem mit der Datum/Uhrzeit-Anzeige zusammen hängen, da nur dort "while(u <= 10)" + 'delay(500)' verknüpft ist.

led.r, led.g und led.b kannst Du an 3 Pins via PWM ausgeben.

Der RGB-LED-Driver, der die LED-Stripe steuert hat einen eigenen Sketch (siehe oben) LedStripDriverLibrariesforArduino1.0+.zip

Dort wird nicht direkt mit 3 Pins die drei Grundfarben gesteuert, sondern durch zwei (CIN+DIN) Eingänge.
Deshalb würde auch der FastLED-Sketch nicht funktionieren.

Dann kann ja nur das Problem mit der Datum/Uhrzeit-Anzeige zusammen hängen, da nur dort "while(u <= 10)" + 'delay(500)' verknüpft ist.

Genau dort ist das Problem.

Wenn du davon ausgehst, das FastLED zig tausendmal in der Sekunde durchläuft - und nur alle paar Microsekunden davon an deinen RGB-Werten etwas verändert, kannst du davon ausgehen dass jedes Halbsekunden-Delay in einem anderen Programmteil alles andere extrem ausbremst.

Schau noch mal oben nach bei meiner "BetriebsLED". So oder ähnlich müsste es gehen. Statt einer LED kannst du auch eine Boolean-Variable umschalten und bei "false" das Display aktualisieren. Egal wie, nur das delay(x) muss raus.

Ich habe einmal den loop-Teil des Codes hier eingestellt und habe den Datum/Uhrzeit Teil entfernt.

void loop()
{
 //Sensoren abfragen
  sensors.begin();
  numSensors = sensors.getDeviceCount(); // Anzahl der angeschlossenen Sensoren in numSensors speichern
  sensors.requestTemperatures();

  temp0 = sensors.getTempC(sensor10);
  temp1 = sensors.getTempC(sensor1);
  temp2 = sensors.getTempC(sensor2);
  temp3 = sensors.getTempC(sensor3);
  temp4 = sensors.getTempC(sensor4);
  temp5 = sensors.getTempC(sensor5);
  temp6 = sensors.getTempC(sensor6);
  temp7 = sensors.getTempC(sensor7);
  temp8 = sensors.getTempC(sensor8);
  temp9 = sensors.getTempC(sensor9);


  if(numSensors > 0 && status == 0) // Es wurde mindestens 1 Sensor gefunden
  {
    status = 1; 
    lcd.clear();    
    lcd.begin(16, 2);
    lcd.print(numSensors);
    lcd.print( "Temp.-Sensoren");
    lcd.setCursor(0, 1);
    lcd.print("gefunden.");
    lcd.noCursor();
    nextMillis = millis() + 3000L; // next state in 1 min

  } 
  else if(numSensors == 0 && status == 0 && millis() > nextMillis) {
    status = 1;
    lcd.clear();
    lcd.begin(16, 2);
    lcd.print("Keine Temp.Sen-");
    lcd.setCursor(0, 1);
    lcd.print("soren gefunden.");
    lcd.noCursor();

    nextMillis = millis() + 3000L; // next state in 2 min


  } 
  else if (status == 1 && millis() > nextMillis) {
    status = 2;



  }
  else if (status == 2 && temp1 == -127.00 && millis() > nextMillis){ 
    lcd.clear();     
    lcd.setCursor(0, 1);      
    lcd.print("Fehler Sensor01");
    if (status == 2 && millis() > nextMillis) {
      status = 3;
      nextMillis = millis() + 3000L; // next state in 2 min
    }
  } 
  if (status == 2 && temp1 != -127.00 && millis() > nextMillis) {
    lcd.clear(); 
    lcd.begin(16, 2);
    lcd.print("01:");
    lcd.setCursor(3, 0);
    lcd.print(temp1);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 3;
    nextMillis = millis() + 3000L;
  }

  if (status == 3 && temp2 == -127.00 && millis() > nextMillis){ 
    lcd.clear();      
    lcd.setCursor(0, 1); 
    lcd.print("Fehler Sensor02");
    status = 4;
    nextMillis = millis() + 3000L;
  }
  else if (status == 3 && temp2 != -127.00 && millis() > nextMillis) {
    lcd.clear(); 
    lcd.begin(16, 2);
    lcd.print("02:");
    lcd.setCursor(3, 0);
    lcd.print(temp2);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 4;
    nextMillis = millis() + 3000L;

  }
  if (status == 4  && temp3 == -127.00 && millis() > nextMillis) {
    lcd.clear();      
    lcd.setCursor(0, 1); 
    lcd.print("Fehler Sensor03");
    status = 5;
    nextMillis = millis() + 3000L;
  }
  else if (status == 4 && temp2 != -127.00 && millis() > nextMillis) {
    lcd.clear(); 
    lcd.begin(16, 2);
    lcd.print("03:");
    lcd.setCursor(3, 0);
    lcd.print(temp3);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 5;
    nextMillis = millis() + 3000L;
  }
  if (status == 5  && temp4 == -127.00 && millis() > nextMillis) {
    lcd.clear();      
    lcd.setCursor(0, 1); 
    lcd.print("Fehler Sensor04");
    status = 6;
    nextMillis = millis() + 3000L;
  }
  else if (status == 5 && temp4 != -127.00 && millis() > nextMillis) {
    lcd.clear(); 
    lcd.begin(16, 2);
    lcd.print("04:");
    lcd.setCursor(3, 0);
    lcd.print(temp4);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 6;
    nextMillis = millis() + 3000L;

  }
  if (status == 6  && temp5 == -127.00 && millis() > nextMillis) {
    lcd.clear();      
    lcd.setCursor(0, 1); 
    lcd.print("Fehler Sensor05");
    status = 7;
    nextMillis = millis() + 3000L;
  }
  else if (status == 6 && temp5 != -127.00 && millis() > nextMillis) {
    lcd.clear(); 
    lcd.begin(16, 2);
    lcd.print("05:");
    lcd.setCursor(3, 0);
    lcd.print(temp5);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 7;
    nextMillis = millis() + 3000L;
//-----------------------------------------------------------------------------------------------------------------
// hier wurde der Code um 5 Temperatur Anzeige-Funktionen gekürzt, weil es sonst beim posting in //dieser Code-Box wieder zu einer Fehlermeldung (max. 9000 Zeichen) gekommen wäre.
//-----------------------------------------------------------------------------------------------------------------
}

  Serial.print("FanOut: ");                       // Werte über RS232 Port ausgeben
  Serial.println(fanOut); 
  aktuelleTemp = max(temp0, temp1);
  aktuelleTemp = max(aktuelleTemp, temp2);
  aktuelleTemp = max(aktuelleTemp, temp3);
  aktuelleTemp = max(aktuelleTemp, temp4);
  aktuelleTemp = max(aktuelleTemp, temp5);
  aktuelleTemp = max(aktuelleTemp, temp6);
  aktuelleTemp = max(aktuelleTemp, temp7);
  aktuelleTemp = max(aktuelleTemp, temp8);
  aktuelleTemp = max(aktuelleTemp, temp9);
  // Lüftergeschwindigkeit über den Temperaturbereich einstellen
  // TMin->0% PWM | TMax->100% PWM
  fanSpeed = map(aktuelleTemp, tMin, tMax, 95, 255);    

  // Wenn der PWM Wert unter den van FanMin fällt, schält der Lüfter ab
  if (fanSpeed < fanMin)
  {
    fanSpeed = 0;
    fanOut = 1;
  }

  // Hysterese
  if (fanOut == 1)
  {
    fanSpeed = 0;
  }

  if(aktuelleTemp >= 50)
  {
    if(fanOut == 1)
    {
      fanOut = 0;
      analogWrite(fanPin,255);//überwindet die Trägheit beim Anlauf der Lüfter bei kleinen Drehzahlen
      delay(500); 
    }
  }

  // PWM Wert auf 255 begerenzen  
  if (fanSpeed > 255)
  { 
    fanSpeed = 255;
  }
  analogWrite(fanPin, fanSpeed);  
  // Lüftergeschwindigkeit über den Seriellen Monitor ausgeben
  if (status == 7 && millis() > nextMillis) {
    lcd.begin(16, 2);
    lcd.print("L""\xF5""fterspeed: ");    // Werte über RS232 Port ausgeben
    lcd.setCursor(12, 0);  
    lcd.print(fanSpeed);
    status = 8;
    nextMillis = millis() + 3000L;
  }
  else if (status == 8 && millis() > nextMillis) {
    status = 9;


    status = 0;

  aktMillis = millis();
  if (aktMillis - fadeMillis >= fadeZeit) {
    fadeMillis = aktMillis;
    switch (status) {
      case 0:
        if (r < 255) {
          r++;
        } else {
          farbenFestlegen(status = 1);
        }
        break;
      case 1:
        if (b > 0) {
          b--;
        } else {
          farbenFestlegen(status = 2);
        }
        break;
      case 2:
        if (g < 255) {
          g++;
        } else {
          farbenFestlegen(status = 3);
        }
        break;
      case 3:
        if (r > 0) {
          r--;
        } else {
          farbenFestlegen(status = 4);
        }
        break;
      case 4:
        if (b < 255) {
          b++;
        } else {
          farbenFestlegen(status = 5);
        }
        break;
      case 5:
        if (g > 0) {
          g--;
        } else {
          farbenFestlegen(status = 0);
        }
        break;
    }
  Driver.begin();
  Driver.SetColor(r, g, b);
  Driver.end();
  }
  }
}

Das Problem besteht immer noch. Es kann also nicht nur an der "while(u <= 10)" + "delay(500)" Funktion liegen.

Gruß Jens

Irgendwie ist der Code sehr schwer verständlich. Dennoch müssen noch mehr Fehler drin sein. Recht weit unten steht z.B.:

  else if (status == 8 && millis() > nextMillis) {
    status = 9;


    status = 0;

Status 9 wird hier direkt durch 0 überschrieben und findet die verbleibenden Case-Schnippsel nie mehr.

Weiterhin ist mir folgendes noch aufgefallen:

  if (status == 5  && temp4 == -127.00 && millis() > nextMillis) {
    lcd.clear();     
    lcd.setCursor(0, 1);
    lcd.print("Fehler Sensor04");
    status = 6;
    nextMillis = millis() + 3000L;
  }
  else if (status == 5 && temp4 != -127.00 && millis() > nextMillis) {
    lcd.clear();
    lcd.begin(16, 2);
    lcd.print("04:");
    lcd.setCursor(3, 0);
    lcd.print(temp4);
    lcd.setCursor(7, 0);
    lcd.print((char)223);         // degree symbol
    lcd.print("C");
    status = 6;
    nextMillis = millis() + 3000L;

  }

Hier muss auch irgend eine Macke sein, welche erkenne ich nicht genau.

Du fragst z.B. nach:

if (status == 5 && temp4 == -127.00 && millis() > nextMillis) {
...
}
else if((status == 5 && temp4 != -127.00 && millis() > nextMillis))
{...}

Normalerweise fragt man:
if( bedingung )
{ ... }
else
{ ... }

NICHT mehr die umgekehrte Frage noch mal, denn wenn dann in den Bruchteilen der Millis-Sekunden sich etwas verändert hat, dann findet er nie den alternativen Zweig zur Ausgabe.

Und so ganz nebenbei sollte man vermeiden, nach "Exaktheit" von Float-Werten (-127.00) fragen, das geht ebenfalls selten bis gar nicht gut. Entweder größer oder kleiner, nie nach identisch.

Sorry, ich muss in die Matratzen, aber hier solltest du echt noch mal einiges deiner Philosophie überdenken. Funktionierte denn das reine Display-Programm schon mal komplett und einwandfrei?

noch 'ne Frage hinterher:
Funtioniert denn "überhaupt" irgend etwas für sich alleine wie gewünscht?
Liste doch vielleicht mit knappen Worten auf, was alles parallel verarbeitet werden soll. Vielleicht finden wir ja gemeinsam irgendwie eine Lösung.

  nextMillis = millis() + 3000L; // next state in 2 min

Das funktioniert wohl nicht immer.....

Es ist eigentlich immer (im Arduino Umfeld) falsch, den nächsten Zeitpunkt zu berechnen!
Denn so wird der Vergleich, ab und an, versagen, oder muss unnötig verkompliziert werden.

Mal ganz davon abgesehen dass 3000ms nur ganz selten mal 2 Minuten sind.