Go Down

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

Knippi

Hier der neu aufgebaute Code der Temperaturfühler:

Code: [Select]
#include <DallasTemperature.h> // library für Temperatursensoren
#include <OneWire.h> // library für den OneWire Bus
#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68
#define ONE_WIRE_BUS  30

// Konstanten
const int backlight = 31;   // Pin für die Display-Hintergrundbeleuchtung
const int fanPin = 3;       // Pin für den Lüfter

// Variablen
int fanSpeed = 0;          // Variable für die Lüftergeschwindigkeit
int fanMin = 90;           // Kleinster PWM (z.B.110/41°C) Wert für den Lüfter befor er abschaltet
int fanOut = 1;            // Variable um zu Prüfen, ob der Lüfter aus war
int tMin = 25;             // Untere Grenze des Temperaturbereichs
int tMax = 60;             // Obere Grenze des Temperaturbereichs

// Initialisierung des LCD
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);

//DeviceAdressen der einzelnen ds1820 Temperatursensoren
DeviceAddress sensor1 = {
  0x28, 0xAA, 0x86, 0x99, 0x4, 0x0, 0x0, 0x36 };
DeviceAddress sensor2 = {
  0x28, 0x96, 0x5E, 0x99, 0x4, 0x0, 0x0, 0xC6};
DeviceAddress sensor3 = {
  0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor4 = {
  0x28, 0x1B, 0x18, 0x99, 0x4, 0x0, 0x0, 0x13 };
DeviceAddress sensor5 = {
  0x28, 0xFF, 0x94, 0x29, 0xB2, 0x15, 0x4, 0x82 };  
DeviceAddress sensor6 = {
  0x28, 0xFF, 0x62, 0x26, 0xB2, 0x15, 0x4, 0x22};
DeviceAddress sensor7 = {
  0x28, 0xFF, 0xE2, 0x32, 0xB2, 0x15, 0x3, 0x5C };  
DeviceAddress sensor8 = {
  0x28, 0xFF, 0x66, 0x33, 0xB2, 0x15, 0x4, 0x84 };
DeviceAddress sensor9 = {
  0x28, 0xFF, 0x5E, 0x4A, 0xB2, 0x15, 0x4, 0x5};
DeviceAddress sensor10 = {
  0x10, 0x3C, 0x68, 0xA9, 0x1, 0x8, 0x0, 0xA3 };


//Objekte initialisieren
OneWire oneWire(ONE_WIRE_BUS);                       // OneWire initialisierung
DallasTemperature sensors(&oneWire);                 // DallasTemperature initialisierung

const unsigned long TEMP_POLLING_INTERVAL = 1000UL;
uint32_t nextMillis = 0;
uint8_t status;

float temp1,temp2,temp3,temp4,temp5,temp6,temp7,temp8,temp9,temp0; // Variable für die Berechnung der Temperatur
float aktuelleTemp;

int numSensors; // Variable zum speichern der Anzahl der Temperatur-Sensoren


void setup(){

  sensors.setWaitForConversion(false);

  pinMode(backlight, OUTPUT);     // Setzt den Pin der Display-Hintergrundbeleuchtung als Ausgang
  pinMode(fanPin, OUTPUT);        // Setzt den Pin des Lüfters als Ausgang

  digitalWrite (backlight, HIGH); // Schaltet die Display-Hintergrundbeleuchtung ein

  status = 0;

}

void loop(){


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

    switch (status){
    case 0:

      if(numSensors > 0 && status == 0){ // Es wurde mindestens 1 Sensor gefunden
        lcd.clear();   
        lcd.begin(16, 2);
        lcd.print(numSensors);
        lcd.print( "Temp.-Sensoren");
        lcd.setCursor(0, 1);
        lcd.print("gefunden.");
        lcd.noCursor();
        status = 1;
      }
      else {
        lcd.clear();
        lcd.begin(16, 2);
        lcd.print("Keine Temp.Sen-");
        lcd.setCursor(0, 1);
        lcd.print("soren gefunden.");
        lcd.noCursor();
        status = 1;
      }
      break;

    case 1:

      if (temp1 != -127.00 && status == 1){
        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 = 2;
      }
      else {
        lcd.clear();     
        lcd.setCursor(0, 1);     
        lcd.print("Fehler Sensor01");
        status = 2;
      }
      break;

    case 2:

      if (temp2 != -127.00  && status == 2){   
        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 = 3;
      }
      else {
        lcd.clear();     
        lcd.setCursor(0, 1);     
        lcd.print("Fehler Sensor02"); 
        status = 3;
      }
      break;

    case 3:


      if (temp3 != -127.00 && status == 3){
        lcd.clear();
        lcd.begin(16, 2);
        lcd.print("03:");
        lcd.setCursor(3, 0);
        lcd.print(temp1);
        lcd.setCursor(7, 0);
        lcd.print((char)223);         // degree symbol
        lcd.print("C");
        status = 4;
      }
      else {
        lcd.clear();     
        lcd.setCursor(0, 1);     
        lcd.print("Fehler Sensor03");
        status = 4;
      }
      break;
    case 4:

      // Lüftergeschwindigkeit über den Seriellen Monitor ausgeben
      if (status == 4) {
        lcd.begin(16, 2);
        lcd.print("L""\xF5""fterspeed: ");    // Werte über RS232 Port ausgeben
        lcd.setCursor(12, 0); 
        lcd.print(fanSpeed);
        status = 5;
      }
      status = 0;

    }
  }
}

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);
    temp3 = sensors.getTempC(sensor3);
    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);
    sensors.begin();
    numSensors = sensors.getDeviceCount(); // Anzahl der angeschlossenen Sensoren in numSensors speichern
    dataRequested = false;
    previousMillis = millis();
    return true;
  }

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

  return false;


  // 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, schaltet 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);




}

