Timer espressomachine

Projecten die niet passen in bovenstaande onderwerpen
Berichten: 3
Geregistreerd: 06 Jun 2014, 14:37

Timer espressomachine

Berichtdoor espresso » 07 Jun 2014, 14:22

Ik zal mij even voorstellen, ik ben Jaap en een espresso liefhebber. Om een espresso te maken gebruik ik een aparte koffiemolen en een espressomachine. Ik gebruik nu enige weken tot volle tevredenheid mijn koffiemolen met een Arduino Nano die als timer fungeert. Ik kan de dosering hierdoor regelen door het instellen van het aantal seconden dat de maler aan gaat. Wanneer ik weet dat het 6 seconden duurt om 18 gram koffiemaalsel te krijgen dan stel ik de timer in op 6 seconden en dan heb ik steeds ongeveer 18 gram koffiemaalsel om een espresso mee te maken. In het menu van de timer kan ik het aantal seconden instellen en 2 doseringen in het geheugen houden, dose 1 en dose 2. Ook door Add Grinding uit het menu te gebruiken kan ik de maler handmatig gebruiken. Bij Add Grinding druk je de start knop in en de maler gaat malen totdat je de knop weer indrukt om de maler te laten stoppen.

Door deze molentimer (zie onderstaand de code) kwam ik op het idee om de timer ook te gebruiken voor mijn espressomachine. Met de huidige code lukt dit helaas deels omdat je de machine dmv 2 schakelaars moet bedienen.

Graag wil ik ook mijn espresso machine laten schakelen dmv Arduino Nano met dezelfde componenten maar dan ipv een 1 channel relay met een 2 channel relay.
Waarom een 2 channel relay? Omdat ik deze heb en mijn espresso machine bedient moet worden dmv 2 schakelaars.
Hoe de espressomachine nu werkt:
Schakelaar 1 is een drukschakelaar (achter een hendeltje) en is standaard ingedrukt, dmv de hendel over te halen gaat de drukschakelaar los/uit. Deze drukschakelaar bedient een solenoid valve, wanneer de schakelaar dus uit/los is gaat er water stromen door de espresso machine (waterleidingdruk), wanneer de schakelaar ingeschakelt is stopt de waterleiding toevoer. Het koffiemaalsel wordt door het water welke op leidingdruk is nat gemaakt wat men een pre-infuse noemt. Na een aantal seconden (doorgaans tussen de 5 en 15 seconden) schakel ik met schakelaar 2 de pomp in. Schakelaar 2 is een normale aan/uit schakelaar. Met schakelaar 2 bedien ik de pomp van de espressomachine. Ipv van waterleidingdruk gaat de machine nu op pompdruk water door het koffiemaalsel persen wat een espresso geeft. Na +/- 25 seconden schakel ik dan schakelaar 2 uit (de pomp uit) en laat dan nog een aantal seconden (tussen de 2 en 10 seconden) de espresso alleen op waterdruk doorlopen en schakel dan ook schakelaar 1 waardoor er geen waterleidingdruk is en er geen water meer door de machine loopt.

Mijn doel is om met aanpassingen aan de bestaande code (en het 1 channel relay te vervangen voor een 2 channel relay) deze schakelingen door de Arduino Nano te laten doen.
Mijn gedachte is om schakelaar 1 te schakelen voor een duur van bv 35 seconden (instelbaar in het menu van zeg 0 tot 50 seconden). Waarna schakelaar 2 daarna aangaat na bijvoorbeeld 5 seconden nadat schakelaar 1 is aangegaan (delay instelbaar in menu van 0 tot bv 10 seconden) voor een duur van bijvoorbeeld een 25 seconden (instelbaar via menu).
In dit voorbeeld krijg je dan:
eerst een pre-infusie (alleen waterleidingdruk) van 5 seconden
daarna pompdruk voor een duur van 25 seconden
en als laatste weer een 5 seconden alleen leidingdruk

Dus instelbaar in menu:
1. aantal seconden schakelaar 1
2. delay voordat schakelaar 2 aangaat nadat schakelaar 1 is aangegaan
(het aantal seconden dat schakelaar 2 aangaat nadat schakelaar 1 is aangegaan)
3. aantal seconden schakelaar 2

Helaas is mijn kennis van de Arduino code heel erg beperkt.
Ik hoor graag of dit te realiseren is. Wie kan/wil mij (tegen een vergoeding) op weg helpen?
Alvast bedankt voor de moeite.

M.vr.gr.
Jaap

Code: Alles selecteren
/*

This is a minimalistic rewrite of the original Mühlentimer V3.1.0 of Michael Hinderer.
It has less features but uses far less code. Enjoy, experiment, go!
By Matthias Mueller (user mamu of http://www.kaffee-netz.de )

*/

#include <EEPROM.h>
#include <Wire.h> // http://arduino.cc/de/Reference/Wire
#include <LiquidCrystal_I2C.h> // http://hmario.home.xs4all.nl/arduino/LiquidCrystal_I2C/
#include <MsTimer2.h> // http://playground.arduino.cc/Main/MsTimer2
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce-Arduino-Wiring/wiki

// *** UI ***
//
// START
// Je nach Menu-Position wird Timerwert für Dose 1 oder 2 ausgeführt. Ein erneutes Drücken von START stoppt den Timer und lässt Restzeit in der Anzeige. Es kann erneut weiter gemahlen werden.
// Steht Menu auf Add Grinding, läuft der Motor nur so lange, wie der START-Taster gedrückt bleibt.
// SELECT
// Reaktion nur, wenn Motor nicht an ist.
// Drücken führt bei Dose 1 oder 2 zum Änderungsmodus. Erneutes Drücken speichert neuen Wert.
// Drücken bei Add Grinding hat keine Wirkung.
// ROTATE/Encoder
// Reaktion nur, wenn Motor nicht an ist.
// Menu-Wahl zwischen Dose 1, 2 oder Add Grinding.
// Neue Menu-Auswahl wird immer gespeichert.
// Im Änderungsmodus wird die Zeit um 1/102 hoch bzw. herunter gezählt.
// RESET
// Zeiten auf einen Standardwert zuruecksetzen, wenn Start und Select gleichzeitig gedrückt werden und das Menu auf Add Grinding steht
//
// *** Übergänge ***
// Dose 1/2     -> START -> Motor läuft bis Ende oder START erneut gedrückt -> Stop
// Add Grinding -> START -> Motor läuft bis START losgelassen wird -> Stop
// Motor läuft  -> SELECT -> keine Auswirkung
// Add Grinding -> SELECT -> keine Auswirkung
// Dose 1/2     -> SELECT -> Zeiteinstellung Dose 1/2 -> SELECT -> speichert neuen Wert
// Dose 1/2/Add Grinding -> ROTATE -> Ändert Menu-Wert und speichert neuen Wert
// Add Grinding -> SELECT + START gleichzeitig -> Reset


// *** BEGIN OF CONFIG SECTION ***

#define MACHINE_NAME      F("Super Jolly")

// I2C LCD connection, SDA at A4 and SCL at A5 using UNO / NANO and SDA at SDA and SCL at SCL using LEONARDO / MICRO
// I2C address of LCD, e.g. 0x27 (in most cases this is the default address)
#define I2C_ADDR          0x27
// select the pins used on the LCD panel
#define BACKLIGHT_PIN     3
#define EN_PIN            2
#define RW_PIN            1
#define RS_PIN            0
#define D4_PIN            4
#define D5_PIN            5
#define D6_PIN            6
#define D7_PIN            7

const byte RELAY_PIN = 12;  // relay pin for controlling motor (D12)
const boolean ON = HIGH;    // pin state for acting relay as ON
const boolean OFF = LOW;    // pin state for acting relay as OFF

