Härteofen-Steuergerät

Verfasst von Glenn Hoffmann

Seit ich denken kann, bin ich leidenschaftlicher Handwerker. Ich liebe das Tüfteln und Experimentieren. Nichtsdestotrotz bin ich Ingenieur geworden und studier auch gern, bevor ich probier.

14 November 2021

Härteofen Bauanleitung

Vorab möchte ich euch sagen, dass ein gewisses maß an Eigenarbeit notwendig ist, um das Projekt nachzubauen. Es gibt im Netz unzählige Anleitungen, dass ihr kein Problem haben solltet, um das nötige Fachwissen zu erlangen.

Bauteile

Für mein Steuergerät verwende ich ein Arduino Uno. Das ist ein Mikrocontroller, denn man mit der Programmiersprache C++ programmiert. Dazu verwende ich ein LCD Display mit 20×4 Zeichen inkl. I2C Interface. Dieses ist oft schon an den Displays verbaut. Achtet drauf! Einen Temperatursensor mit dem Namen MAX6675 Modul K und zwei SSR. SSR steht für Solid State Relais. Diese Relais brauchen einen Kühlkörper aus Aluminium. Diese gibt es oft schon im Set. Diese Relais werden vom Arduino Uno angesteuert, um die Heizspirale mit Strom zu versorgt. Alle Bauteile findet man entspannt im Netz. Wundert euch nicht, ich habe mich gegen Affiliate-Links entschieden. Schaut einfach im Netz nach dem günstigsten Angebot. 

Ich habe mich für einen recht dünnen Heizdraht entschieden, damit ich eine geringe Leistung erreiche. Der Ofen sollte in meiner Werkstatt stehen. Dort habe ich keinen Stromanschluss, sondern nur eine kleine Solaranlage und einen Stromerzeuger, der mit seinen 2,5kw Dauerleistung nicht überfordert sein sollte. Vermutlich geht mit dem dünneren Querschnitt des Drahtes auch eine verringerte Lebenszeit einher.

Steuergerät selbst programmieren

Die meisten Steuergeräte auf dem Markt (PID-Regler) oder anders gesagt, die meisten in Härteofenselbstbauten verbauten Regler können nur eine definierte Temperatur anfahren. So einen Regler wollte ich nicht nutzen. Ich möchte mehr Funktionen haben. Aufheizzeiten, Abkühlzeiten, vordefinierte Härtetemperaturen für Stahlsorten usw. und da ich unglaublich gerne tüftle, ist Programmieren genau das Richtige für mich.

Um einem Arduino Uno das Steuerprogramm zu verpassen, muss man das dazugehörige Programm downloaden und installieren. Das Steuerprogramm benötigt auch noch ein paar Bibliotheken. Ich habe sie für euch schon zusammengestellt. Hier könnt ihr sie herunterladen. Diese müsst ihr nur in den Ordner „libraries“ ablegen. Anschließend kopiert man den Programmcode in das Fenster und sendet den Code einfach per Button. Auf YouTube findet ihr dazu unzählige Tutorials.

Programmcode
// CLK = D2; DT = D3; SW = D4; SSR = D6; SCL = A5; SDA = A4; SCK = D13; CS = D10; SO = D11;

#include <PID_v1.h>
//#include <EEPROM.h>
//#include „EEPROMAnything.h“
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#include <RotaryEncoder.h>
#include „max6675.h“

// Rotary Encoder
#define PIN_IN1 2
#define PIN_IN2 3
#define Button 4

// LCD Display
LiquidCrystal_I2C lcd(0x27, 20, 4);

const int thermoDO = 11;
const int thermoCS = 10;
const int thermoCLK = 13;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);

int Aufheizen = 0;
int PreAufheizen;
int Abkuehlen = 0;
int PreAbkuehlen;
int x, k;
int y = 0;
int newPos;
int pos;
double TempPoint = 25;
double PreTempPoint;
const int Spirale = 6;
double Output;
double IstTemp;
bool los;
bool PostAbkuehlen = false;
int Val1;
int PreVal;

double Kp=10, Ki=0, Kd=0;
PID myPID(&IstTemp, &Output, &TempPoint, Kp, Ki, Kd, DIRECT);

void setup() {
  Serial.begin(9600);
  pinMode(Button, INPUT_PULLUP);
  pinMode(Spirale, OUTPUT);
  lcd.begin();
  lcd.backlight();
  encoder.setPosition(1);
  IstTemp = thermocouple.readCelsius();
//  EEPROM_readAnything(0, Kp);
//  EEPROM_readAnything(1, Ki);
//  EEPROM_readAnything(2, Kd);
//  EEPROM_readAnything(3, TempPoint);
//  EEPROM_readAnything(4, Aufheizen);
//  EEPROM_readAnything(5, Abkuehlen);
  //windowStartTime = millis();
  //initialize the variables we’re linked to
  pos = 0;
  PreTempPoint = TempPoint;
  los = false;
  y = 0;
  //tell the PID to range between 0 and the full window size
  //myPID.SetOutputLimits(0, WindowSize);
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  Startbildschirm();
}

void loop() {
  myPID.Compute();
  pos = 1;
  Startseite();
  if (los == true) Heizen();

  if (digitalRead(Button) == LOW)
  {
    delay(1000);
    if (digitalRead(Button) == LOW)
    {
      if (los == true) {
        los = false;
        digitalWrite(Spirale, LOW);
        lcd.clear();
        lcd.setCursor(9, 1);
        lcd.print(„STOP“);
        delay(4000);
        lcd.clear();
      }
      else {
        if (Aufheizen != 0) {
          //PreTempPoint = TempPoint;
          PreAufheizen = Aufheizen;
          TempPoint = 0;
        }
        if (Abkuehlen != 0) {
          //PreTempPoint = TempPoint;
          PreAbkuehlen = Abkuehlen;
        }        
        los = true;
        lcd.clear();
        lcd.setCursor(7, 1);
        lcd.print(„HEIZEN“);
        delay(4000);
        lcd.clear();
      }
    }
    else
    {
      lcd.clear();
      delay(500);
      Auswaehlen();
    }
  }
}
// Solltemperatur einstellen
void Auswaehlen() {
  encoder.setPosition(pos);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(„Temp.-Konfigurieren“);
  lcd.setCursor(2, 1);
  lcd.print(„Soll-Temp. :“);
  lcd.setCursor(2, 2);
  lcd.print(„Aufheizzeit:“);
  lcd.setCursor(2, 3);
  lcd.print(„Abk\xF5hlzeit :“);
  lcd.setCursor(16, 1);
  lcd.print(int (TempPoint));
  lcd.setCursor(16, 2);
  lcd.print(Aufheizen);
  lcd.setCursor(16, 3);
  lcd.print(Abkuehlen);
  lcd.setCursor(0, pos);
  lcd.print(\x7E);
  do {
    encoder.tick();
    newPos = encoder.getPosition();
    if (pos != newPos) {
      pos = newPos;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(„Temp.-Konfigurieren“);
      lcd.setCursor(2, 1);
      lcd.print(„Soll-Temp. :“);
      lcd.setCursor(2, 2);
      lcd.print(„Aufheizzeit:“);
      lcd.setCursor(2, 3);
      lcd.print(„Abk\xF5hlzeit :“);
     
      lcd.setCursor(16, 1);
      lcd.print(int (TempPoint));
      lcd.setCursor(16, 2);
      lcd.print(Aufheizen);
      lcd.setCursor(16, 3);
      lcd.print(Abkuehlen);
      lcd.setCursor(0, pos);
      lcd.print(\x7E);
     
      if (pos == 4) {
        pos = 1;
        PIDmenu();
        break;
      }
      if (pos == 0) {
        pos = 3;
        PIDmenu();
        break;
      }
    }
    if (digitalRead(Button)==LOW) {
      delay(1000);
      if (digitalRead(Button) == LOW) x = 1;
      else Einstellen1();
      delay(500);
    }
  } while(x<1);
  x=0;
  lcd.clear();
  delay(500);
  Startseite();
}