Serenifly

#31
Mar 17, 2016, 02:20 am Last Edit: Mar 17, 2016, 02:24 am by Serenifly
Und?

Du kannst auch erst mal den ganzen Auswerte-Kram weglassen. Und zum Test erst mal nur die Sensoren auslesen und einfach auf Serial ausgeben. Das ist bei vielen Anwendungen ein erster Schritt. Wenn das mal läuft und dann deine LED Geschichte nicht stört kann man mehr machen


Code: [Select]

sensors.begin();
numSensors = sensors.getDeviceCount();

Wieso machst du das an der Stelle? Das gehört einmal nach setup()!

Geht es darum ausgefallene Fühler zu erkennen? Das sollte man doch daran merken dass kein gültiger Wert mehr kommt.

Knippi

Quote
@ Serenifly:
Wieso machst du das an der Stelle? Das gehört einmal nach setup()!

Geht es darum ausgefallene Fühler zu erkennen? Das sollte man doch daran merken dass kein gültiger Wert mehr kommt.
Du hast recht, natürlich kann man es an einem ungültigen Wert erkennen. Es soll nur etwas komfortabel zur schnellen Übersicht sein.

Quote
Wenn das mal läuft und dann deine LED Geschichte nicht stört kann man mehr machen
Ich habe gestern Nacht wieder einige Stunden damit verbracht, den RGB-LED-Code in den Temp.-Code mit einzubauen. Ich bekomme es einfach nicht hin und um 02:30 Uhr habe ich denn wieder einmal erfolglos abgebrochen.

Wenn ich den RGB-LED-Code mit einbaue und die 'case #:'-Funktion des RGB-LED-Codes in der Reihenfolge der Nummerierung anpasse, dauert der Farbverlauf ewig, da ja immer vorher die Temp.-Fühler zur Anzeige gebracht werden und dann erst wieder der RGB-LED-Loop dran ist. Also wird es ja irgendwie seriell abgearbeitet und nicht parallel. Das ist ja schon die ganze Zeit mein Hauptproblem.

Gruß Jens

ElEspanol

Du solltest dich vielleicht vor so einem Projekt mit einfacheren Sketchen in die "Parallelverarbeitung" reinfinden.

Blinkwithoutdelay und Funktionen sind hier mal anfangs das Stichwort

Knippi

Quote
Blinkwithoutdelay und Funktionen sind hier mal anfangs das Stichwort
Damit habe ich mich beschäftigt, nur sagt mir das nichts über Parallelverarbeitung aus. :o
Man denkt vielleicht manchmal einfach zu quer und sieht den Wald vor lauter Bäumen nicht.
Hilfreich ist dann manchmal eine Lösung zu sehen, um den Denkfehler zu erkennen.
Ich beschäftige mich nur hobbymäßig mit dem Arduino, lerne aber immer mehr dazu und verstehe die Prozesse die dahinter stecken. Manchmal sind es für mich aber, muss ich ehrlich zu geben, böhmische Dörfer und baue die Funktionen einfach mit ein und irgendwann später verstehe ich es dann. :smiley-eek:

Serenifly

Wirklich parallel geht sowie nichts. Du kannst nur eine Sache tun und danach eine andere. Der Trick ist dass man den Prozessor nicht lange aufhält, sondern nur so viel macht wie gerade zu tun ist. Dann hat man zwischendrin Zeit für andere Aufgaben.

z.B. bei der Temperatur-Messung. Statt die blockierende Version von requestTemperatures() zu verwenden die jedesmal 200ms wartet (bei 10 Bit), macht man nur die Anforderung und kehr dann nach loop() zurück. Dort kann man dann was anderes machen und abfragen ob diese 200ms vorbei sind. Dann ist es Zeit die Temperaturen auszulesen.

Knippi

@Serenifly

Habe ich denn deinen Vorschlag (in der Code-Box oben) so umgesetzt?

ElEspanol

Womit du dich auch Beschäftigen kannst, ist der Aufbau eines endlichen Automaten, auch Zustandsautomat, State machine, genannt. Sehr interessantes Thema, das dir in Zukunft viele Probleme lösen wird, wenn du das Konzept mal verinnerlicht hast.


Serenifly

Habe ich denn deinen Vorschlag (in der Code-Box oben) so umgesetzt?
Eigentlich schon. Das macht Abfragen in einem Abstand von einer Sekunde. Wobei nicht genau 1 Sekunde dazwischen vergeht, da noch die 200ms dazukommen. Das ist aber egal. Also: Anfordern -> 200ms für was anderes -> Temperatur auslesen -> 1s Pause -> Anfordern -> ...

Ich würde den Code wie gesagt mal minimal vereinfachen. Lies nur einen Sensor aus und gebe den auf Serial aus. Dann mehrere Sensoren. Ohne irgendwas zu steuern.

Auch auf der LED Seite kann man vielleicht erst mal einfacheren Code nehmen.

Knippi

Aber es macht doch meiner Meinung keinen Sinn.

Ich habe den Code von 10 auf 3 Temperaturen -Fühler gekürzt.
Natürlich ist es jetzt schneller. Es werden ja auch nur noch 3 Temperatur-Fühler zur Anzeige gebracht. Aber trotzdem wird ja der LED-Code erst danach im loop bearbeitet.

Es sollen aber 10 bleiben

ElEspanol

Du siehst die Lösung nicht, weil du noch falsch denkst.
Der LED Teil muss zb 100 mal durchlaufen, ohne dass der Sensor und lcd Tei berührt wird. Dann 1 Mal Sensoren auslesen und ausgeben, dann wieder 100 mal led, etc.

DerLehmi

Hier gibts ein recht einfaches Tutorial zum Thema paralleler Ablauf, kannst Dich dort mal durch die Anleitung klicken ;)

Knippi

Ich hab's :)  :)  :)

Der Fehler lag bei den Variablen!!!

Ich hatte für beide Codes die selben Variablen verwendet.

combie

#43
Mar 18, 2016, 08:02 am Last Edit: Mar 18, 2016, 08:03 am by combie
Quote
Ich hatte für beide Codes die selben Variablen verwendet.
Das nennt sich: "Ein unerwünschter Seiteneffekt."
Recht schwer zu finden. Manchmal.

Kommt bei der Verwendung von globalen, statischen Variablen und  Singletons gerne mal vor.
Einzige Abhilfe: Disziplin.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

beeblebrox

#44
Mar 18, 2016, 02:21 pm Last Edit: Mar 18, 2016, 02:36 pm by beeblebrox
Ich hab mal auf eine ähnliche Art zwei Applikationen verknüpft.
Das was ich hatte war eine Umschaltbox für 4 Plattenspieler, die steuerte 4 Readrelais und ein Display in Abhängigkeit von 4 Tastern.
Die Taster hatte ich eh schon im Interrupt bedient, so das ich den Tastendruck auch hatte wenn ich die Taster
gerade nicht gepollt habe.
Als das alles lief dachte ich mir der Prozessor hat einfach zu wenig zu tun, wenn ich ihn schon (mit Energie)
fütter soll er auch arbeiten  :smiley-roll-blue: .
Also bekam jeder Plattenspieler ein Schildchen das mit 4 Leds beleuchtet wurde. Das war ein in 4 Gruppen
auseinander gezogener WS2812 Streifen. Natürlich sollten die Schildchen (Plexiglas) nicht nur leuchten
sondern auch Farbverläufe anzeigen. Dafür hatte ich auch einen Sketch.
Der Mainsketch wurde jetzt der für die LedStreifen. Er wurde so modifiziert das nur die 4 Leds für den aktiven
Spieler angingen. In diesem Sketch gab es einen Wartebereich mit delays. Der wurde durch eine millis
Schleife ersetzt und im Rumpf dieser Schleife wurde das alte "main" für die Tastatur und Displaysteuerung
aufgerufen (einen 433 Mhz Empfänger frage ich da auch noch ab). Und das klappt wunderbar.
Die Leds werden schön fließend gesteuert und auf Knopfdruck reagiert das Gerät auch spontan, jedenfalls
so schnell das man nichts störendes merkt.

Es ist immer nur eine Frage wie man alles verschachtelt.

Ulli

Go Up