Go Down

Topic: parallel Ablauf von Programm-Codes (Read 3819 times) previous topic - next topic

RudiDL5

Quote
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.


Knippi

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

Code: [Select]
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

RudiDL5

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

Code: [Select]

  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:

Code: [Select]

  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?

RudiDL5

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.

combie

#19
Mar 16, 2016, 10:18 am Last Edit: Mar 16, 2016, 10:19 am by combie
Quote
Code: [Select]
  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.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

RudiDL5

Quote
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.
Das kommt hier noch erschwerend hinzu.

michael_x

Quote
  sensors.requestTemperatures();
  temp0 = sensors.getTempC(sensor10);

keine Ahnung was sensors ist, aber da kann ein dickes delay versteckt sein :)

Knippi

Quote
@RudiDL5:
noch 'ne Frage hinterher:
Funtioniert denn "überhaupt" irgend etwas für sich alleine wie gewünscht?
Ja, die einzelnen Codes funktionieren.

Ich habe im 2.Thread die zwei einzelnen Codes und den zusammengeführten Code mit angehängt.

Leider lassen sich zwei nicht in der Code-Box im Thread Anzeigen, da immer eine Fehlermeldung (maximale Zeichen....)erscheint.

RudiDL5

Gut.
Nur muss dann irgendetwas beim Zusammenführen schief laufen. Vielleicht sind (wie die Kollegen und auch ich schon geschrieben haben) offene und/oder versteckte Delays enthalten, die dein ganzes Konzept in Schutt und Asche legen.
Damit wir hier eine Lösung finden müssen wir wahrscheinlich eine Art Frage-und-Anwort-Spiel durchziehen, damit alle verstehen was gewünscht wird - oder damit man direkt erkennt wo es hapert. Dazu interessiert es MICH vorab, was alles "wirklich" erreicht werden soll, welche Programmteile alle zusammenspielen sollen. Vielleicht kannst du das ja mal in kurzen aber klaren Statements hier schreiben.
Gruß, Rudi

Serenifly

keine Ahnung was sensors ist, aber da kann ein dickes delay versteckt sein :)
Das delay() steckt in requestTemperatures() und tritt daher nur einmal für alle Sensoren auf. Bei 10 Bit Auflösung sind das 188ms

Man kann das aber auch mit der Library von Miles Burton verzögerungsfrei mach wenn man waitForConversion(false) aufruft. Dann kann (und muss!!) man die Zeit zwischen Anforderung und Abfrage per millis() machen

ElEspanol

Mich wundert da gar nichts, wenn in jedem Loop 10 Sensoren abgefragt werden.

Serenifly

#26
Mar 16, 2016, 10:04 pm Last Edit: Mar 16, 2016, 10:07 pm by Serenifly
Es ist egal wie viele Sensoren man abfragt, solange man die Anforderung nicht einzeln adressiert. requestTemperatures() sagt allen Sensoren dass sie eine Messung starten sollen und wartet dann. readTemperatures() macht kein delay()!! Die Verzögerung ist zwischen Anforderung und Auslesen!

Mit dieser Lib geht das aber auch ohne Delay:
https://milesburton.com/Dallas_Temperature_Control_Library


Dann kann man das machen:
Code: [Select]

const unsigned long TEMP_POLLING_INTERVAL = 1000UL;

float temp1, temp2;

void setup()
{
   ...
   sensors.setWaitForConversion(false);
}

void loop()
{
   if (readTemperatureSensors() == true)
   {
      //hier wurde eine Messung abgeschlossen und man kann mit den Werten was machen
   }
}

bool readTemperatureSensors()
{
  static unsigned long previousMillis;
  static bool dataRequested;

  if(dataRequested == true && millis() - previousMillis > 200)   //Die Zeit muss an die Auflösung angepasst werden. 200ms passt für 10 Bit
  {
    temp1 = sensors.getTempC(sensor1);
    temp2 = sensors.getTempC(sensor2);

    dataRequested = false;
    previousMillis = millis();
    return true;
  }
 
  if(dataRequested == false && millis() - previousMillis > TEMP_POLLING_INTERVAL)
  {
     sensors.requestTemperatures();
     dataRequested = true;
     previousMillis = millis();
  }

  return false;
}




Man kann Sensoren übrigens auch schön in ein Array packen:
Code: [Select]

DeviceAddress temperatureSensorList[] = {
{ 0x28,0x68,0x2A,0xA4,0x05,0x00,0x00,0xAB },
{ 0x28,0x82,0x38,0xA5,0x05,0x00,0x00,0x3D }
};


Dann kann man bequem darüber mit einer for-Schleife iterieren

ElEspanol

#27
Mar 16, 2016, 10:39 pm Last Edit: Mar 16, 2016, 10:41 pm by ElEspanol
Ich mache das genauso, trotzdem dauern bei mir 5 Sensoren über 100ms. aber der Punkt ist ja, das der TE die Sensoren unnötigerweise in jedem loop abfragt.

Serenifly

#28
Mar 16, 2016, 10:43 pm Last Edit: Mar 16, 2016, 10:46 pm by Serenifly
Rein für die OneWire Kommunikation? Das ist natürlich möglich.

Aber Temperatur Sensoren muss man sowieso nicht ständig abfragen. Alle 1 Sekunde ist schön für flüssige LDC Anzeigen aber wenn man nur Werte vergleichen muss immer noch viel schneller es es sein müsste.

Nachtrag:
Ja, ich sehe jetzt dass er das anscheinend ständig macht. Das ist natürlich extrem schlecht :( Das muss anders gemacht werden. Ich dachte das wäre verzögert.

Und sensors.begin() gehört nicht in loop() sondern in setup()

Knippi



Ich habe mich nach euren Kommentaren dazu entschlossen das ganze neu aufzubauen.

Quote
@Serenifly
Mit dieser Lib geht das aber auch ohne Delay:
https://milesburton.com/Dallas_Temperature_Control_Library


Dann kann man das machen:
Code: [Select]

const unsigned long TEMP_POLLING_INTERVAL = 1000UL;

float temp1, temp2;

void setup()
{
   ...
   sensors.setWaitForConversion(false);
}

void loop()
{
   if (readTemperatureSensors() == true)
   {
      //hier wurde eine Messung abgeschlossen und man kann mit den Werten was machen
   }
}

bool readTemperatureSensors()
{
  static unsigned long previousMillis;
  static bool dataRequested;

  if(dataRequested == true && millis() - previousMillis > 200)   //Die Zeit muss an die Auflösung angepasst werden. 200ms passt für 10 Bit
  {
    temp1 = sensors.getTempC(sensor1);
    temp2 = sensors.getTempC(sensor2);

    dataRequested = false;
    previousMillis = millis();
    return true;
  }
 
  if(dataRequested == false && millis() - previousMillis > TEMP_POLLING_INTERVAL)
  {
     sensors.requestTemperatures();
     dataRequested = true;
     previousMillis = millis();
  }

  return false;
}
Ich habe einmal den Code-Vorschlag von "Serenifly" aufgenommen und auf dieser Basis den Code neu aufgebaut.

Quote
@ RudiDL5
Damit wir hier eine Lösung finden müssen wir wahrscheinlich eine Art Frage-und-Anwort-Spiel durchziehen, damit alle verstehen was gewünscht wird - oder damit man direkt erkennt wo es hapert. Dazu interessiert es MICH vorab, was alles "wirklich" erreicht werden soll, welche Programmteile alle zusammenspielen sollen. Vielleicht kannst du das ja mal in kurzen aber klaren Statements hier schreiben.
Zur Erklärung, was mit diesem Teil des Code bezweckt werden soll:

Es werden 10 Temperaturfühler ausgelesen und ab einem festgelegten Wert, hier 50 Grad
Quote
if(aktuelleTemp >= 50)
  {
    if(fanOut == 1)
ein PWM-Ausgang temperaturgesteuert zu erhöhen und abzusenken. Dieser Ausgang steuert eine KSQ, die wiederum 10 Lüfter drehzahlabhängig steuert. Es werden alle 10 Temperaturfühler permanent überwacht und bei einem Ausfall (-127.00 ist der Wert bei einem Ausfall eines Sensors) von einem Fühler im Display als Fehler angezeigt. Auch die Gesamtzahl der gefundenen Fühler wird im Display angezeigt.

Gleichzeitig soll ein RGB-LED-Lichtstreifen durch einen RGB-LED-Driver gesteuert, alle Farben durchfahren. Der RGB-LED-Driver hat einen eigene 'RGBdriver.h', die ich im #1 Thread mit eingestellt habe (LedStripDriverLibrariesforArduino1.0+.zip).

Für diesen habe ich auch einen fertigen Code:

Code: [Select]

#include "RGBdriver.h"
#define CLK 28//pins definitions for the driver       
#define DIO 29//pins definitions for the driver 
RGBdriver Driver(CLK,DIO);

const byte farben[6][3] = {
//  r    g    b
    0,   0, 255,  // 0 r++
  255,   0, 255,  // 1 b--
  255,   0,   0,  // 2 g++
  255, 255,   0,  // 3 r--
    0, 255,   0,  // 4 b++
    0, 255, 255   // 5 g--
};
const unsigned long zeiten[] = {1000, 1000, 1000, 1000, 1000, 1000}; // Werte für die Fadezeiten zum naechsten Wechsel
const int fanPin = 3;                 // Pin für den Lüfter

byte status, r, g, b;
unsigned long aktMillis, fadeMillis, fadeZeit;

void setup() {
  analogWrite(fanPin, 90);
  farbenFestlegen(status = 0);
   pinMode(fanPin, OUTPUT);        // Setzt den Pin des Lüfters als Ausgang
}
void farbenFestlegen(byte sta) {
  r = farben[sta][0];
  g = farben[sta][1];
  b = farben[sta][2];
  fadeZeit = zeiten[sta];
}
void loop() {
  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();
  }
}


Nun soll dieser, in den Code mit den Temperaturfühlern eingebaut werden, ohne dass weder der eine noch der andere Code, sich gegenseitig behindert.

Gruß Jens

Go Up