While loop verlassen

Hallo zusammen,

ich bin neu was das Programieren angeht. Ich habe schon ne menge gelesen, aber vieles ist mir noch nicht klar.
Ich bin gerade dabei eine Temperatursteuerung zu bauen. Bisher habe ich es geschafft über zwei Buttons eine Solltemperatur einzustellen, sowie mit einem DS18B20 die aktuelle Temperatur zu messen.

Das Kombinieren von beidem macht mir Probleme. Die Temperatur messung läuft in einem While Loop welcher, wenn ich das richtig verstehe verhindert, dass ich meine Soll Temperatur einstellen darf.

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

LiquidCrystal lcd(7,8,9,10,11,12);
#define ONE_WIRE_BUS 4 /* Digitalport Pin 4 definieren */

OneWire ourWire(ONE_WIRE_BUS); /* Ini oneWire instance */
DallasTemperature sensors(&ourWire);/* Dallas Temperature Library für Nutzung der oneWire Library vorbereiten */


const int TempUp = 6;     // the number of the pushbutton pin
const int TempDown = 5;     // the number of the pushbutton pin
const int maxTemp = 25; //this can be any number - it's the number of steps between dimmest and brightest. 

// variables will change:
int temperatur = 18;
int interval=1;

void setup() {
  // initialize the LED pin as an output:
  // pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pins as an input:
  pinMode(TempUp, INPUT);     
  pinMode(TempDown, INPUT);   

   lcd.begin(20,4);
   lcd.setCursor(0,1);
   lcd.print("Soll Temp:");
   lcd.setCursor(11,1);
   lcd.print(temperatur);
   lcd.setCursor(13,1);
   lcd.print((char)223);
   lcd.print("C");

   sensors.begin();/* Inizialisieren der Dallas Temperature library */
   
   lcd.setCursor(0,0);
   lcd.print("Ist Temp :");
}

void loop(){

 sensors.requestTemperatures(); // Temp abfragen
    lcd.setCursor(11,0);
    lcd.print(sensors.getTempCByIndex(0) );
    lcd.setCursor(16,0);
    lcd.print((char)223);
    lcd.print("C");
}

void adresseAusgeben(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  Serial.print("Suche 1-Wire-Devices...\n\r");// "\n\r" is NewLine 
  while(ourWire.search(addr)) {
    Serial.print("\n\r\n\r1-Wire-Device gefunden mit Adresse:\n\r");
    for( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n\r");
      return;
    }
  }
  Serial.println();
  ourWire.reset_search();
   
  return;

  
    if (digitalRead(TempUp) == HIGH && temperatur < maxTemp){ 
      temperatur = temperatur + interval; 
      //if the temperatur Up button is pushed, add one degree of temperatur to the current level
      lcd.setCursor(12,1);
      lcd.print(temperatur);
      lcd.setCursor(14,1);
      lcd.print((char)223);
      lcd.print("C");
      }

    
    if (digitalRead(TempDown) == HIGH && temperatur > 0){
      temperatur = temperatur - interval;
      //if the temperatur Down button is pushed, subtract one degree of temperatur from the current level
      lcd.setCursor(12,1);
      lcd.print(temperatur);   
      lcd.setCursor(14,1);
      lcd.print((char)223);
      lcd.print("C");
      }
    delay(200);

      
}

Ich denke das der Teil unterhalb von “return” nach oben muss und es zwei “break” Kriterien geben muss.
So was wie:

if (digitalRead(TempUp) == HIGH)
break;


if (digitalRead(TempDown) == HIGH)
break;

Aber ich bekomme das einfach nicht hin…
Wäre jemand von euch so nett und könnte mir bitte helfen?

Vielen Dank,
Torsten

Hmm...

Trenne Anzeige, von Tastenauswertung.. Denke nebenläufig. Verzichte auf Delay

Ablaufsteuerung

Meine Standardantwort zu Ablaufsteuerungen: Eine Stichworte Sammlung für Google Suchen: Endlicher Automat, State Machine, Multitasking, Coroutinen, Ablaufsteuerung, Schrittkette,

BlinkWithoutDelay,

