Temperaturreglung 3D-Drucker

Hallo Community,

ich habe für meinen 3D-Drucker eine Temperaturreglung gebaut. Leider habe ich das Problem das nach ein paar Stunden der Arduino einfriert und nur ein resett hilft die Reglung wieder zu starten. Bis er sich aufhängt funktioniert alles wie es gewünscht ist.

Folgende Bauteile wurden verbaut.

-Arduino Uno
-LCD 16x2 mit I2C
-2x DHT 22
-10kohm Poti
-Meanwell RS15 Spannungsversorgung
-Noctua PWM FAN

Schaltplan im Anhang

Kurze Funktionsbeschreibung:
-mit Poti lässt sich die Soll Temp zwischen min und max einstellen.
-der Mittelwert der zwei DHT22 wird für die Temperaturreglung verwendet (alle 2 sek. wird Temp abgefragt)
-Dutycycle (PWM) Lüfter 10%-100% also der Lüfter läuft immer mit mind. 10%
-stellt man das Poti auf min dann soll der Lüfter unabhängig von der Temperatur mit 100% laufen
-stellt man das Poti auf max dann soll der Lüfter unabhängig von der Temperatur auf 10% laufen
-erste Zeile LCD zeigt die Soll Temp an oder ob Lüfter auf max oder min gestellt ist
-zweite Zeile LCD zeigt die Ist Temp und die aktuelle Geschwindigkeit des Lüfters

#include <TimerOne.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"

#define DHTPIN3 3
#define DHTPIN2 2
#define DHTTYPE DHT22

DHT dht2(DHTPIN2, DHTTYPE);
DHT dht3(DHTPIN3, DHTTYPE);
LiquidCrystal_I2C lcd(0x27,16,2);

int Poti = 0;
int wechsler = 0;
int min_temp = 10;
int max_temp = 60;
float soll_temp = 0;
float ist_temp =0;
float t2 = 0;
float t1 = 0;
float dutyCycle_P = 0;

unsigned long Startzeit_1 = 0;
unsigned long Startzeit_2 = 0;
unsigned long Startzeit_3 = 0;

const int fanPin = 9;
float dutyCycle = 0;

void setup() {
  // put your setup code here, to run once:
lcd.init();
Timer1.initialize(40);  // 40 us = 25 kHz
Serial.begin(9600);

dht2.begin();
dht3.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
Poti = analogRead(A0);
soll_temp = map(Poti, 0, 1023, min_temp, max_temp);
//Serial.println(soll_temp);
lcd.backlight();
//Nachricht ausgeben
if ((soll_temp > min_temp) && (soll_temp < max_temp))
{ 
lcd.setCursor(0,0);
lcd.print("Soll Temp ");
lcd.setCursor(10,0);
lcd.print(soll_temp,1);
lcd.setCursor(14,0);
lcd.print(" C");
}
else if (soll_temp < (min_temp + 1))
{
lcd.setCursor(0,0);
lcd.print("  Luefter 100%  ");  
}
else if (soll_temp > (max_temp -1 ))
{
lcd.setCursor(0,0);
lcd.print("  Luefter 10%   ");  
}


if ((millis() - Startzeit_2) > 4000)
{
  if (wechsler == 0)
  {
    lcd.setCursor(0,1);
    lcd.print("Ist  Temp");
    lcd.setCursor(10,1);
    lcd.print(ist_temp,1);
    lcd.setCursor(14,1);
    lcd.print(" C");
    wechsler = 1;
  }
  else if (wechsler == 1)
  {
    if (dutyCycle == 100)
    {
      lcd.setCursor(0,1);
      lcd.print("FAN Speed  ");
      lcd.setCursor(11,1);
      lcd.print(dutyCycle,0);
      lcd.setCursor(14,1);
      lcd.print(" %");
    }
    if (dutyCycle < 100)
    {
      lcd.setCursor(0,1);
      lcd.print("FAN Speed   ");
      lcd.setCursor(12,1);
      lcd.print(dutyCycle,0);
      lcd.setCursor(14,1);
      lcd.print(" %");
    }
    wechsler = 0;
  }
  Startzeit_2 = millis();
}


if ((millis() - Startzeit_1) > 2000)
{
  t1 = dht2.readTemperature();
  t2 = dht3.readTemperature();
  Startzeit_1 = millis();
  //Serial.print(millis());
  //Serial.print(t1);
  //Serial.print(t2);
}

ist_temp = (t1 + t2) / 2;

if ((soll_temp > min_temp) && (soll_temp < max_temp))
{
  if ((millis() - Startzeit_3) > 2000)
{
  dutyCycle_P = dutyCycle_P + (ist_temp - soll_temp);

  if (dutyCycle_P < 100)
  {
    dutyCycle_P = 100;
  }
  if (dutyCycle_P > 1000)
  {
    dutyCycle_P = 1000;
  }
  Startzeit_3 = millis();
}
}
else if (soll_temp == min_temp)
{
  dutyCycle_P = 1000;
}
else if (soll_temp == max_temp)
{
  dutyCycle_P = 100;
}
else
{
  dutyCycle_P = 500;
}

dutyCycle = map(dutyCycle_P, 100, 1000, 10, 100);
Timer1.pwm(fanPin, (dutyCycle / 100) * 1023);

}

Hi

Hat wohl noch Nichts mit Deinem Freeze zu tun, aber

  • LCD nur Ausgaben, wenn was zum Ausgeben da ist, feste Texte müssen nur 1x geschrieben werden.

Drück Mal STRG+T in der IDE - Das rückt den Sketch auf Klammer-Ebene ein, macht den Kram lesbarer.

Kommentare wären auch schön, unschön sind die durchgezählten Variablen (mindestens die Startzeiten).

Mir ist noch nicht klar, wo die DHT22 sitzen und welche Temperatur Du regeln möchtest - für Düse scheinen mir die DHT deutlich zu groß.

MfG

Auf den ersten Blick kann ich keinen Grund für das Einfrieren entdecken. Evtl mal eine Test-Anzeige (z.B. millis(()/1000) auf dein LCD in einem deiner gegebenen Zyklen) und genau schauen, ob sie immer zur gleichen Zeit stehen bleibt.

Oder/Und diesen TimerOne Timer1 einfach mal auf Verdacht raus. Pin 9 am Uno kann ganz normales Hardware-PWM per analogWrite. (Oder hab ich was übersehen?)

Oder/Und diesen TimerOne Timer1 einfach mal auf Verdacht raus. Pin 9 am Uno kann ganz normales Hardware-PWM per analogWrite. (Oder hab ich was übersehen?)

PWM Lüfter (4Pin Lüfter) sind meist recht pingelig, was die Frequenz angeht.

Also, da dran drehen muss man sowieso.

Hallo,

ja das hätte ich noch dazu schreiben sollen. Der 3D-Drucker ist in einem Isolierten Gehäuse eingebaut. Die Innentemperatur des Gehäuses wird mit dem Arduino geregelt.

postmaster-ino:
Hi

Hat wohl noch Nichts mit Deinem Freeze zu tun, aber

  • LCD nur Ausgaben, wenn was zum Ausgeben da ist, feste Texte müssen nur 1x geschrieben werden.

MfG

Okay muss ich mich nochmal mit beschäftigen. Dies ist mein erstes Projekt mit LCD.

michael_x:
Oder/Und diesen TimerOne Timer1 einfach mal auf Verdacht raus. Pin 9 am Uno kann ganz normales Hardware-PWM per analogWrite. (Oder hab ich was übersehen?)

bei meinen anderen Schaltungen mit PWM hab ich immer direkte Portmanipulation mit dem Timerregister gemacht. Allerdings brauch der PWM FAN 25khz als PWM Frequenz. Das hab ich nicht gewusst wie das geht. Deshalb die TimerOne Bibliothek.

Der Code jetzt etwas besser sortiert und mit Kommentaren. Vergebt mir falls nicht alles so Programmierer mäßig ist. Ich bin Maschinenbauer und hab im Studium nur mal 4 Wochen C++ gehabt. Aber so als Hobby macht ein Bisschen Arduino basteln schonmal Spaß.

#include <TimerOne.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"

#define DHTPIN3 3         //Anschlusspin Temp Sensor 2
#define DHTPIN2 2         //Anschlusspin Temp Sensor 1
#define DHTTYPE DHT22     //Sensor Typ definieren

DHT dht2(DHTPIN2, DHTTYPE);
DHT dht3(DHTPIN3, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);

int Poti = 0;             //Variable für Potiwert
int wechsler = 0;         //Variable welcher Text angezeigt werden soll
int min_temp = 10;        //minimalste einstellbare Temp
int max_temp = 60;        //maximalste einstellbare Temp
float soll_temp = 0;      //Variable Soll Temp
float ist_temp = 0;       //Variable Ist Temp
float t2 = 0;             //Variable Temp Sensor 2 auslesen
float t1 = 0;             //Variable Temp Sensor 1 auslesen
float dutyCycle_P = 0;    //Variable zur Berechnung des dutyCycle abhängig der Temp differenz soll ist (in Promill)
float dutyCycle = 0;      //Übergabe Variable für TimerOne Bibo (in Prozent)

unsigned long Startzeit_1 = 0;  //Variable für blinkwithoutdelay 1
unsigned long Startzeit_2 = 0;  //Variable für blinkwithoutdelay 2
unsigned long Startzeit_3 = 0;  //Variable für blinkwithoutdelay 3

const int fanPin = 9;     //Fan Pin definieren


void setup() {
  // put your setup code here, to run once:

  lcd.init();             //LCD initialisieren
  //Timer1 Initialisieren
  Timer1.initialize(40);  //Timer 1 initialisieren PWM Frequenz einstellen(40 us = 25 kHz)
  Serial.begin(9600);

  dht2.begin();           //Sensor 1 aktivieren
  dht3.begin();           //Sensor 2 aktivieren
}

void loop() {
  // put your main code here, to run repeatedly:
  Poti = analogRead(A0);  //Potiwert auslesen

  //Soll Temp Zahlenbereich konvertieren
  soll_temp = map(Poti, 0, 1023, min_temp, max_temp);

  lcd.backlight();        //LCD Licht an

  //Soll Temp in Zeile 1 schreiben von LCD wenn sie zwischen min und max liegt
  if ((soll_temp > min_temp) && (soll_temp < max_temp))
  {
    lcd.setCursor(0, 0);
    lcd.print("Soll Temp ");
    lcd.setCursor(10, 0);
    lcd.print(soll_temp, 1);
    lcd.setCursor(14, 0);
    lcd.print(" C");
  }
  //wenn Soll Temp auf min dann Lüfter 100% in Zeile 1 schreiben
  else if (soll_temp < (min_temp + 1))
  {
    lcd.setCursor(0, 0);
    lcd.print("  Luefter 100%  ");
  }
  //wenn Soll Temp auf max dann Lüfter 10% in Zeile 1 schreiben
  else if (soll_temp > (max_temp - 1 ))
  {
    lcd.setCursor(0, 0);
    lcd.print("  Luefter 10%   ");
  }

  //alle vier Sekunden wechselt die Anzeige von Zeile 2
  if ((millis() - Startzeit_2) > 4000)
  {
    //wenn "Wechsler" Variable = 0 dann schreibe "Ist Temp" in Zeile 2 und setze "Wechsler" Variable auf = 1
    if (wechsler == 0)
    {
      lcd.setCursor(0, 1);
      lcd.print("Ist  Temp");
      lcd.setCursor(10, 1);
      lcd.print(ist_temp, 1);
      lcd.setCursor(14, 1);
      lcd.print(" C");
      wechsler = 1;
    }
    //wenn "Wechsler" Variable = 1 dann schreibe "FAN Speed" in Zeile 2 und setze "Wechsler" Variable auf = 0
    else if (wechsler == 1)
    {
      //schreibe FAN Speed wenn 3 Zeichen
      if (dutyCycle == 100)
      {
        lcd.setCursor(0, 1);
        lcd.print("FAN Speed  ");
        lcd.setCursor(11, 1);
        lcd.print(dutyCycle, 0);
        lcd.setCursor(14, 1);
        lcd.print(" %");
      }
      //schreibe FAN Speed wenn 2 Zeichen
      if (dutyCycle < 100)
      {
        lcd.setCursor(0, 1);
        lcd.print("FAN Speed   ");
        lcd.setCursor(12, 1);
        lcd.print(dutyCycle, 0);
        lcd.setCursor(14, 1);
        lcd.print(" %");
      }
      wechsler = 0;
    }
    Startzeit_2 = millis();   //setze Startzeit 2 auf millis
  }

  //alle 2 Sekunden werden die Temp Sensoren ausgelesen
  if ((millis() - Startzeit_1) > 2000)
  {
    t1 = dht2.readTemperature();
    t2 = dht3.readTemperature();
    Startzeit_1 = millis();
    //Serial.print(millis());
    //Serial.print(t1);
    //Serial.print(t2);
  }

  ist_temp = (t1 + t2) / 2;   //Mittelwert aus beiden Temperaturen bilden

  //wenn Soll Temp zwischen min und max liegt dann ausführen
  if ((soll_temp > min_temp) && (soll_temp < max_temp))
  {
    //alle 2 Sekunden wird die Differenz zwischen IST und Soll Temp als Störgröße auf Regelgröße aufsummiert
    if ((millis() - Startzeit_3) > 2000)
    {
      dutyCycle_P = dutyCycle_P + (ist_temp - soll_temp);
      //falls Regelgröße dabei kleiner als min Lüfter speed wird so setze sie auf min Lüfter Speed (10%)
      if (dutyCycle_P < 100)
      {
        dutyCycle_P = 100;
      }
      //falls Regelgröße dabei größer als min Lüfter speed wird so setze sie auf max Lüfter Speed (100%)
      if (dutyCycle_P > 1000)
      {
        dutyCycle_P = 1000;
      }
      Startzeit_3 = millis(); /setze Startzeit 3 auf millis
    }
  }
  //wenn Soll Temp (Poti) auf min Temp steht dann setze denn Lüfter auf 100% (unabhängig der Temperatur)
  else if (soll_temp == min_temp)
  {
    dutyCycle_P = 1000;
  }
  //wenn Soll Temp (Poti) auf max Temp steht dann setze denn Lüfter auf 10% (unabhängig der Temperatur)
  else if (soll_temp == max_temp)
  {
    dutyCycle_P = 100;
  }
  //falls ein Sensor unplausible Werte ausgibt oder ein Fehler in Soll Temp entsteht dann setze Lüfter auf 50%
  else
  {
    dutyCycle_P = 500;
  }
  //Zahlenbereich des berechneten Promill Dutycycle_P konvertieren auf DutyCycle in Prozent
  dutyCycle = map(dutyCycle_P, 100, 1000, 10, 100);
  //Lüftergeschwindigkeit 
  Timer1.pwm(fanPin, (dutyCycle / 100) * 1023);

}