INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Temperaturregelung Kohlegrill (ähnl. PartyQ)
21.04.2015, 13:52
Beitrag #1
Temperaturregelung Kohlegrill (ähnl. PartyQ)
Hallo Arduino-Gemeinde,

ich habe vor einigen Wochen begonnen mich mit Arduino und allem was dazugehört zu beschäftigen. Meine Vorkenntnisse beschreibe ich mal als grobe Vorahnung, aber keineswegs Fachkenntnisse.
Der Grund für meinen Entschluss ist ein Problem gewesen, welches beim Grillen über einen langen Zeitraum aufgetreten ist. Es ist nämlich nicht so einfach, mit Kohle oder Briketts die Temperatur im Grill über mehrere Stunden konstant auf einer Temperatur zu halten.
Mein Bruder hatte sich dann dazu entschlossen, sich eine fertige Apparatur für dieses Problem zu kaufen. Jedoch hat dieses Gerät mit ca. 160€ schon einen recht stolzen Preis (PartyQ). Also habe ich mir gesagt, das muss auch billiger gehen. Zudem kommt es bei einer Grillsession von 24 Std durchaus vor, dass man 4x die 4 AAA Batterien tauschen darf. Nachts um 4 Uhr sehr lästig. Tongue

Ich habe mich in den letzten Wochen durch etliche Foren und Sketches gelesen und habe mir hier und da ein Häppchen abgeschaut. Herausgekommen ist ein im Prinzip funktionierende Regelung, d.h. auf dem Schreibtisch funktioniert alles, am Grill habe ich es noch nicht ausprobiert. Das Verhalten ist jedoch sehr nahe an dem Luxusteil von PartyQ.
   

Ich habe versucht folgende Features unterzubringen:
- beleuchtetes Display (über Timer abschaltbar)
- Anzeige von SOLL und IST Temperatur
- Menüführung und Auswahl durch Taster
- Verwendung eines Thermofühlers vom Maverick Grillthermometer ET-732
- LED Anzeige für optische Anzeige SOLL-IST-Temperatur
- Spannungsversorgung über 12V Netzteil
- Vorwahl der Lüfterdrehzahl

Code:
/*
BBQ Temperaturregelung fuer Holzkohlegrills
Temperaturbereich: 0-250°C
Messfühler: NTC 1MOhm, Maverick ET-732
Features:
Vorwahl der BBQ Solltemperatur
Timer fuer LED Hintergrundbeleuchtung
Booster-Taste fuer schnelles Aufheizen
3-LED-Anzeige fuer SOLL-IST-Temperatur
*/
#include <LiquidCrystal.h>
#include <Wire.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define button_menue 7 //Pin Menuetaster
#define backlight 9 // Pin Hintergrundbeleuchtung LCD Display
#define contrast 6 // Pin Kontrast LCD Display
#define adjust_up 8 // Pin Wahltaster "erhoehen"
#define adjust_down 13 // Pin Wahltaster "verringern"
#define THERMISTORPIN A0 // Pin Thermofuehler        
#define THERMISTORNOMINAL 1000000 // Widerstand des Thermofuehlers bei 25 Grad C      
#define TEMPERATURENOMINAL 25 // Nominaltemperatur des Thermofuehlers in Grad C  
#define NUMSAMPLES 10 // Anzahl Temperaturmesswerte, die geglaettet werden
#define BCOEFFICIENT 4608 // Beta Koeffizient des Thermofuehlers
#define SERIESRESISTOR 1000000 // Widerstand des Vergleichswiderstands (Spannungsteiler)  
#define led_red 15 // LED Zustand IST Temp > SOLL Temp
#define led_green 16 // LED Zustand IST Temp = SOLL Temp
#define led_blue 17 // LED Zustand IST Temp < SOLL Temp
#define luefter 10 // Pin Luefteransteuerung

//Bereich Berechnung BBQ Temperatur:
int samples[NUMSAMPLES];
float steinhart = 0;

//Bereich MenueCounter:
int menuePoints = 7; //Anzahl Menuepunkte
int menueCounter = 6; //Counter zaehlt bei Betaetigung von button_menue hoch

//Bereich Menue Taster:
boolean buttonPressedMenue = false; //prueft den Status des Tasters MENUE
boolean buttonPressedUp = false; //prueft den Status des Tasters UP
boolean buttonPressedDown = false; //prueft den Status des Tasters DOWN

//Bereich SOLL Temperatur:
int targetTemp = 25; //Zieltemperatur fuer BBQ
int minTarget = 0; //minimal einzustellende SOLL Temperatur
int maxTarget =250; //maximal einzustellende SOLL Temperatur

//Bereich Helligkeit LCD:
int valueBrightness = 5;
int minBrightness = 0;
int maxBrightness = 9;

//Bereich Status LEDs:
int hystereseTemp = 2; // +- Wert um die Solltemperatur wo die Status LED_green leuchtet

//Bereich Lueftersteuerung:
int stepLuefter; // Zaehlt in welchem Schritt sich der Luefter befindet (AN oder AUS)
unsigned long timerLuefter = 200; // erster Startwert fuer Luefter AN
unsigned long preMillisLuefter = 0;
unsigned long currMillisLuefter = 0;
int maxDiffTemp = 20;
int rpmLuefter = 255;
int maxRpmLuefter = 255;
int minRpmLuefter = 105;

//Bereich Kontrast LCD: (noch nicht im Schaltplan vorgesehen)
int valueContrast = 100;
int minContrast = 0;
int maxContrast = 255;

//Bereich Timer Hintergrundbeleuchtung:
long interval = 6000; // Zeit, die die Beleuchtung nach Tastendruck an ist
long minInterval = 1000;
long maxInterval = 9000;
unsigned long previousvalue = 0; // Variable zum Auswerten der verstrichenen Zeit
int ledLcdStatus = 0; // 0 fuer LCD LED Timer aus; 1 fuer LCD LED Timer an

void setup() {
  analogReference(EXTERNAL);
  delay(100);
  pinMode(button_menue, INPUT);
  pinMode(adjust_up, INPUT);
  pinMode(adjust_down, INPUT);
  pinMode(backlight, OUTPUT);
  pinMode(contrast, OUTPUT);
  pinMode(luefter, OUTPUT);
  lcd.begin(16, 2); // Declares the number of the lines and columns

  //Begruessung
  lcd.setCursor(2,0);
  lcd.print("Welcome to:");
  lcd.setCursor(2,1);
  lcd.print("BooBQ v1.2");

  // Test Luefter
  digitalWrite(luefter, HIGH);
  delay(2000);
  digitalWrite(luefter, LOW);

  //Test LEDs
  for (int d=0; d <=3; d++){
  digitalWrite(led_blue, HIGH);
  delay(200);
  digitalWrite(led_green, HIGH);
  delay(200);
  digitalWrite(led_blue, LOW);
  digitalWrite(led_red, HIGH);
  delay(200);
  digitalWrite(led_green, LOW);
  delay(200);
  digitalWrite(led_red, LOW);
  }
  delay (1000);
  lcd.clear(); //Display leeren
}

void loop() {

  analogWrite(contrast, valueContrast);

  ledTemp();
  BBQtemp();
  lueftercontrol();

  if (ledLcdStatus==0){
    analogWrite(backlight, (230-(valueBrightness*25)));
  }
  else {
    backlightTimer();
  }
  if ((digitalRead(button_menue)==HIGH)&&(buttonPressedMenue==false)){ //beim Loslassen des Tasters springt das Menue einen Eintrag weiter
    buttonPressedMenue=true;
    menueCounter = menueCounter + 1;
    lcd.clear();
  }
  if (digitalRead(button_menue)==LOW){
    buttonPressedMenue=false;
  }
  if (menueCounter >= menuePoints){
    menueCounter = 0;
  }


  switch (menueCounter){  
  case 0:

    lcd.setCursor(0,0);
    lcd.print("BBQ Temp: ");
    if (steinhart<100){
      lcd.setCursor(13,0);
      lcd.print(" ");
    }
    if (steinhart<10){
      lcd.setCursor(12,0);
      lcd.print("  ");
    }
    lcd.setCursor(11,0);
    lcd.print(steinhart, 0);
    lcd.setCursor(14,0);
    lcd.println("\337C");
    lcd.setCursor(0,1);
    lcd.print("Men\365       Boost");

    if (digitalRead(adjust_up)==LOW){ //beim Druecken wird der Boost eingeschaltet
      buttonPressedUp=false;
      digitalWrite(luefter, HIGH);
    }

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){ //beim Loslassen wird der Boost ausgeschaltet
      buttonPressedUp=true;
      digitalWrite(luefter, LOW);
    }

    break;

  case 1:

    lcd.setCursor(0,0);
    lcd.print("Soll Temp: ");
    if (targetTemp<100){
      lcd.setCursor(13,0);
      lcd.print(" ");
    }
    if (targetTemp<10){
      lcd.setCursor(12,0);
      lcd.print("  ");
    }
    lcd.setCursor(11,0);
    lcd.print(targetTemp);
    lcd.setCursor(14,0);
    lcd.print("\337C");
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird die Soll Temp um 1 hochgezaehlt
      targetTemp = targetTemp + 1;
      if (targetTemp >= maxTarget) {
        targetTemp = maxTarget;
      }
      delay(100);
    }
    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird die Soll Temp um 1 runtergezaehlt
      targetTemp = targetTemp - 1;
      if (targetTemp <= minTarget) {
        targetTemp = minTarget;
      }
      delay(100);
    }
    break;

  case 2:
    lcd.setCursor(0,0);
    lcd.print("LED Timer:");
    if (ledLcdStatus==1){
      lcd.setCursor(11,0);
      lcd.print("AN ");
    }
    if (ledLcdStatus==0){
      lcd.setCursor(11,0);
      lcd.print("AUS");
    }
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird der Timer eingeschaltet
      ledLcdStatus = 1;
    }

    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird der Timer ausgeschaltet
      ledLcdStatus = 0;
    }
    break;

  case 3:
    lcd.setCursor(0,0);
    lcd.print("Zeit LED an:");
    lcd.setCursor(13,0);
    lcd.print((interval / 1000));
    lcd.setCursor(15,0);
    lcd.print("s");
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird die Zeit um 1 sec hochgezaehlt
      interval = interval + 1000;
      if (interval >= maxInterval) {
        interval = maxInterval;
      }
      delay(200);
    }
    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird die Zeit um 1 sec runtergezaehlt
      interval = interval - 1000;
      if (interval <= minInterval) {
        interval = minInterval;
      }
      delay(200);
    }
    break;

  case 4: // noch nicht in Funktion
    lcd.setCursor(0,0);
    lcd.print("Kontrast:");
    if (valueContrast<100){
      lcd.setCursor(12,0);
      lcd.print(" ");
    }
    if (valueContrast<10){
      lcd.setCursor(11,0);
      lcd.print("  ");
    }
    lcd.setCursor(10,0);
    lcd.print(valueContrast);
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird der Kontrastwert um 5 hochgezaehlt
      valueContrast = valueContrast + 5;
      if (valueContrast >= maxContrast) {
        valueContrast = maxContrast;
      }
      delay(200);
    }
    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird der Kontrastwert um 5 runtergezaehlt
      valueContrast = valueContrast - 5;
      if (valueContrast <= minContrast) {
        valueContrast = minContrast;
      }
      delay(200);
    }
    break;

  case 5:
    lcd.setCursor(0,0);
    lcd.print("Helligk. LCD:");
    lcd.setCursor(14,0);
    lcd.print(valueBrightness);
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird der Helligkeitswert um 1 hochgezaehlt
      valueBrightness = valueBrightness + 1;
      if (valueBrightness >= maxBrightness) {
        valueBrightness = maxBrightness;
      }
      delay(200);
    }
    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird der Helligkeitswert um 1 runtergezaehlt
      valueBrightness = valueBrightness - 1;
      if (valueBrightness <= minBrightness) {
        valueBrightness = minBrightness;
      }
      delay(200);
    }
    break;

  case 6:
    lcd.setCursor(0,0);
    lcd.print("rpm L\365fter:");
    lcd.setCursor(12,0);
    lcd.print(map(rpmLuefter, 0, 255, 0, 5000));
    lcd.setCursor(0,1);
    lcd.print("Men\365   \177-     -\176");

    if ((digitalRead(adjust_up)==HIGH)&&(buttonPressedUp==false)){
      buttonPressedUp=true;
    }
    if (digitalRead(adjust_up)==LOW){ //beim Loslassen wird die Drehzahl um 50 hochgezaehlt
      buttonPressedUp=false;
      rpmLuefter = rpmLuefter + 50;
      if (rpmLuefter >= maxRpmLuefter) {
        rpmLuefter = maxRpmLuefter;
      }
      delay(200);
    }
    if ((digitalRead(adjust_down)==HIGH)&&(buttonPressedDown==false)){
      buttonPressedDown=true;
    }
    if (digitalRead(adjust_down)==LOW){ //beim Loslassen wird die Drehzahl um 50 runtergezaehlt
      buttonPressedUp=false;
      rpmLuefter = rpmLuefter - 50;
      if (rpmLuefter <= minRpmLuefter) {
        rpmLuefter = minRpmLuefter;
      }
      delay(200);
    }
    break;

  }
}

void BBQtemp(){ //Beginn der Auswertung und Berechnung der IST Temperatur

  uint8_t i;
  float average;

  // misst N Werte mit einer kurzen Verzoegerung
  for (i=0; i< NUMSAMPLES; i++) {
    samples[i] = analogRead(THERMISTORPIN);
    delay(10);
  }
  // bilden des Mittelwerts aus den Messwerten
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average += samples[i];
  }
  average /= NUMSAMPLES;

  // Umwandeln des Mittelwertes in Widerstandswert
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;

  steinhart = average / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invertieren
  steinhart -= 273.15;                         // Konvertieren in C
  steinhart = (int)steinhart;

  //Ende der Auswertung und Berechnung der IST Temperatur
}

void backlightTimer(){

  unsigned long currentvalue = millis();
  if((digitalRead(button_menue)) == LOW) {
    previousvalue = currentvalue;
    analogWrite(backlight, (230-(valueBrightness*25)));
  }
  if((digitalRead(adjust_up)) == LOW) {
    previousvalue = currentvalue;
    analogWrite(backlight, (230-(valueBrightness*25)));
  }
  if((digitalRead(adjust_down)) == LOW) {
    previousvalue = currentvalue;
    analogWrite(backlight, (230-(valueBrightness*25)));
  }
  if(((currentvalue - previousvalue) > interval)) {
    previousvalue = currentvalue;
    digitalWrite(backlight, HIGH);
  }
}

void ledTemp(){

  if (steinhart < (targetTemp - hystereseTemp)){
    digitalWrite(led_blue, HIGH);
    digitalWrite(led_red, LOW);
    digitalWrite(led_green, LOW);
  }
  if (steinhart > (targetTemp + hystereseTemp)){
    digitalWrite(led_blue, LOW);
    digitalWrite(led_red,HIGH);
    digitalWrite(led_green, LOW);
  }
  if ((steinhart >= (targetTemp - hystereseTemp))&&(steinhart <= (targetTemp + hystereseTemp))){
    digitalWrite(led_blue, LOW);
    digitalWrite(led_red,LOW);
    digitalWrite(led_green, HIGH);
  }
}

void lueftercontrol(){
  int diffTemp = targetTemp - steinhart;
  if (diffTemp <= 0){
    diffTemp = 0;
  }

  currMillisLuefter = millis();
  if (currMillisLuefter - preMillisLuefter > timerLuefter){
    stepLuefter++;

    switch (stepLuefter){

    case 1:
      if (diffTemp > 0){
        analogWrite(luefter, rpmLuefter);
        timerLuefter = (diffTemp * 1000); // Zeit Luefter an
      }
      break;

    case 2:
      if (diffTemp < maxDiffTemp - 5){
        digitalWrite(luefter, LOW);
        timerLuefter = ((maxDiffTemp - diffTemp) * 1000); // Zeit Luefter aus
      }
      break;

    default:
      stepLuefter = 0;
      timerLuefter = 0;
    }
    preMillisLuefter = currMillisLuefter;
  }
}

Wie gesagt, ich bin blutiger Anfänger und wenn jemandem noch Fehler auffallen oder eine Idee hat, wie man etwas schöner gestalten kann, bin ich sehr dankbar über eure Kommentare.

Vielleicht sieht ja jemand von euch auch auf Anhieb die beiden kleinen Fehler, die ich noch nicht wegbekommen habe. Zum Einen habe ich das Phänomen, dass bei der Spannungsversorgung über das 12V Netzteil (1000mA) die Einer-Stelle der berechneten BBQ-Temperatur immer zittert. Das heißt sie springt immer sehr schnell (Millisekunden) um +-2 °C um die tatsächliche Temperatur. Verwende ich einen 9V Block oder die USB-Spannungsversorgung, ist das Flackern weg. Bei einem Aufbau zuvor hatte ich einen 100k NTC, da war das PRoblem auch nicht vorhanden. Kann es etwas mit dem hochohmigen NTC zu tun haben?
Das Zweite ist, dass ich für die LED Anzeige eigentlich die Farben blau (zu kalt), grün (optimal) und rot (zu heiß) verwenden wollte. Ich musste jedoch die grüne LED durch eine gelbe ersetzen, da ich die grüne nicht zum Leuchten bekommen habe. Ich habe sie einzeln auf dem Breadbord mit dem gleichen Funduino Uno am gleichen Pin getestet und siehe da: sie leuchtet. Aber in der Schaltung tut sie es nicht. Auch keine rote oder blaue, nur die gelbe. Hat da jemand eine Erklärung für?

Vielen Dank schon mal für eure konstruktiven Rückmeldungen.

Gruß Stefan

   
   
   
   
   
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Temperaturregelung für Temperofen alter_Peter 3 4.620 22.06.2014 09:22
Letzter Beitrag: alter_Peter

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste