Thermostat mit Arduino, DS18B20, 20x4 LCD

Hallo Leute,

Ich bin neu hier im Forum und auch in Sachen Arduino und Programmierung.
Ich habe Elektroniker gelernt und kenne mich soweit mit SSteuerungen wie einer Logo und einer S7 aus.

Mein erstes Projekt soll auf einem Arduino Uno basieren.

Zur Funktion:

Gebaut wurde eine Heizbox, die mit PTC Heizelementen ausgestattet ist um die Box auf 60 Grad auf zu Heizen.
Über die Ausgänge des Uno werden Transistoren angesteuert, die wiederum die 12VDC zu den Heizelementen durch schalten.

Eine RGB LED soll zusätzlich die Temperaturen grob anzeigen:

LED Blau → unter 50 Grad
LED Grün → zwischen 50 Grad und 60 Grad
LED Rot → über 60 Grad

Demensprechend sollen auch die Heizelemente angesteuert werden:
Fällt die Temperatur unter 50 Grad → Heizelemente einschalten
Erreicht die Temperatur 60 Grad → Heizelemente ausschalten
Hysterese also erstmal 10 Grad.

Ich bin jetzt mittlerweile so weit, dass ich den Temperaturfühler (1-Wire) einlesen kann und auf dem Display in der zweiten Zeile darstellen kann.

In der 3 Zeile wird die feste Soll Temperatur angezeigt

und in der 4 Zeile soll angezeigt werden, ob gerade geheizt wird oder nicht.

Und da sind wir auch schon beim Knackpunkt, den if Bedingungen.
diese funktionieren nicht, es wird dauernd “Heizen AUS” ausgegeben auf dem Display und dementsprechen werden auch keine Outputs gesetzt.

Kann sich eventuell jemand erbarmen dem armen Arduino Neuling unter die Arme zu greifen und mir sagen wo mein Fehler liegt :-D?

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>



#define I2C_ADDR 0x27 // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

int BLED = 2;
int GLED = 3;
int RLED = 4;


// Data wire is plugged into pin 8 on the Arduino
#define ONE_WIRE_BUS 8

// Setup a oneWire instance to 
//communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.

DeviceAddress boxThermometer = { 0x28, 0xFF, 0x8F, 0x64, 0x86, 0x16, 0x05, 0xB8 };

int heater1 = 9; // heatergroup 1 control pin
int heater2 = 10; // heatergroup 2 control pin
int heater3 = 11; // heatergroup 3 control pin


float boxtemp = 0;

void setup(void)
{
  // Start up the library
  sensors.begin();
  // set the resolution to 12 bit
  sensors.setResolution(boxThermometer, 12);
  
  
  pinMode(BLED, OUTPUT); // LED's
  pinMode(GLED, OUTPUT);
  pinMode(RLED, OUTPUT);
  
  digitalWrite(BLED, HIGH); // set LED's off
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);

  

lcd.begin(20,4); 
// columns, rows. use 16,2 for a 16x2 LCD, etc.

// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

lcd.print ("Thermobox");
lcd.print ("2017");

delay(4000);

lcd.clear(); 



pinMode(heater1, OUTPUT); // Box heatergroup 1
pinMode(heater2, OUTPUT); // Box heatergroup 2
pinMode(heater3, OUTPUT); // Box heatergroup 3

}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
lcd.print("Error");
} else {
lcd.print(tempC);
  }
 { boxtemp = sensors.getTempC(deviceAddress);

}
}

void loop(void)
{ 
  delay(500);

  sensors.requestTemperatures();

lcd.setCursor(0,0);
lcd.print("*****Temperatur*****");
  
lcd.setCursor(0,1);
lcd.print("Ist: ");

printTemperature(boxThermometer);

lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,2);
lcd.print("Soll: 60");
lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,3);
if (heater1 == HIGH || heater2 == HIGH || heater3 == HIGH)
{
lcd.print("Heizen EIN");
} else {
lcd.print("Heizen AUS"); }