Blink Without Delay

Der Wachmann

Multitasking Macros Intervall Macros

Aktuell wird die FunktionadresseAusgeben()mit ihrer while-Schleife gar nicht verwendet. Und wohl eigentlich auch nicht gebraucht, weil die DallasTemperature library alls Sensoren sucht, und du einfach den ersten gefundenen verwendest: sensors.getTempCByIndex(0) läuft schon andauernd in der loop() Funktion.

Bevor du mehrere Beispiele sinnvoll zu einem sketch zusammenkopieren kannst, solltest du sie einzeln und unverändert ausprobiert haben und halbwegs verstehen.

Der zweite Teil von adresseAusgeben() kann wegen derreturn; - Anweisung nicht drankommen.

Diesen Teil, erstmal mit demdelay(200);, könntest du in die loop() Funktion übernehmen. Dann würde alle 0.2 sec geprüft, ob gerade eine der Tasten gedrückt ist, und gegebenenfalls die Solltemp verändert und neu angezeigt. Ausserdem würde dadurch auch die Temperaturmessung und Anzeige auf den 0.2s Zyklus verlangsamt. Wenn dein sensors.getTemp nicht sowiesoschon das Ganze wegen zu häufigem Aufruf selbst runterbremst...

Danach kannst du combies Tipps

Trenne Anzeige, von Tastenauswertung.. Denke nebenläufig. Verzichte auf Delay

beherzigen.

Hallo zusammen,

vielen Dank euch beiden für euer Interesse. In der Zwischenzeit habe ich alles Umgebaut. Der Code funktioniert jetzt. Was Ihr mir mit dem “Denke nebenläufig” sagen wolltet habe ich ehrlich gesagt nicht verstanden…

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

LiquidCrystal lcd(7,8,9,10,11,12);

#define ONEWIRE_BUS 4

OneWire oneWire(ONEWIRE_BUS);
DallasTemperature oneWireSensors(&oneWire);

//Gehört zur Temperatur messung
float ActualTemp = 0;
byte Devices = 0;
byte Address[8];

// Konstanten für Buttons
const int TempUp = 6;        // Pin für TempUp Button
const int TempDown = 5;     // Pin für TempDown Button
const int maxTemp = 25;     // SetTemp Limit
double SetTemp = 20;         // Standard SetTemp
double interval = 0.5;        //  Erhöhungs intervall für SetTemp

const int relaisPin = 13;     // Pin für Relais
 
void setup()
{
//Display und Temp. Sensor und Relais initialisieren

    lcd.begin(20,4);
    oneWireSensors.begin();
    pinMode(relaisPin, OUTPUT);

// One wire Module finden

    while(oneWire.search(Address)) 
        Devices++;
    for (byte i = 0; i < 40; i++)




    

    lcd.clear();
    
    lcd.setCursor(0,0);
    lcd.print(String("Wintergarten"));

    lcd.setCursor(0,1);
    lcd.print(String("Temperatursteuerung"));
    
    lcd.setCursor(0,3);
    lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
    
}



void loop()
{

 //##################### SetTemp auslesen #######################################

 // SetTemp Sensor auslesen; getTempCByIndex(0) => Index 0 entspricht erstem gefundenem Sensor
 
    oneWireSensors.requestTemperatures();
    ActualTemp = oneWireSensors.getTempCByIndex(0);

// ActualTemp auf Display ausgeben

    lcd.setCursor(0,2);
    lcd.print(String("ActualTemp: " + String(ActualTemp) + (char)223 + "C"));


//######################  Buttons überwachen  ######################################


// Wenn der TempUp Button gedrückt wird, erhöhe die SetTemp um 1

      if (digitalRead(TempUp) == HIGH && SetTemp < maxTemp){ 
        SetTemp = SetTemp + interval; 

        lcd.setCursor(0,3);
        lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
      

      }
// Wenn der TempDown Button gedrückt wird, erniedrige die SetTemp um 1

       if (digitalRead(TempDown) == HIGH && SetTemp > 0){
         SetTemp = SetTemp - interval;
      
         lcd.setCursor(0,3);
         lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
      
      }
      
//Verzögerung stellt empfindlichkeit der Buttons ein. Zu keiner Wert hat zu doppelklicks geführt

    delay(50);  

//########################## Relais schalten ###############################################

      if (SetTemp > ActualTemp){
        digitalWrite(relaisPin, HIGH);
      }
      if (SetTemp < ActualTemp){
        digitalWrite(relaisPin, LOW);
      }
}

Wie gesagt, der Code läuft jetzt. Was mit aufgefallen ist, dass man die Buttons recht lange drücken muss, so ca. 1-2 Sek. bis die Soll Temperatur sich ändert. Woran kann das liegen?

Hier noch der Aufbau:

Nunja…

Du könntest das Temperatur auslesen in 2 Schritte aufteilen.
Auch muss man meist gar nicht so oft messen…

// 10 Sekunden was anderes tun
// Dann erst:
oneWireSensors.requestTemperatures();
// 1 Sekunde was anderes tun
// Dann erst:
oneWireSensors.getTempCByIndex(0);

Auch die LCD ausgaben, erst bei Veränderung.

Dann bleibt viel mehr Zeit für Tastenabfragen
Und damit bessert sich die Reaktionszeit.

drdrhase: ... Was Ihr mir mit dem "Denke nebenläufig" sagen wolltet habe ich ehrlich gesagt nicht verstanden...

Das ist auch nicht unbedingt leicht zu verstehen.

Damit ist gemeint, dass man so denken/programmieren soll, dass mehrere Aufgaben quasi gleichzeitig erledigt werden können. „Quasi“ deshalb, weil auf einem Mikrocontroller wie dem ATmega328 faktisch nichts wirklich gleichzeitig ablaufen kann. Man kann aber so programmieren, dass unterschiedliche Aufgaben so schnell im Wechsel erledigt werden, dass es so aussieht, als liefen sie parallel/gleichzeitig.

Gruß

Gregor

Das hört sich super an, würde ich gerne alles beherzigen.

Hab Ihr vielleicht Beispiele für mich? Wie kann man einen Teil des Programms 10 Sek. liegen lassen und was anderes machen?

drdrhase: Das hört sich super an, würde ich gerne alles beherzigen. Hab Ihr vielleicht Beispiele für mich? Wie kann man einen Teil des Programms 10 Sek. liegen lassen und was anderes machen?

Indem man die zu erledigenden Aufgaben so programmiert, dass sie in kleinen Schritten ausgeführt werden können. Dann konstruiert man etwas, das dafür sorgt, dass jede Aufgabe einen Schritt macht und das Programm mit der nächsten Aufgabe fortfährt.

Ein ziemlich gut verständliches Konstrukt ist ein „endlicher Automat“. Was mir dazu einfiel, habe ich vor einiger Zeit hier ins Netz gekippt. Das ist vielleicht nicht „auf die Schnelle“ nachzuvollziehen, aber im Kasten am Ende der Seite sind zwei alternative Erklärungen verlinkt. Eine davon ist die „Nachtwächter-Erklärung“, die diese „Denke“ IMO sehr verständlich erklärt.

Gruß

Gregor

Vielen Dank, ich glaube den Nachtwächter habe ich verstanden.

Werde ich mir am WE mal ansehen. :)

https://github.com/milesburton/Arduino-Temperature-Control-Library/blob/master/examples/WaitForConversion/WaitForConversion.pde Da siehst du wie du vermeiden kannst, dass.requestTemperatures(); dich lange blockiert.

Wenn und nachdem du verstanden hast, wie "nebenläufig" funktioniert, kannst du auch mal nach INTERVAL.H hier im Forum suchen, da wird das ganze dann wieder versteckt, so dass man nicht mehr erkennen kann wie es funktioniert, es aber super einfach aussieht.

Hallo zusammen,

hier der Zwischenstand:

/*
=====================================================================================================
Temperatursteuerung mit Arduino Nano, HD44780 20x4, DS18S20 Tempertursensor, zwei Buttons und Relais
=====================================================================================================

Code erstellt nach folgenden Tutorials:

https://deloarts.wordpress.com/2016/03/14/get-temperature-via-ds18b20/
https://www.arduino.cc/en/Tutorial/InputPullupSerial
https://www.arduino.cc/en/Tutorial/LiquidCrystalDisplay
https://forum.arduino.cc/index.php?topic=423688.0

=====================================================================================================
*/

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

LiquidCrystal lcd(7,8,9,10,11,12);

#define ONEWIRE_BUS 4

OneWire oneWire(ONEWIRE_BUS);
DallasTemperature oneWireSensors(&oneWire);

//Gehört zur Temperatur messung
float ActualTemp = 0;
byte Devices = 0;
byte Address[8];

// Konstanten für Buttons
const int TempUp = 3;        // Pin für TempUp Button
const int TempDown = 2;     // Pin für TempDown Button
const int maxTemp = 25;     // SetTemp max Limit
double SetTemp = 20;         // Standard SetTemp
double interval = 0.5;        //  Erhöhungs intervall für SetTemp

const int relaisPin = 13;     // Pin für Relais

unsigned long temp_timestore;   // Variable Speicher für Systemzeit.
unsigned long relais_timestore;

 
void setup()
{
//Display initialisieren

    lcd.begin(20,4);  

// Button Pins initialisieren

    pinMode(TempUp, INPUT_PULLUP);
    pinMode(TempDown, INPUT_PULLUP);
    
// One wire Module finden

      oneWireSensors.begin();
    while(oneWire.search(Address)) 
        Devices++;
    for (byte i = 0; i < 40; i++)




// Statischer Text  

    lcd.clear();
    
    lcd.setCursor(0,0);
    lcd.print(String("Wintergarten"));

    lcd.setCursor(0,1);
    lcd.print(String("Temperatursteuerung"));
    
    lcd.setCursor(0,3);
    lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
    
}



void loop()
{

 //##################### Temp auslesen #######################################

 // Temperatur Sensor auslesen; getTempCByIndex(0) => Index 0 entspricht erstem gefundenem Sensor


  if (millis() - temp_timestore> 2000 ) {       //Interval für Temp auslesen
    
  
    oneWireSensors.requestTemperatures();
    ActualTemp = oneWireSensors.getTempCByIndex(0);

// ActualTemp auf Display ausgeben

    lcd.setCursor(0,2);
    lcd.print(String("ActualTemp: " + String(ActualTemp) + (char)223 + "C"));


    temp_timestore = millis();   //Aktuelle Systemzeit speichern für nächsten Interval

  }


//######################  Buttons überwachen  ######################################


// Wenn der TempUp Button gedrückt wird, erhöhe die SetTemp um 1

      if (digitalRead(TempUp) == LOW && SetTemp < maxTemp){ 
        SetTemp = SetTemp + interval; 

        lcd.setCursor(0,3);
        lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
      

      }
// Wenn der TempDown Button gedrückt wird, erniedrige die SetTemp um 1

       if (digitalRead(TempDown) == LOW && SetTemp > 0){
         SetTemp = SetTemp - interval;
      
         lcd.setCursor(0,3);
         lcd.print(String("SetTemp   : " + String(SetTemp) + (char)223 + "C"));
      
      }
      
//Verzögerung stellt empfindlichkeit der Buttons ein. Zu keiner Wert hat zu doppelklicks geführt

    delay(300);  

//########################## Relais schalten ###############################################

if (millis() - relais_timestore> 2000 ) {       //Interval für Temp auslesen

      if (SetTemp > ActualTemp){
        digitalWrite(relaisPin, LOW);
      }
      if (SetTemp < ActualTemp){
        digitalWrite(relaisPin, HIGH);
      }
    relais_timestore = millis();   //Aktuelle Systemzeit speichern für nächsten Interval
}
      
}

Ich haben noch ein bisschen umgebaut und es schein zu funktionieren! Ich werde bei Gelegenheit noch das Schaltbild und ein paar Fotos ergänzen.

Vielen Dank für eure Hilfe!

@michael_x
Ich muss mir deinen Beitrag noch in Ruhe anschauen, bin etwas bussy im Moment…