const byte START_BTN_PIN = 5; // pin to use as START button (D5)
const byte SELECT_BTN_PIN = 4; // pin to use as SELECT button (D4). Might be button of enoder switch

// rotary encoder must use pin D2 and D3 using UNO / NANO or pin D8 and D9 using LEONARDO / MICRO
const byte ENCODER_A_PIN = 3;
const byte ENCODER_B_PIN = 2;


// *** END OF CONFIG SECTION ***


#define EEPROM_VALUE_VERSION   3

#define ADD_GRINDING           0
#define DOSE1                  1
#define DOSE2                  2


LiquidCrystal_I2C lcd(I2C_ADDR, EN_PIN, RW_PIN, RS_PIN, D4_PIN, D5_PIN, D6_PIN, D7_PIN);

Bounce debouncerSTARTBtn = Bounce();
Bounce debouncerSELECTBtn = Bounce();

volatile int encoderPos = 0;
int lastEncoderPos = 0;

volatile byte menu = DOSE1;
volatile bool relayOn = false;
volatile byte currentTime = 0;
bool inSetupMode = false;

byte doseTime[] = {0, 55, 93}; // time in 1/10s that is value 55 for 5.5s (this is done to prevent the memory consuming and slow usage of float/double)
byte newDoseTime;


void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, OFF);
 
  pinMode(START_BTN_PIN, INPUT);
  digitalWrite(START_BTN_PIN, HIGH);
  debouncerSTARTBtn.attach(START_BTN_PIN);
  debouncerSTARTBtn.interval(5);
 
  pinMode(SELECT_BTN_PIN, INPUT);
  digitalWrite(SELECT_BTN_PIN, HIGH);
  debouncerSELECTBtn.attach(SELECT_BTN_PIN);
  debouncerSELECTBtn.interval(5);
 
  pinMode(ENCODER_A_PIN, INPUT);
  pinMode(ENCODER_B_PIN, INPUT);
  digitalWrite(ENCODER_A_PIN, HIGH);
  digitalWrite(ENCODER_B_PIN, HIGH);
  attachInterrupt(0, doEncoderA, FALLING);
  attachInterrupt(1, doEncoderB, FALLING);
 
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.begin(16, 2);
  lcd.setCursor(2, 0);
  lcd.print(MACHINE_NAME);
  lcd.setCursor(6, 1);
  lcd.print(F("v."));
  lcd.print(EEPROM_VALUE_VERSION);
 
  readSettings();

  // setup timer
  MsTimer2::set(100, updateRelayState);  // period to check relay state: every 100ms
  MsTimer2::start();
 
  delay(2000);
 
  updateLCDMenu(doseTime[menu]);
}


void loop() {
  delay(10);
 
  bool hasNewValueSELECTBtn = debouncerSELECTBtn.update();
  bool hasNewValueSTARTBtn = debouncerSTARTBtn.update();
 
  if (hasNewValueSTARTBtn && !inSetupMode) {
    checkOperationMode(debouncerSTARTBtn.read() == LOW);
  }
 
  if (relayOn) {
    // prevents entering setup while relay is on
    updateTime(currentTime);
  }
  else if (lastEncoderPos != encoderPos) {
    encoderChanged(encoderPos > lastEncoderPos);
    lastEncoderPos = encoderPos;
  }
  else if (hasNewValueSELECTBtn && debouncerSELECTBtn.read() == LOW && menu != ADD_GRINDING) {
    handleSetupMode();
  }
  else if (!inSetupMode && currentTime == 0) {
    currentTime = doseTime[menu];
    updateTime(currentTime);
  }
}


void encoderChanged(bool addValue) {
  if (inSetupMode) {
    newDoseTime += addValue ? 1 : -1;
    updateTime(newDoseTime);
  }
  else {
    updateMenu(addValue);
  }
}

void handleSetupMode() {
  // enter setup mode
  inSetupMode = !inSetupMode;
  if (inSetupMode) {
    // get old values
    newDoseTime = doseTime[menu];
  }
  else {
    // get new values
    doseTime[menu] = newDoseTime;
    EEPROM.write(menu, newDoseTime);
  }
 
  updateLCDMenu(newDoseTime);
}

void checkOperationMode(bool pressedSTARTBtn) { 
  if (menu == ADD_GRINDING) {
    // Reset ?
    bool pressedSELECTBtn = debouncerSELECTBtn.read() == LOW;
    if (pressedSTARTBtn && pressedSELECTBtn) {
      lcd.setCursor(10, 1);
      lcd.print(F("RESET"));
      EEPROM.write(0, 0);
      readSettings();
      delay(1000);
      updateLCDMenu(doseTime[menu]);
      lastEncoderPos = encoderPos;
      return;
    }
   
    relayOn = pressedSTARTBtn; // button still down?
  }
  else if (pressedSTARTBtn) {
    relayOn = !relayOn; // toggle relay state depending on prev state: off -> on or on -> off
  }
}

void updateTime(int time) { 
  lcd.setCursor(10, 1);
  lcd.print(time / 10);
  lcd.print(F("."));
  lcd.print(time % 10);
  lcd.print(F("   "));
}

void updateMenu(bool encoderAdd) {
  if (encoderAdd) {
    if (menu < DOSE2) {
      menu++;
    }
    else {
      menu = ADD_GRINDING;
    }
  }
  else {
    if (menu > ADD_GRINDING) {
      menu--;
    }
    else {
      menu = DOSE2;
    }
  }
  EEPROM.write(3, menu);
 
  currentTime = doseTime[menu];
 
  updateLCDMenu(currentTime);
}

void updateLCDMenu(int time) {
  lcd.clear(); 
  lcd.setCursor(2, 0);
 
  if (menu == ADD_GRINDING) {
    lcd.print(F("ADD GRINDING"));
  }
  else {
    lcd.print(F("DOSE"));
    lcd.setCursor(10, 0);
    lcd.print(F("TIME"));   
   
    if (inSetupMode) {
      lcd.setCursor(2, 1);   
      lcd.print(F("--->"));
    }
    else {
      lcd.setCursor(3, 1);
      lcd.print(menu == DOSE1 ? F("1") : F("2"));
    }

    updateTime(time);
  }
}


void updateRelayState() {
  if (relayOn) {
    if (menu == ADD_GRINDING) {
      currentTime++;
    }
    else {
      currentTime--;
      relayOn = currentTime > 0;
    }
  }
 
  digitalWrite(RELAY_PIN, relayOn ? ON : OFF);
}

void doEncoderA() {
  if (relayOn) {
    return;
  } 
  if (digitalRead(ENCODER_A_PIN) == LOW) {
    encoderPos++;
  }
}

void doEncoderB() {
  if (relayOn) {
    return;
  } 
  if (digitalRead(ENCODER_B_PIN) == LOW) {
    encoderPos--;
  }
}

void readSettings() {
  // version check
  bool readFromEEPROM = EEPROM.read(0) == EEPROM_VALUE_VERSION;
  if (readFromEEPROM) {   
    // dose time values
    doseTime[DOSE1] = EEPROM.read(DOSE1);
    doseTime[DOSE2] = EEPROM.read(DOSE2);
   
    // menu
    menu = EEPROM.read(3);
  }
  else {
    // first time init   
    doseTime[DOSE1] = 55;
    EEPROM.write(DOSE1, doseTime[DOSE1]);
    doseTime[DOSE2] = 93;
    EEPROM.write(DOSE2, doseTime[DOSE2]);
   
    menu = DOSE1;
    EEPROM.write(3, menu);
   
    EEPROM.write(0, EEPROM_VALUE_VERSION);
  }
}

Advertisement

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Timer espressomachine

Berichtdoor shooter » 07 Jun 2014, 20:17

ik denk dat je heel goed op weg bent, zag zelfs eeprom writes etc.

enkele opmerkingen, ik denk dat schakelaar 1 een normaal gesloten contact is, en dus is het contact met ingedrukte schakelaar open en niet gesloten komt veel voor bij microschakelaars, als er nog een contactje opzit weet je het zeker.
dan heb je dus eigenlijk gewoon twee kleine relais nodig om de functies te bedienen.

Ik vind de grinder erg moeilijk van opzet , maar ach
je kunt dezelfde nano gebruiken voor je espresso, als ze maar naast elkaar staan.
bouw de beide relais in de espresso machine dan loopt er geen 230 over het geheel, maar slechts 5 volt. (of in een kastje eronder.

als je inderdaad een encoder gebruikt een menu keuze toevoegen.
persoonlijk zou ik de startknop (als deze < 1 sec ingedrukt wordt dan gewoon standaard 6 seconden malen, als langer dan 1 sec dan tot knop losgelaten wordt en natuurlijk seconden op scherm.
voor de espresso machine gewoon een startknop met start cyclus en weer nog te gaan aantal seconden op scherm.
paul deelen
shooter@home.nl

Berichten: 3
Geregistreerd: 06 Jun 2014, 14:37

Re: Timer espressomachine

Berichtdoor espresso » 08 Jun 2014, 12:27

Paul, hartelijk dank voor je reactie.

Ik ben bang dat ik niet helemaal duidelijk ben geweest.

Wat ik nu heb is een molentimer die ik gebruik voor de koffiemolen. De Arduino zit ingebouwd in de koffiemolen en deze werkt prima en daar gebruik ik de bestaande code voor die ik in mijn vorige bericht heb toegevoegd. Die code is dus voor de koffiemolen. Dat project is voor mij afgerond.

De Arduino voor de espresso machine moet gezien worden als een nieuw project en daarvoor ga ik een andere Arduino Nano inbouwen in de espressomachine (dus los van de koffiemolen).

Wat betreft schakelaar 1 (solenoid valve) weet ik niet of het een normaal gesloten contact is, dat is een heel goed punt en ga ik dinsdag nakijken. Mijn gedachte was, stroom op de solenoid valve zorgt er voor dat de klep gesloten is en daardoor geen water, stroom er af, klep open en water maar dat hoeft dus niet zo te zijn. Ik ga het nakijken en laat het dinsdag hier weten.

Wat ik nu wens is een timer voor de espressomachine. Daarvoor heb ik een aparte Arduino Nano, 2 channel relay, lcd enz..

Helaas ontbreekt de code en heb ik daar weinig verstand van. Wat ik dacht/denk is dat de code voor de molentimer met aanpassingen zou kunnen werken voor mijn espressomachine. Mijn wens is dus een aangepaste code die mijn espressomachine kan bedienen met:
Instelbaar in menu:
1. aantal seconden dat schakelaar 1 aanblijft.
2. aantal seconden delay voordat schakelaar 2 aangaat nadat schakelaar 1 is aangegaan
3. aantal seconden dat schakelaar 2 aanblijft.

Wie kan/wil mij (tegen een vergoeding) op weg helpen?

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Timer espressomachine

Berichtdoor shooter » 08 Jun 2014, 21:57

als je dezelfde opzet wilt gebruiken dus met encoder en display, dan is dat zeker mogelijk, je kunt dan de code domweg in de espresso laden met wat wijzigingen uiteraard in de loop

Code: Alles selecteren
/*

This is a minimalistic rewrite of the original Mühlentimer V3.1.0 of Michael Hinderer.
It has less features but uses far less code. Enjoy, experiment, go!
By Matthias Mueller (user mamu of http://www.kaffee-netz.de )

*/

#include <EEPROM.h>
#include <Wire.h> // http://arduino.cc/de/Reference/Wire
#include <LiquidCrystal_I2C.h> // http://hmario.home.xs4all.nl/arduino/LiquidCrystal_I2C/
#include <MsTimer2.h> // http://playground.arduino.cc/Main/MsTimer2
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce-Arduino-Wiring/wiki

// *** UI ***
//
// START
// Je nach Menu-Position wird Timerwert für Dose 1 oder 2 ausgeführt. Ein erneutes Drücken von START stoppt den Timer und lässt Restzeit in der Anzeige. Es kann erneut weiter gemahlen werden.
// Steht Menu auf Add Grinding, läuft der Motor nur so lange, wie der START-Taster gedrückt bleibt.
// SELECT
// Reaktion nur, wenn Motor nicht an ist.
// Drücken führt bei Dose 1 oder 2 zum Änderungsmodus. Erneutes Drücken speichert neuen Wert.
// Drücken bei Add Grinding hat keine Wirkung.
// ROTATE/Encoder
// Reaktion nur, wenn Motor nicht an ist.
// Menu-Wahl zwischen Dose 1, 2 oder Add Grinding.
// Neue Menu-Auswahl wird immer gespeichert.
// Im Änderungsmodus wird die Zeit um 1/102 hoch bzw. herunter gezählt.
// RESET
// Zeiten auf einen Standardwert zuruecksetzen, wenn Start und Select gleichzeitig gedrückt werden und das Menu auf Add Grinding steht
//
// *** Übergänge ***
// Dose 1/2     -> START -> Motor läuft bis Ende oder START erneut gedrückt -> Stop
// Add Grinding -> START -> Motor läuft bis START losgelassen wird -> Stop
// Motor läuft  -> SELECT -> keine Auswirkung
// Add Grinding -> SELECT -> keine Auswirkung
// Dose 1/2     -> SELECT -> Zeiteinstellung Dose 1/2 -> SELECT -> speichert neuen Wert
// Dose 1/2/Add Grinding -> ROTATE -> Ändert Menu-Wert und speichert neuen Wert
// Add Grinding -> SELECT + START gleichzeitig -> Reset


// *** BEGIN OF CONFIG SECTION ***

#define MACHINE_NAME      F("Super Jolly")

// I2C LCD connection, SDA at A4 and SCL at A5 using UNO / NANO and SDA at SDA and SCL at SCL using LEONARDO / MICRO
// I2C address of LCD, e.g. 0x27 (in most cases this is the default address)
#define I2C_ADDR          0x27
// select the pins used on the LCD panel
#define BACKLIGHT_PIN     3
#define EN_PIN            2
#define RW_PIN            1
#define RS_PIN            0
#define D4_PIN            4
#define D5_PIN            5
#define D6_PIN            6
#define D7_PIN            7

const byte klepPIN = 12;  // relay pin for controlling solenoid klep (D12)
const byte pompPIN = 13;  // relay pin for controlling pompmotor (D13) bijvoorbeeld
const
const boolean ON = HIGH;    // pin state for acting relay as ON
const boolean OFF = LOW;    // pin state for acting relay as OFF

const byte START_BTN_PIN = 5; // pin to use as START button (D5)
const byte SELECT_BTN_PIN = 4; // pin to use as SELECT button (D4). Might be button of enoder switch

// rotary encoder must use pin D2 and D3 using UNO / NANO or pin D8 and D9 using LEONARDO / MICRO
const byte ENCODER_A_PIN = 3;
const byte ENCODER_B_PIN = 2;


// *** END OF CONFIG SECTION ***


#define EEPROM_VALUE_VERSION   3

#define ADD_GRINDING           0
#define DOSE1                  1
#define DOSE2                  2


LiquidCrystal_I2C lcd(I2C_ADDR, EN_PIN, RW_PIN, RS_PIN, D4_PIN, D5_PIN, D6_PIN, D7_PIN);

Bounce debouncerSTARTBtn = Bounce();
Bounce debouncerSELECTBtn = Bounce();

volatile int encoderPos = 0;
int lastEncoderPos = 0;

volatile byte menu = DOSE1;
volatile bool relayOn = false;
volatile byte currentTime = 0;
bool inSetupMode = false;

byte doseTime[] = {0, 55, 93}; // time in 1/10s that is value 55 for 5.5s (this is done to prevent the memory consuming and slow usage of float/double)
byte newDoseTime;


void setup() {
  pinMode(klepPIN, OUTPUT);
  digitalWrite(klepPIN, OFF);
 
  pinMode(pompPIN, OUTPUT);
  digitalWrite(pompPIN, OFF);

  pinMode(START_BTN_PIN, INPUT);
  digitalWrite(START_BTN_PIN, HIGH);
  debouncerSTARTBtn.attach(START_BTN_PIN);
  debouncerSTARTBtn.interval(5);
 
  pinMode(SELECT_BTN_PIN, INPUT);
  digitalWrite(SELECT_BTN_PIN, HIGH);
  debouncerSELECTBtn.attach(SELECT_BTN_PIN);
  debouncerSELECTBtn.interval(5);
 
  pinMode(ENCODER_A_PIN, INPUT);
  pinMode(ENCODER_B_PIN, INPUT);
  digitalWrite(ENCODER_A_PIN, HIGH);
  digitalWrite(ENCODER_B_PIN, HIGH);
  attachInterrupt(0, doEncoderA, FALLING);
  attachInterrupt(1, doEncoderB, FALLING);
 
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.begin(16, 2);
  lcd.setCursor(2, 0);
  lcd.print(MACHINE_NAME);
  lcd.setCursor(6, 1);
  lcd.print(F("v."));
  lcd.print(EEPROM_VALUE_VERSION);
 
  readSettings();

  // setup timer
  MsTimer2::set(100, updateRelayState);  // period to check relay state: every 100ms
  MsTimer2::start();
 
  delay(2000);
 
  updateLCDMenu(doseTime[menu]);
}


void loop() {
  delay(10);
 
  bool hasNewValueSELECTBtn = debouncerSELECTBtn.update();
  bool hasNewValueSTARTBtn = debouncerSTARTBtn.update();
 
  if (hasNewValueSTARTBtn && !inSetupMode) {
    checkOperationMode(debouncerSTARTBtn.read() == LOW);
  }
 
  if (relayOn) {
    // prevents entering setup while relay is on
    updateTime(currentTime);
  }
  else if (lastEncoderPos != encoderPos) {
    encoderChanged(encoderPos > lastEncoderPos);
    lastEncoderPos = encoderPos;
  }
  else if (hasNewValueSELECTBtn && debouncerSELECTBtn.read() == LOW && menu != ADD_GRINDING) {
    handleSetupMode();
  }
  else if (!inSetupMode && currentTime == 0) {
    currentTime = doseTime[menu];
    updateTime(currentTime);
  }
}


void encoderChanged(bool addValue) {
  if (inSetupMode) {
    newDoseTime += addValue ? 1 : -1;
    updateTime(newDoseTime);
  }
  else {
    updateMenu(addValue);
  }
}

void handleSetupMode() {
  // enter setup mode
  inSetupMode = !inSetupMode;
  if (inSetupMode) {
    // get old values
    newDoseTime = doseTime[menu];
  }
  else {
    // get new values
    doseTime[menu] = newDoseTime;
    EEPROM.write(menu, newDoseTime);
  }
 
  updateLCDMenu(newDoseTime);
}

void checkOperationMode(bool pressedSTARTBtn) {
  if (menu == ADD_GRINDING) {
    // Reset ?
    bool pressedSELECTBtn = debouncerSELECTBtn.read() == LOW;
    if (pressedSTARTBtn && pressedSELECTBtn) {
      lcd.setCursor(10, 1);
      lcd.print(F("RESET"));
      EEPROM.write(0, 0);
      readSettings();
      delay(1000);  // pd dit zal problemen geven
      updateLCDMenu(doseTime[menu]);
      lastEncoderPos = encoderPos;
      return;
    }
   
    relayOn = pressedSTARTBtn; // button still down?
  }
  else if (pressedSTARTBtn) {
    relayOn = !relayOn; // toggle relay state depending on prev state: off -> on or on -> off
  }
}

void updateTime(int time) {
  lcd.setCursor(10, 1);
  lcd.print(time / 10);
  lcd.print(F("."));
  lcd.print(time % 10);
  lcd.print(F("   "));
}

void updateMenu(bool encoderAdd) {
  if (encoderAdd) {
    if (menu < DOSE2) {
      menu++;
    }
    else {
      menu = ADD_GRINDING;
    }
  }
  else {
    if (menu > ADD_GRINDING) {
      menu--;
    }
    else {
      menu = DOSE2;
    }
  }
  EEPROM.write(3, menu);
 
  currentTime = doseTime[menu];
 
  updateLCDMenu(currentTime);
}

void updateLCDMenu(int time) {
  lcd.clear();
  lcd.setCursor(2, 0);
 
  if (menu == ADD_GRINDING) {
    lcd.print(F("ADD GRINDING"));
  }
  else {
    lcd.print(F("DOSE"));
    lcd.setCursor(10, 0);
    lcd.print(F("TIME"));   
   
    if (inSetupMode) {
      lcd.setCursor(2, 1);   
      lcd.print(F("--->"));
    }
    else {
      lcd.setCursor(3, 1);
      lcd.print(menu == DOSE1 ? F("1") : F("2"));
    }

    updateTime(time);
  }
}


void updateRelayState() {
  if (relayOn) {
    if (menu == ADD_GRINDING) {
      currentTime++;
    }
    else {
      currentTime--;
      relayOn = currentTime > 0;
    }
  }
 
  digitalWrite(klepPIN, relayOn ? ON : OFF);  //pd hier moet dus een uitbreiding voor de pomptijd
}

void doEncoderA() {
  if (relayOn) {
    return;
  }
  if (digitalRead(ENCODER_A_PIN) == LOW) {
    encoderPos++;
  }
}

void doEncoderB() {
  if (relayOn) {
    return;
  }
  if (digitalRead(ENCODER_B_PIN) == LOW) {
    encoderPos--;
  }
}

void readSettings() {
  // version check
  bool readFromEEPROM = EEPROM.read(0) == EEPROM_VALUE_VERSION;
  if (readFromEEPROM) {   
    // dose time values
    doseTime[DOSE1] = EEPROM.read(DOSE1);
    doseTime[DOSE2] = EEPROM.read(DOSE2);
   
    // menu
    menu = EEPROM.read(3);
  }
  else {
    // first time init   
    doseTime[DOSE1] = 55;
    EEPROM.write(DOSE1, doseTime[DOSE1]);
    doseTime[DOSE2] = 93;
    EEPROM.write(DOSE2, doseTime[DOSE2]);
   
    menu = DOSE1;
    EEPROM.write(3, menu);
   
    EEPROM.write(0, EEPROM_VALUE_VERSION);
  }
}


bovenstaand zoe dus alleen de klep bedienen, maar zou dus prima moeten werken.
er is dus nog wel een extra relais nodig en stukje software om de pomp te bedienen,
paul deelen
shooter@home.nl

Berichten: 3
Geregistreerd: 06 Jun 2014, 14:37

Re: Timer espressomachine

Berichtdoor espresso » 10 Jun 2014, 17:17

Paul nogmaals dank!

De schakelaar 1 voor de watertoevoer is inderdaad een normaal gesloten contact. Zoals je al dacht, het contact is met ingedrukte schakelaar open en niet gesloten.

Ik heb de machine al even laten draaien en met het 2 channel relay kan ik nu de watertoevoer en pomp tegelijkertijd laten schakelen. Arduino schakelt beiden tegelijkertijd aan/uit.

Wat ik nu voor elkaar moet zien te krijgen is dat schakelaar 1 en 2 onafhankelijk van elkaar voor een aantal (instelbaar) schakelen. Schakelaar 2 moet tevens een (instelbaar) aantal seconden later starten dan schakelaar 1.

Iemand tips?

Terug naar Overige projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 38 gasten