if (boxtemp <=50)
{
  digitalWrite(BLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);
  digitalWrite(heater1, HIGH);
  digitalWrite(heater2, HIGH);
  digitalWrite(heater3, HIGH);
}

if (boxtemp >= 50.1 && boxtemp <= 60)

{
  digitalWrite(GLED, LOW);
  digitalWrite(RLED, HIGH);
  digitalWrite(BLED, HIGH);
}

if (boxtemp >= 60.1)
{
  digitalWrite(heater1, LOW);
  digitalWrite(heater2, LOW);
  digitalWrite(heater3, LOW);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(BLED, HIGH);}

  delay(500); 
  
  }

Vielen Dank für die Antwort. Ich werde es nachher gleich ausprobieren.

Ein klassischer Fall von else-if

if (boxtemp <= 50)
 HeizungEin;
else if (boxtemp >= 60)
 HeizungAus;
else //50-60
 TemperaturOK;

Hallo DRDietrich

Habs jetzt nochmal versucht jedoch zeigt das Display immernoch Heizung aus unter 50 Grad =( iwo is noch der Wurm drin… evtl bei der übertragung der Temperatur in die If Bedingungen?

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>



#define I2C_ADDR 0x27 // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

int BLED = 2;
int GLED = 3;
int RLED = 4;


// Data wire is plugged into pin 8 on the Arduino
#define ONE_WIRE_BUS 8

// Setup a oneWire instance to 
//communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.

DeviceAddress boxThermometer = { 0x28, 0xFF, 0x8F, 0x64, 0x86, 0x16, 0x05, 0xB8 };

int heater1 = 9; // heatergroup 1 control pin
int heater2 = 10; // heatergroup 2 control pin
int heater3 = 11; // heatergroup 3 control pin


float boxtemp = 0.0;

void setup(void)
{
  // Start up the library
  sensors.begin();
  // set the resolution to 12 bit
  sensors.setResolution(boxThermometer, 12);
  
  
  pinMode(BLED, OUTPUT); // LED's
  pinMode(GLED, OUTPUT);
  pinMode(RLED, OUTPUT);
  
  digitalWrite(BLED, HIGH); // set LED's off
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);

  

lcd.begin(20,4); 
// columns, rows. use 16,2 for a 16x2 LCD, etc.

// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

lcd.print ("Thermobox");
lcd.print ("2017");

delay(4000);

lcd.clear(); 



pinMode(heater1, OUTPUT); // Box heatergroup 1
pinMode(heater2, OUTPUT); // Box heatergroup 2
pinMode(heater3, OUTPUT); // Box heatergroup 3

}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
lcd.print("Error");
} else {
lcd.print(tempC);
  }
 { boxtemp = sensors.getTempC(deviceAddress);

}
}

void loop(void)
{ 
  delay(500);

  sensors.requestTemperatures();

lcd.setCursor(0,0);
lcd.print("*****Temperatur*****");
  
lcd.setCursor(0,1);
lcd.print("Ist: ");

printTemperature(boxThermometer);

lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,2);
lcd.print("Soll: 60");
lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,3);
if (heater1 == HIGH || heater2 == HIGH || heater3 == HIGH)
{
lcd.print("Heizen EIN");
} else {
lcd.print("Heizen AUS"); }

if (boxtemp <= 50)
{
  digitalWrite(BLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);
  digitalWrite(heater1, HIGH);
  digitalWrite(heater2, HIGH);
  digitalWrite(heater3, HIGH);
}

else if (boxtemp >= 60)

{  digitalWrite(heater1, LOW);
  digitalWrite(heater2, LOW);
  digitalWrite(heater3, LOW);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(BLED, HIGH);
  
}

else
{ digitalWrite(GLED, LOW);
  digitalWrite(RLED, HIGH);
  digitalWrite(BLED, HIGH);
}

  delay(500);
if (heater1 == HIGH || heater2 == HIGH || heater3 == HIGH)

Du willst den Zustand des Pins vergleichen. Nicht die Pin-Nummer

Ich kann dir nicht ganz folgen... Ich dachte es wäre der richtige code, wenn ich sagen möchte:

Wenn alle drei heater outputs high sind, dann schreibe Heizung EIN auf das display, ansonsten Schreibe Heizung AUS....

Oder hab ich da gerade ein Denkfehler?

Schon mal was von digitalRead() gehört?

Ja, aber ich dachte das mache ich indirekt, da die heater weiter oben ja bestimmten pins zugeordnet sind...

Also müsste ich um den zustand des textes zu ändern die pins direlt abfragen mit digitalread in der if bedingung? Sorry bin wie gesagt noch neu und nicht zu 100% fit. Gruß

MasterOfPuppets: Sorry bin wie gesagt noch neu und nicht zu 100% fit.

Dann ist Lesen der Dokumentation, Testen und Verstehen der Beispiele angesagt.

Was für einen Sinn soll es machen, die Heizungspins abzufragen? Die können doch nur per Programm gesetzt werden, und zwar dann wenn die Heizung eingeschaltet werden soll. Und wenn alle Heizungen gleichzeitig geschaltet werden sollen, dann reicht dafür 1 Pin.

So ganz verkehrt ist es nicht. Statt dessen könnte man sich natürlich auch gleich beim Einschalten den Zustand merken. Oder man schreibt beim Setzen der Pins auch sofort auf das Display. Aber die Pins zu setzen und wo anders auslesen geht auch.

Hallo danke für die Hilfestellung.
Jetzt läuft es soweit Super mit diesem Code

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>



#define I2C_ADDR 0x27 // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

int BLED = 2;
int GLED = 3;
int RLED = 4;

int heater1 = 9; // heatergroup 1 control pin
int heater2 = 10; // heatergroup 2 control pin
int heater3 = 11; // heatergroup 3 control pin


float boxtemp = 0.0;

// Data wire is plugged into pin 8 on the Arduino
#define ONE_WIRE_BUS 8

// Setup a oneWire instance to 
//communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.

DeviceAddress boxThermometer = { 0x28, 0xFF, 0x8F, 0x64, 0x86, 0x16, 0x05, 0xB8 };



void setup(void)
{
  // Start up the library
  sensors.begin();
  // set the resolution to 12 bit
  sensors.setResolution(boxThermometer, 12);
  
  
  pinMode(BLED, OUTPUT); // LED's
  pinMode(GLED, OUTPUT);
  pinMode(RLED, OUTPUT);
  
  digitalWrite(BLED, HIGH); // set LED's off
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);

  

lcd.begin(20,4); 
// columns, rows. use 16,2 for a 16x2 LCD, etc.

// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

lcd.print ("Thermobox");
lcd.print ("2017");

delay(4000);

lcd.clear(); 



pinMode(heater1, OUTPUT); // Box heatergroup 1
pinMode(heater2, OUTPUT); // Box heatergroup 2
pinMode(heater3, OUTPUT); // Box heatergroup 3

}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
lcd.print("Error");
} else {
lcd.print(tempC);
  }
 { boxtemp = sensors.getTempC(deviceAddress);

}
}

void loop(void)
{ 
  delay(500);

  sensors.requestTemperatures();

lcd.setCursor(0,0);
lcd.print("*****Temperatur*****");
  
lcd.setCursor(0,1);
lcd.print("Ist: ");

printTemperature(boxThermometer);

lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,2);
lcd.print("Soll: 60");
lcd.print((char)223);
lcd.print("C");

if (boxtemp <= 58)
{
  digitalWrite(BLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);
  digitalWrite(heater1, HIGH);
  digitalWrite(heater2, HIGH);
  digitalWrite(heater3, HIGH);
}

else if (boxtemp >= 62)

{ digitalWrite(heater1, LOW);
  digitalWrite(heater2, LOW);
  digitalWrite(heater3, LOW);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(BLED, HIGH);
  
}

else
{ digitalWrite(GLED, LOW);
  digitalWrite(RLED, HIGH);
  digitalWrite(BLED, HIGH);
}

lcd.setCursor(0,3);
if (digitalRead(9)==HIGH || digitalRead(10)==HIGH || digitalRead(11)==HIGH)
{
lcd.print("Heizen EIN");
} else {
lcd.print("Heizen AUS"); }

  delay(500); 
  
  }

Dass ich alle abfragen möchte hat folgenden Hintergrund:

Ich möchte noch eine Funktion implementieren, damit nicht alle 3 Heizungen zur selben Zeit eingeschaltet werden, sondern sobald die Vorgaben für Heizen EIN gegeben sind Heizung1 sofort eingeschaltet wird, Heizung2 mit 10 Sekunden Verzögerung, nachdem Heizung2 eingeschaltet ist, wiederum Heizung 3 mit 10 Sekunden Verzögerung.
Der Hintergrund ist nämlich folgender, die Heizungen haben eine extrem hohe Stromaufnahme in den ersten Sekunden wenn sie kalt sind und würden meine Sicherung durchbrennen lassen.

wo ich wiederum nun beim nächsten Problem wäre.
Eine Funktion von der ich dachte, sie wäre am leichtesten von allem einzubauen entpuppt sich als das schwierigste für mich. Mit einem Delay von 10000 nach Heizung1 HIGH und Heizung2 HIGH würde mein Programm für einen Durchlauf über 20 Sekunden benötigen in der keine Aktualisierung der Temperatur auf dem Display statt findet.

Nach etwas Recherche bin ich auf die mills() Funktion gestoßen die auch in dem Beispiel BlinkWithoutDelay benutzt wird. So wie es für mich aussieht ist dies für mich die EInzige möglichkeit delays zwischen die Heizungen zu setzen ohne dass etwas anderes davon beeinflusst wird. Leider scheitere ich vollkommen an dieser Funktion und wäre froh wenn mir jemand Helfen könnte diese Funktion noch in meinen Sketch einzubauen… Dann wäre er nämlich fertig =)

Gruß.

Such mal nach der Nachtwächtererklärung (kein Witz). Dann wirst Du mehr von millis() verstehen.

Gruß Tommy

Mit den Task Makros kann man das Einschalten sofort hinschreiben:

void Heizung() {
 taskBegin();
 taskWaitFor(HeizungEin);
 digitalWrite(heater1, HIGH);
 taskDelay(10000);
 digitalWrite(heater2, HIGH);
 taskDelay(10000);
 digitalWrite(heater3, HIGH);
//warten auf Ausschalten
 taskWaitFor(!HeizungEin);
 digitalWrite(heater1, LOW);
 digitalWrite(heater2, LOW);
 digitalWrite(heater3, LOW);
 taskEnd();
}

Vielen lieben dank, dass ist natürlich wesentlich einfacher und unkomplizierter.... kann ich diesen task also direkt in meinen loop einbinden und muss in meiner if bedingung nur noch mit dem stichwort Heizung EIN den task für das einschalten abrufen?

Gruß

Jede Task in einem Programm muß bei jedem Durchlauf von loop() aufgerufen werden, damit sie alle quasi-parallel ablaufen können. Siehe die Beispiele zu ALib0. Man könnte den Code (taskBegin bis taskEnd) auch direkt in loop() einfügen, damit geht aber IMO die Übersichtlichkeit verloren.

Die Bedingung (hier HeizungEin) kann eine globale Variable sein, man könnte sie aber auch als Parameter übergeben. Dann reicht es, irgendwo im Programmablauf HeizungEin auf true oder false zu setzen, um die Heizung ein- oder auszuschalten.

Vielen Dank für die nette Hilfe, ich werde mich jetzt mal durch die Beispiele arbeiten um auch zu verstehen was ich da einfüge.

Gruß

So habs jetzt einmal ausprobiert und den task für meine Einschaltbedingung eingebunden.

Funktioniert beim ersten mal ganz Super, jedoch auch nur beim allerersten mal wenn das Programm startet. Wenn die Heizung dann jedoch ausschaltet und die Bedingungen für das wiedereinschalten gegeben sind, werden sofort alle 3 eingeschaltet und der Task wird ignoriert =(.

#include <ALib0.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>




#define I2C_ADDR 0x27 // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

int BLED = 2;
int GLED = 3;
int RLED = 4;

int heater1 = 9; // heatergroup 1 control pin
int heater2 = 10; // heatergroup 2 control pin
int heater3 = 11; // heatergroup 3 control pin


float boxtemp = 0.0;

// Data wire is plugged into pin 8 on the Arduino
#define ONE_WIRE_BUS 8

// Setup a oneWire instance to 
//communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.

DeviceAddress boxThermometer = { 0x28, 0xFF, 0x8F, 0x64, 0x86, 0x16, 0x05, 0xB8 };



void setup(void)
{
  // Start up the library
  sensors.begin();
  // set the resolution to 12 bit
  sensors.setResolution(boxThermometer, 12);
  
  
  pinMode(BLED, OUTPUT); // LED's
  pinMode(GLED, OUTPUT);
  pinMode(RLED, OUTPUT);
  
  digitalWrite(BLED, HIGH); // set LED's off
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);

  

lcd.begin(20,4); 
// columns, rows. use 16,2 for a 16x2 LCD, etc.

// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

lcd.print ("Thermobox");
lcd.print ("2017");

delay(4000);

lcd.clear(); 



pinMode(heater1, OUTPUT); // Box heatergroup 1
pinMode(heater2, OUTPUT); // Box heatergroup 2
pinMode(heater3, OUTPUT); // Box heatergroup 3

}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
lcd.print("Error");
} else {
lcd.print(tempC);
  }
 { boxtemp = sensors.getTempC(deviceAddress);

}
}

void loop(void)
{ 
  delay(500);

  sensors.requestTemperatures();

lcd.setCursor(0,0);
lcd.print("*****Temperatur*****");
  
lcd.setCursor(0,1);
lcd.print("Ist: ");

printTemperature(boxThermometer);

lcd.print((char)223);
lcd.print("C");

lcd.setCursor(0,2);
lcd.print("Soll: 60");
lcd.print((char)223);
lcd.print("C");

if (boxtemp <= 25)
{
  digitalWrite(BLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(RLED, HIGH);

 taskBegin();
 digitalWrite(heater1, HIGH);
 taskDelay(10000);
 digitalWrite(heater2, HIGH);
 taskDelay(10000);
 digitalWrite(heater3, HIGH);
 taskEnd();

}

else if (boxtemp >= 26)

{ digitalWrite(heater1, LOW);
  digitalWrite(heater2, LOW);
  digitalWrite(heater3, LOW);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, HIGH);
  digitalWrite(BLED, HIGH);
  
}

else
{ digitalWrite(GLED, LOW);
  digitalWrite(RLED, HIGH);
  digitalWrite(BLED, HIGH);
}

lcd.setCursor(0,3);
if (digitalRead(9)==HIGH || digitalRead(10)==HIGH || digitalRead(11)==HIGH)
{
lcd.print("Heizen EIN");
} else {
lcd.print("Heizen AUS"); }

  delay(500); 
  
  }

So wird der Task Code nicht bei jedem Durchlauf von loop() durchlaufen, und dann kann das nicht funktionieren.

Aber wieso nicht?

Der Task steht doch direkt im loop, wie die if bedingungen auch....

Gruß