Hilfe beim Code einer Bediensoftware für Espressomaschine

Diskutiere Hilfe beim Code einer Bediensoftware für Espressomaschine im Grundsätzliches Forum im Bereich Fragen und Tipps; Liebe Leute, ich hab eine etwas dreiste Bitte. Ich arbeite gerade an dem Umbau einer günstigen Thermoblock-Maschine aus China (CRM3605). Ich habe...

  1. #1 Yoku-San, 02.09.2021
    Zuletzt bearbeitet: 02.09.2021
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Liebe Leute,

    ich hab eine etwas dreiste Bitte. Ich arbeite gerade an dem Umbau einer günstigen Thermoblock-Maschine aus China (CRM3605). Ich habe mittlerweile eine Bediensoftware für die Maschine geschrieben, nachdem ich die Knopfverschaltung inklusive LED-Beleuchtung des Bedienpanels dank @Pflunz verstanden hatte. Die Software kann die vier Knöpfe (Power, Coffee, Water, Steam) und das Steemwheel digital auslesen und führt dann gewünschte Funktionen durch. Thermoblock und Pumpe werden über AC Dimmer Module von RobotDyn geregelt. In dem Thermoblock ist ein NTC, der auch ausgelesen wird und mit dessen Hilfe via PID eine IDLE Temp von 97 Grad eingestellt ist. Im Brühmodus geht die dann auf 105 Grad. Im Brühmodus geht die Pumpe auf 30% Leistung und dann kann man während des Brühvorgangs mit Hilfe der Water- und Steamknöpfe die Pumpenleistung in 10er Schritten hoch und runterregeln. Mit Hilfe des eigenbauten Manometers sollte so eine Preinfusion und Pressure Profiling umgesetzt werden. Ich möchte nächste Woche die Platine mit dem ESP32 und den Modulen und Relays für die 3-Wege- und Wasserventile in die Maschine bauen anstelle der Platine des Herstellers. Da ich relativ unerfahren im Programmieren bin, würde ich mich freuen, wenn vielleicht einige von euch mal über den Code schauen, damit ich nicht irgendeinen Unsinn fabriziert habe und da irgendwas nach hinten losgeht. Ich würde mich über Kommentare freuen.

    Vielen Dank für eure Hilfe im Voraus!

    Lieben Gruß,

    Johannes
     
    Dingelding und Lancer gefällt das.
  2. #2 Yoku-San, 02.09.2021
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Code:
    #include <Arduino.h>
    #include <dimmable_light_linearized.h>
    #include <driver/rtc_io.h>
    #include <Thermistor.h>
    #include <NTC_Thermistor.h>
    #include <PID_v1.h>
    
    
    #define SENSOR_PIN             34 //AnalogPIN
    #define REFERENCE_RESISTANCE   4700
    #define NOMINAL_RESISTANCE     100000
    #define NOMINAL_TEMPERATURE    25
    #define B_VALUE                3950
    #define STM32_ANALOG_RESOLUTION 4095
    
    Thermistor* thermistor;
    
    const int numOfInputs = 5;
    const int inputPins[numOfInputs] = {4,16,17,5,9};
    const int syncPin = 7;
    const int ThreeWayValvePin = 6;
    const int WaterValvePin = 8;
    
    
    DimmableLightLinearized Pump(0);
    DimmableLightLinearized Thermoblock(2);
    
    int PowerButtonState = 0;
    int CoffeeButtonState = 0;
    int WaterButtonState = 0;
    int SteamButtonState = 0;
    int SteamWheelState = 0;
    int PumpPower = 30;
    int PumpPulseState = LOW;
    int inputState[numOfInputs];
    int lastInputState[numOfInputs] = {LOW,LOW,LOW,LOW, LOW};
    bool inputFlags[numOfInputs] = {LOW,LOW,LOW,LOW, LOW};
    
    long lastDebounceTime[numOfInputs] = {0,0,0,0,0};
    long debounceDelay = 50;
    unsigned long previousMillis = 0;
    const long interval = 500;
    
    //PID
    //Define Variables we'll be connecting to
    double Setpoint, Input, Output;
    //Specify the links and initial tuning parameters
    double Kp=68, Ki=1.2, Kd=100;
    PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
    
    
    //declare functions
    
    void setInputFlags();
    void resolveInputFlags();
    void printString();
    void updateLEDState(int input);
    void resolveOutputs();
    void PowerButtonOn();
    void PowerButtonOff();
    void CoffeeButtonOn();
    void CoffeeButtonOff();
    void WaterButtonOn();
    void WaterButtonOff();
    void SteamButtonOn();
    void SteamButtonOff();
    void SteamWheelOn();
    void SteamWheelOff();
    void ReadNTCTemp();
    
    void setup() {
      for(int i = 0; i < numOfInputs; i++) {
        pinMode(inputPins[i], INPUT_PULLDOWN);
      }
      Serial.begin(9600);
      pinMode(ThreeWayValvePin, OUTPUT);
      pinMode(WaterValvePin, OUTPUT);
      digitalWrite(ThreeWayValvePin, LOW);
      digitalWrite(WaterValvePin, LOW);
    
      thermistor = new NTC_Thermistor(
        SENSOR_PIN,
        REFERENCE_RESISTANCE,
        NOMINAL_RESISTANCE,
        NOMINAL_TEMPERATURE,
        B_VALUE,
        STM32_ANALOG_RESOLUTION
        );
        
    
      //PID
      //initialize the variables we're linked to
      Input = 0;
      Setpoint = 0;
    
      //turn the PID on
      myPID.SetMode(AUTOMATIC);
    
      DimmableLightLinearized::setSyncPin(syncPin);
      // VERY IMPORTANT: Call this method to start internal light routine
      DimmableLightLinearized::begin();
     
      rtc_gpio_pulldown_en((gpio_num_t)GPIO_NUM_4);
      esp_sleep_enable_ext0_wakeup((gpio_num_t)GPIO_NUM_4, RISING);
    }
    
    void loop() {
      ReadNTCTemp();
      setInputFlags();
      resolveInputFlags();
      resolveOutputs();
      printString();
    }
    
    void setInputFlags() {
      for(int i = 0; i < numOfInputs; i++) {
        pinMode(inputPins[i], INPUT_PULLDOWN);
        delayMicroseconds(20);
        int reading = digitalRead(inputPins[i]);
        if (reading != lastInputState[i]) {
          lastDebounceTime[i] = millis();
        }
        if ((millis() - lastDebounceTime[i]) > debounceDelay) {
          if (reading != inputState[i]) {
            inputState[i] = reading;
            if (inputState[i] == LOW) {
              inputFlags[i] = HIGH;
            }
          }
        }
        lastInputState[i] = reading;
      }
    }
    
    void resolveInputFlags() {
      for(int i = 0; i < numOfInputs; i++) {
        if(inputFlags[i] == HIGH) {
          // Input Toggle Logic
          updateLEDState(i);
          inputFlags[i] = LOW;
        }
      }
    }
    
    void printString() {
          Serial.print("Thermoblock Temperature: ");
          Serial.println(Input);
          Serial.print("PowerButton: ");
          Serial.println(PowerButtonState);
          Serial.print("Coffeebutton: ");
          Serial.println(CoffeeButtonState);
          Serial.print("WaterButton: ");
          Serial.println(WaterButtonState);
          Serial.print("SteamButton: ");
          Serial.println(SteamButtonState);
          Serial.print("Steamwheel: ");
          Serial.println(SteamWheelState);
    }
    
    void updateLEDState(int input) {
      // input 0 = State 0 and 1, PowerButton
      if(input == 0) {
        if(PowerButtonState == 0) {
          PowerButtonState = 1;
        }
        else{
          PowerButtonState = 0;
        }
        }
      // input 1 = State 0 and 1, Coffee utton
      else if(input == 1) {
        if(CoffeeButtonState == 0 && WaterButtonState == 0 && SteamButtonState == 0) {
          CoffeeButtonState = 1;
        }
        else{
          CoffeeButtonState = 0;
        }
      }
      //WaterButton
      else if(input == 2) {
        if(WaterButtonState == 0 && CoffeeButtonState == 0 && SteamButtonState == 0) {
          WaterButtonState = 1;
        }
        if(WaterButtonState == 0 && CoffeeButtonState == 1 && SteamButtonState == 0) {
          while(PumpPower<100){
            PumpPower = PumpPower + 10;
          }
        }
        else{
          WaterButtonState = 0;
        }
      }
      //SteamButton
      else if(input == 3) {
        if(SteamButtonState == 0 && CoffeeButtonState == 0 && WaterButtonState == 0) {
          SteamButtonState = 1;
        }
        if(SteamButtonState == 0 && CoffeeButtonState == 1 && WaterButtonState == 0) {
          while(PumpPower>30){
            PumpPower = PumpPower - 10;
          }
        }
        else{
          SteamButtonState = 0;
        }
      }
      //SteamWheel
      else if(input == 4) {
        if(SteamWheelState == 0 && SteamButtonState == 1 && CoffeeButtonState == 0 && WaterButtonState == 0) {
          SteamWheelState = 1;
        }
        else{
          SteamWheelState = 0;
        }
      }
    }
    
    void resolveOutputs() {
      switch (PowerButtonState) {
        case 0: //set ESP32 to deep-sleep, machine off
          PowerButtonOff();
          break;
        case 1: //ESP32 awake, machine on
          PowerButtonOn();
          break;
        default:
        break;
      }
      switch (CoffeeButtonState) {
        case 0: //end coffee shot
          CoffeeButtonOff();
          break;
        case 1: //start coffee shot
          CoffeeButtonOn();
          break;
        default:
        break;
      }
      switch (WaterButtonState) {
        case 0: //deactivate Hotwater Tap
          WaterButtonOff();
          break;
        case 1: //activate Hotwater Tap
          WaterButtonOn();
          break;
        default:
        break;
      }
      switch (SteamButtonState) {
        case 0: //deactivate steaming mode
          SteamButtonOff();
          break;
        case 1: //activate steaming mode
          SteamButtonOn();
          break;
        default:
        break;
      }
      switch (SteamWheelState) {
        case 0: //deactivate steaming mode
          SteamWheelOff();
          break;
        case 1: //activate steaming mode
          SteamWheelOn();
          break;
        default:
        break;
      }
    }
    void PowerButtonOn(){ //should be executed permanently after waking ESP32 from sleep
      pinMode(inputPins[0], OUTPUT);
      digitalWrite(inputPins[0], HIGH);
      if(SteamWheelState == 0 && SteamButtonState == 0 && CoffeeButtonState == 0 && WaterButtonState == 0){
      Setpoint = 97;
      myPID.Compute();
      Thermoblock.setBrightness(Output);
      Pump.setBrightness(0);
      }
    }
    void PowerButtonOff(){//should set ESP32 into deep-sleep
      pinMode(inputPins[0], INPUT_PULLDOWN);
      Pump.setBrightness(0);
      Thermoblock.setBrightness(0);
      digitalWrite(ThreeWayValvePin, LOW);
      digitalWrite(WaterValvePin, LOW);
      esp_deep_sleep_start(); //sleep until switch pressed
    }
    void CoffeeButtonOn(){// Heat to coffee temperature and start pump
      pinMode(inputPins[1], OUTPUT);
      digitalWrite(inputPins[1], HIGH);
      digitalWrite(ThreeWayValvePin, HIGH);
      Setpoint = 105;
      myPID.Compute();
      Thermoblock.setBrightness(Output);
      Pump.setBrightness(PumpPower);
    }
    void CoffeeButtonOff(){//Stop pump and heat to IDLE Temperature
      pinMode(inputPins[1], INPUT_PULLDOWN);
      PumpPower = 30;
      digitalWrite(ThreeWayValvePin, LOW);
    }
    void WaterButtonOn(){//Heat to coffee temperature and start pump
      pinMode(inputPins[2], OUTPUT);
      digitalWrite(inputPins[2], HIGH);
      digitalWrite(WaterValvePin, HIGH);
      Setpoint = 97;
      myPID.Compute();
      Thermoblock.setBrightness(Output);
      Pump.setBrightness(100);
    }
    void WaterButtonOff(){//Stop pump and heat to IDLE temperature
      pinMode(inputPins[2], INPUT_PULLDOWN);
      digitalWrite(WaterValvePin, LOW);
    }
    void SteamButtonOn(){ //heat to Steam temperature
      pinMode(inputPins[3], OUTPUT);
      digitalWrite(inputPins[3], HIGH);
      Setpoint = 140;
      myPID.Compute();
      Thermoblock.setBrightness(Output);
    }
    void SteamButtonOff(){//heat to IDLE temperature
      pinMode(inputPins[3], INPUT_PULLDOWN);
    }
    void SteamWheelOn(){ //Pump pulsing 1hz code on (0,5s Pump.setBrightness(95)+0,5s Pump.setBrightness(0))
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if(PumpPulseState == LOW) {
        PumpPulseState = HIGH;
        Pump.setBrightness(100);
      }
      else {
        PumpPulseState = LOW;
        Pump.setBrightness(0);
      }
    }
    
    }
    void SteamWheelOff(){// Pump pulsing code off
    }
    void ReadNTCTemp(){ //read temperature for PID
      const double NTCTemp = thermistor->readCelsius();
      Input = NTCTemp;
    }
     
    00nix und Dingelding gefällt das.
  3. #3 Yoku-San, 04.09.2021
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Ich würde mich wirklich sehr freuen, wenn mir jemand helfen kann.
     
  4. #4 Yoku-San, 06.09.2021
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Hm, dann probier ich es einfach mal aus. Wird schon schiefgehen.
     
  5. #5 faustino, 06.09.2021
    Zuletzt bearbeitet: 06.09.2021
    faustino

    faustino Mitglied

    Dabei seit:
    03.03.2010
    Beiträge:
    2.400
    Zustimmungen:
    1.923
    > Thermoblock und Pumpe werden über AC Dimmer Module von RobotDyn geregelt.

    "Die genormten Anschlussregeln für Niederspannungsnetze in Deutschland (VDE-AR-N 4100) und Österreich (TOR D1 2004) sowie die darauf aufbauenden Technischen Anschlussbedingungen der EVUs (TAB 2007 und TAEV 2016) erlauben die Phasenanschnittsteuerung für Geräte zur Warmwassererzeugung nur bis 200 Watt Leistung" (Quelle: ta.co.at)
     
    Yoku-San gefällt das.
  6. #6 Yoku-San, 06.09.2021
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Danke für die Info. Dann werde ich das lieber mit einem SSR für den Thermoblock realisieren. Kannst Du mir eines empfehlen?
     
  7. #7 Yoku-San, 14.03.2022
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Ich hab noch eine Frage, vielleicht können mir ja ein paar Leute helfen (@Pflunz , @faustino):

    Kann ich anstelle eines SSRs vielleicht doch ein AC-Dimmermodul mit Zero-crossing circuit nutzen, um den Thermoblock zwischen den Zuständen 0 und 100 Prozent hin und her zu schalten?Also kein wirkliches Dimmen sonder nur AN oder AUS?

    Dann würde doch theorethisch die Schaltung immer am Nulldurchlauf geschehen, somit auch wenig Abwärme am TRIAC entstehen und eigentlich auch keine Störungen entstehen sollen. Oder sehe ich das alles falsch?

    Das AC-Dimmer Modul wäre um einiges kompakter und günstiger als ein SSR mit Kühlkörper.

    Siehe hier:

    Dimmer module for 16/24A 600V High Load, 1 Channel, 3.3V/5V logic
     
  8. Pflunz

    Pflunz Mitglied

    Dabei seit:
    24.01.2017
    Beiträge:
    1.116
    Zustimmungen:
    1.780
    Ja, das kannst du.
    allerdings darf die PWM dann nicht zu schnell sein, da du ab ein paar hundert Watt Leistung ( genau Zahl vergessen) weder Phasenanschnitt noch nur einzelne Wellenpakete ansteuern darfst.
    Zahlen wie PWM Frequenz auf 1Hz, und Auflösung auf 50 sollte funktionieren.
    möchtest du also 20% heizen, setzt du den PWM Wert auf 0,2. Dann ist das SSR für 10 Wellenpakete an und 40 Stück aus.
     
  9. #9 Yoku-San, 14.03.2022
    Yoku-San

    Yoku-San Mitglied

    Dabei seit:
    23.08.2017
    Beiträge:
    2.777
    Zustimmungen:
    2.961
    Vielen Dank. Dann werde ich das mal ausprobieren mit einem AC Dimmer.

    Welche Dutycycle Time findest Du für einen Thermoblock denn passend? Ich dachte eigentlich an eine Sekunde mit 100ms (10) als Auflösung.
     
  10. Pflunz

    Pflunz Mitglied

    Dabei seit:
    24.01.2017
    Beiträge:
    1.116
    Zustimmungen:
    1.780
    insgesamt wäre die Auflösung dann wohl zu klein.
    Du kannst natürlich auch "intern" mit viel höherer Auflösung rechnen und akkumulieren bis du bei 20% bist.
    Beispiel Regelschleife die jede Sekunde wiederholt wird, Regler Output 0.0-1.0:
    Regler Out = 0.03 -> PWM Wert = 0 -> Rest 0.03
    Regler Out = 0.04 -> PWM Wert = 0 -> Rest 0.07
    Regler Out = 0.06 -> PWM Wert = 0 -> Rest 0.13
    Regler Out = 0.08 -> PWM Wert = 0.2 -> Rest 0.01
    Regler Out = 0.03 -> PWM Wert = 0 -> Rest 0.04

    Ich hoffe du weißt was ich meine.

    Edit: Wenn ich drüber nachdenke kannst du vermutlich auch gleich die PWM Periode auf 5 Sekunden setzen, dann hast du auch die Auflösung. Ist aber vielleicht zu langsam wenn du beispielsweise einen Feedforward beim Bezug willst.
     
    00nix gefällt das.
Thema:

Hilfe beim Code einer Bediensoftware für Espressomaschine

Die Seite wird geladen...

Hilfe beim Code einer Bediensoftware für Espressomaschine - Ähnliche Themen

  1. Hilfe ! BZ13 beim Rückspülen kurz vor Explosion !

    Hilfe ! BZ13 beim Rückspülen kurz vor Explosion !: Hallo zusammen ! Meine treue BZ13 macht mir große Sorge ... Ich wollte nur mit Pulycaff rückspülen. Dabei hat sich wohl das Expansionsventil (?)...
  2. [Suche] Hilfe beim Bauen eines Singlebaskets für Cafelat Robot

    Hilfe beim Bauen eines Singlebaskets für Cafelat Robot: Hallo, ich würde gerne einen Singlebasket für einen Cafelat Robot bauen und suche Unterstützung von jemanden der Lust an der Sache hat und Drehen,...
  3. Hilfe benötigt - Probleme mit Bezzera Duo DE beim Kaffeebezug

    Hilfe benötigt - Probleme mit Bezzera Duo DE beim Kaffeebezug: Hallo zusammen, ich habe ein Problem mit meiner Bezzera Duo DE Espressomaschine und hoffe, hier kann mir jemand helfen. Seit kurzem macht die...
  4. Hilfe beim Siebträgermaschinenkauf

    Hilfe beim Siebträgermaschinenkauf: Hallo Zusammen, mein Mann und ich sind auf der Suche nach einer neuen Siebträgermaschine für uns. Die Elternzeit steht bevor und da ist ein guter...
  5. Hilfe beim Einstellen: S* B* Pro

    Hilfe beim Einstellen: S* B* Pro: Ich suche jemanden, der mir meine S* B* Pro so einstellen kann, dass mir der Kaffee schmeckt. Ich habe schon alles ausprobiert, würde aber gerne...