void Einstellen1() {
  lcd.setCursor(0, pos);
  lcd.print(\xA5);
 if (pos == 1)
 {
   encoder.setPosition(TempPoint);
   Val1 = TempPoint;
 }
 if (pos == 2)
 {
   encoder.setPosition(Aufheizen);
   Val1 = Aufheizen;
 }
 if (pos == 3)
 {
   encoder.setPosition(Abkuehlen);
   Val1 = Abkuehlen;
 }
 do {
  encoder.tick();
  PreVal = encoder.getPosition();
  if (Val1 != PreVal) {
    Val1 = PreVal;
    if (pos == 1) {
      TempPoint = Val1;
      PreTempPoint = TempPoint;
      //EEPROM_writeAnything(3, TempPoint);
      lcd.setCursor(16, 1);
      lcd.print(int (TempPoint));
    }
    if (pos == 2) {
      Aufheizen = Val1;
      //EEPROM_writeAnything(4, Aufheizen);
      lcd.setCursor(16, 2);
      lcd.print(Aufheizen);
    }
    if (pos == 3) {
      Abkuehlen = Val1;
      //EEPROM_writeAnything(5, Abkuehlen);
      lcd.setCursor(16, 3);
      lcd.print(Abkuehlen);
    }
   }
   if (digitalRead(Button)==LOW) x = 1;
  } while(x<1);
  if (pos == 1) encoder.setPosition(2);
  if (pos == 2) encoder.setPosition(3);
  if (pos == 3) encoder.setPosition(1);
  x=0;
  lcd.clear();
  delay(500);
}

void Einstellen2() {
  lcd.setCursor(0, pos);
  lcd.print(\xA5);
 if (pos == 1)
 {
   encoder.setPosition(Kp);
   Val1 = Kp;
 }
 if (pos == 2)
 {
   encoder.setPosition(Ki);
   Val1 = Ki;
 }
 if (pos == 3)
 {
   encoder.setPosition(Kd);
   Val1 = Kd;
 }
 do {
  encoder.tick();
  PreVal = encoder.getPosition();
  if (Val1 != PreVal) {
    Val1 = PreVal;
    if (pos == 1) {
      Kp = Val1;
      //EEPROM_writeAnything(0, Kp);
      lcd.setCursor(6, 1);
      lcd.print(Kp);
    }
    if (pos == 2) {
      Ki = Val1;
      //EEPROM_writeAnything(1, Ki);
      lcd.setCursor(6, 2);
      lcd.print(Ki);
    }
    if (pos == 3) {
      Kd = Val1;
      //EEPROM_writeAnything(2, Kd);
      lcd.setCursor(6, 3);
      lcd.print(Kd);
    }
   }
   if (digitalRead(Button)==LOW) x = 1;
  } while(x<1);
  if (pos == 1) encoder.setPosition(2);
  if (pos == 2) encoder.setPosition(3);
  if (pos == 3) encoder.setPosition(1);
  x=0;
  lcd.clear();
  delay(500);
 }

void Startseite() {
  TempMessen();
  lcd.setCursor(0, 0);
  lcd.print(„Ist-Temp.  :“);
  lcd.setCursor(0, 1);
  lcd.print(„Soll-Temp. :“);
  lcd.setCursor(0, 2);
  lcd.print(„Aufheizzeit:“);
  lcd.setCursor(0, 3);
  lcd.print(„Abk\xF5hlzeit :“);

  lcd.setCursor(13, 0);
  lcd.print(int (IstTemp));
  lcd.print(\xDF);
  lcd.print(„C“);
  lcd.setCursor(13, 1);
  lcd.print(int (TempPoint));
  lcd.print(\xDF);
  lcd.print(„C“);
  lcd.setCursor(13, 2);
  lcd.print(Aufheizen);
  lcd.print(„min“);
  lcd.setCursor(13, 3);
  lcd.print(Abkuehlen);
  lcd.print(„min“);
}

void Startbildschirm() {
  lcd.clear();
  lcd.setCursor(4, 1);
  lcd.print(„HAND-FORGED“);
  lcd.setCursor(4, 2);
  lcd.print(„Version 1.0“);
  delay(4000);
  lcd.clear();
  Startseite();
}

void PIDmenu() {
  encoder.setPosition(pos);
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print(„PID-Konfigurieren“);
  lcd.setCursor(2, 1);
  lcd.print(„P:“);
  lcd.setCursor(2, 2);
  lcd.print(„I:“);
  lcd.setCursor(2, 3);
  lcd.print(„D:“);
  lcd.setCursor(6, 1);
  lcd.print(Kp);
  lcd.setCursor(6, 2);
  lcd.print(Ki);
  lcd.setCursor(6, 3);
  lcd.print(Kd);
  lcd.setCursor(0, pos);
  lcd.print(\x7E);
  do {
    encoder.tick();
    newPos = encoder.getPosition();
    if (pos != newPos) {
      pos = newPos;
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print(„PID-Konfigurieren“);
      lcd.setCursor(2, 1);
      lcd.print(„P:“);
      lcd.setCursor(2, 2);
      lcd.print(„I:“);
      lcd.setCursor(2, 3);
      lcd.print(„D:“);
      lcd.setCursor(6, 1);
      lcd.print(Kp);
      lcd.setCursor(6, 2);
      lcd.print(Ki);
      lcd.setCursor(6, 3);
      lcd.print(Kd);
      lcd.setCursor(0, pos);
      lcd.print(\x7E);
      if (pos == 4) {
        pos = 1;
        Auswaehlen();
        break;
      }
      if (pos == 0) {
        pos = 3;
        Auswaehlen();
        break;
      }
    }
    if (digitalRead(Button)==LOW) {
      delay(1000);
      if (digitalRead(Button) == LOW) x = 1;
      else Einstellen2();
    }
  } while(x<1);
  x=0;
  lcd.clear();
  delay(500);
}

void Heizen() {
  if (k == 300) {
    // Wenn die Ist-Temperatur höher is als die Voreingestellte, Abkühlzeit vorhanden ist und die Aufheizzeit vor ist
    if (PreTempPoint <= IstTemp) {
      if (Abkuehlen > 0) {
        if (Aufheizen == 0) PostAbkuehlen = true;
      }
    }
    if (PostAbkuehlen == true) {
      TempPoint = TempPoint – (PreTempPoint/PreAbkuehlen);
      Abkuehlen = Abkuehlen – 1;
      if (Abkuehlen == 0) los = false;
    } else {
      if (Aufheizen != 0) {
        TempPoint = (PreTempPoint/PreAufheizen) + TempPoint;
        Aufheizen = Aufheizen – 1;
      }
    }
    k = 0;
    lcd.clear();
  }
  k++;
  if (Output > 0) digitalWrite(Spirale, HIGH);
  else digitalWrite(Spirale, LOW);
}

void TempMessen() {
  if (y == 10) {
    IstTemp = thermocouple.readCelsius();
    y = 0;
    // Der Temperatursensor kann nur maximal alle 0,5 Sekunden abgefragt werden
  }
  y++;
  delay(100);
}

Schaltplan

Schaltplan Steuergerät Härteofen Hand Forged

Leistungsberechnung

Für die Berechnung der Leistung des Ofens gibt es eine kleine Formel.

P = U²/R 

Dafür benötigt man den Widerstand (R) des Heizdrahtes. Heizdrähte werden immer in Ohm pro Meter angegeben. Dieser wird einfach mit der verbauten Länge multipliziert. In meinem Fall hat der Draht einen Widerstand von 2,2Ohm/m. Ich verwendet 11 Meter Draht. Das U steht für die Stromstärke. In den meisten Fällen werden es wohl 230V sein. Daraus folgt:

P = 230²/(2,2*11) = 2185 Watt

Ca. 2,2 kW Leistung bekommt mein Stromerzeuger noch hin und damit sollte der Ofen in meiner Werkstatt laufen.

Fazit

Das Projekt hat mir nicht nur Freude bereitet. Hin und wieder gab es auch kleine Rückschläge. Verzögerter Versand bei den bestellten Artikeln, falsch zugeschnittene Bleche und Fummelarbeit bei den Heizspiralen und vieles mehr. Nicht desto trotz ist es genau mein Anspruch an Projekte. Es muss nicht immer alles rund laufen, es sollte nur zu einem Abschluss kommen. Und auch wenn das nicht gelingt, ist es in Ordnung. Solange man dem Scheitern eines Projektes etwas Positives entnehmen kann. Am Ende hat man immer dazugelernt.

Ich hoffe, meine Videos helfen euch bei dem Bau eines eigenen Härteofens. Stellt eure Fragen ruhig unten als Kommentar. So können auch andere davon profitieren!

 

Das könnte euch auch gefallen…..

Bandschleifer selber bauen

Bandschleifer selber bauen

Grundgedanke Wer Messer bzw. Klingen fertigen möchte, kommt um einen kraftvollen Bandschleifer nicht drum herum. Alles...

15 Kommentare

  1. Thomas Launhardt

    Cool,
    vielen Dank für die schnelle und doch recht umfangreiche Beschreibung der Steuerung in deinem Blog.

    Antworten
  2. Thomas Launhardt

    Hi,
    ich bekomme Fehlermeldungen beim Compilieren der Steuersoftware.
    Könntest du mir das File was bei dir funktioniert vielleicht mailen oder als download bereitstellen?

    Danke
    Thomas

    Antworten
    • Glenn Hoffmann

      Hi Thomas
      aus der Ferne lässt sich ein Fehler ohne weitere Angaben nicht beheben. Welche Fehlermeldung bekommst du denn? Hast du die Bibliotheken von mir heruntergeladen und in den entsprechenden Ordner getan?
      Gruß Glenn

      Antworten
      • Thomas Launhardt

        Hi,
        ich hab die Fehler gefunden, sie entstehen beim Kopieren des Codes von der Webseite, manche der Zeichen werden anscheinend nicht verfälscht. Z.Bsp. “ und – Zeichen wurden nicht dargestellt. Deshalb meine Bitte es als Download bereitzustellen. 😉

        LG
        Thomas

        Antworten
        • Hartmut

          Hallo Glenn,
          tolles Projekt hast du da auf die Beine gestellt.
          Ich bekomme allerdings, wie Thomas auch, Fehlermeldungen beim compilieren, die sich im Arduino Program unter „Werkzeuge“ und dann „Kodierung korrigieren“ beheben lassen sollten.
          Zeile 11 muss ich aber die Gänsefüsschen in eckige Klammern ändern.
          Beim compilieren blebt das Programm immer in der Zeile 405 mit dem Fehler : stray \303
          hängen, kannst du mir da bitte weiterhelfen?

          Antworten
          • Glenn Hoffmann

            Hallo Thomas,
            ich habe den Arduino-Code als Download bereitgestellt.
            Hoffentlich können so die Fehler behoben werden. Wichtig sind die Bibliotheken, die ich im Blogbeitrag auch bereitgestellt habe.
            Wieso er bei dir bei Zeile 405 hängen bleibt? Keine Ahnung!
            An der Stelle ist nur eine einfache Wenn-Dann abfrage, die keinen Fehler produzieren dürfte.
            Gruß Glenn

  3. Thomas Launhardt

    Hi,
    ich hätte noch eine Frage.
    Könntest du ein Schaltdiagramm machen?

    MAX6675 an D10,D11,D13,GND,+5V
    Rotary Encoder an D2,D3,D4,GND,+5V
    I2C Interface an SCL,SDA,GND,+5V
    SSR ???

    Würde mir sehr helfen!

    Danke
    Thomas

    Antworten
    • Glenn Hoffmann

      Hi Thomas, ich habe einen Schaltplan hinzugefügt.
      Gruß Glenn

      Antworten
      • Thomas Launhardt

        Vielen Dank Glenn,

        daß hilft mir sehr und ich bin beigeistert am basteln.

        Vielen Dank
        Thomas

        Antworten
    • Hartmut

      Hallo Glenn,
      Mit dem von dir bereitgestellen Code zum download hat das compilieren und programmieren sofort und ohne Fehler funktioniert.
      Danke dafür.
      Da ich meinen zukünftigen Ofen mit Kraftstrom betreiben möchte : schafft der Arduino an seinem Ausgang 3 parallel geschaltete SSR’s zu versorgen,(wäre am einfachsten), oder sollte ich noch einen Transistor dazwischen setzen ?
      Gruß
      Hartmut

      Antworten
      • Glenn Hoffmann

        Super Hartmut,
        ich hab mittlerweile zwei SSR am Arduino dran und noch läuft er. Beide auch am gleichen Ausgang. Ich hab allerdings nicht nachgemessen, wie hoch der Verbrauch der SSR sind.
        Gruß Glenn

        Antworten
  4. Rudi

    Hallo Glenn, entschuldige bitte dass ich einen älteren Beitrag wieder kommentiere. Ich wollte mal fragen, ob du noch weißt wo du die Keramiktragrohre bestellt hast? Die sind recht schwer in Längen um die 40cm zu finden.

    Antworten
  5. Christoph

    Hi Glenn,

    kannst du noch die Library, die du für dein Display genutzt hast? Ideal vielleicht mit der Version? Ich habe schon einige durchprobiert, aber es scheint bisher nicht die richtige dabei gewesen zu sein.

    Danke und schöne Grüße aus Franken,
    Christoph

    Antworten
    • Glenn Hoffmann

      Hi Christoph,
      die Bibliothek heist: „LiquidCrystal_I2C“. Ich hab leider keinen Link für dich. Nur die Datei selbst, die ich dir gleich per Mail zusende. Ich hoffe du kannst damit etwas anfangen.
      Gruß Glenn

      Antworten

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert