Ir para conteúdo

Fazendo um controlador arduino para máquina de café espresso


Postagens recomendadas

Vou começar a projetar um controlador arduino para máquina de café espresso.

O que vocês gostariam de ver nele?

 

Penso em usar o seguinte case:

 

15209165582_eb9e8c58c7_b.jpg

 

 

Até o momento, minha idéia é que ele possua as seguintes funções:

 

A) Medição de temperatura (na gaggia, externamente à caldeira) (tem um buraco para instalar o termostato, que serve para instalar também o sensor termopar (acho que vou usar tipo k, por ser mais barato), mas estou aberto a sugestões;

 

B) Extração cronometrada (você define o número de segundos e o controlador, controla rss);

 

C) Pré-infusão (não sei se vou conseguir essa; penso em usar potência mais baixa (leia-se, menor voltagem ou pulsos de voltagem mais longos) na bomba para diminuir a pressão, mas não tenho idéia se isso vai influenciar na hora de distribuir a água pelo chuveirinho);

 

D) Definição da temperatura a ser mantida (setpoint);

 

Como a gaggia coffee, que vai ser a cobaia desse projeto, não tem válvula solenoide, não vou mexer com isso  nesse primeiro momento (seria muito complicado colocá-la nessa equação. Para usá-la teria que fazer um bypass por todo o sistema elétrico da cafeteira (na prática, retirar a placa controladora que vem nela da equação e controlar totalmente via arduino).

 

 

  • Curtir 3
Link para o comentário
Compartilhar em outros sites

eu tava começando a fazer um adaptador pra colocar um sensor dentro da caldeira da twin pela tomada de vapor e deixaria ainda a saida de vapor junto, a sua é  igual a twin se me der coragem posso tentar fazer dois se bem que o torno ainda nao foi ligado nas idas e vindas da mudança.

 essa caixa onde tem, sera que tem pra versao lcd com botoes?

eu comprei as coisas do arduino pensando nisso mesmo, vendo voce se animar to ate pensando em desempoeirar aqueles componentes... é que da uma preguiça aprender a programar o arduino...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Lisca, eu posso programar e deixar o sketch e quais componentes comprar aqui para quem se animar a replicar.

Quanto à caixa. Não encontrei nenhuma que suporte esse shield que vem com botões. A melhor que encontrei até agora foi essa. Tem também a seguinte:

 

271-03.jpg

 

 

271-02.jpg

 

 

Mas ela é bem mais compacta e, a primeira vista, não tem espaço adequado para colocar botões.

 

Estou pensando em usar um LCD comum mesmo (sem os botões). Uma boa saída seria usar com uma plaquina I2C ou diretamente um LCD I2C (mais ou menos 14 dólares no ebay).

 

Os botões podem ser comprados em qualquer eletrônica, mesmo no plano piloto, em Brasília, onde só tem uma +ou- relativamente boa (Contato).

 

 

Se for usar mesmo um LCD I2C, qualquer pin digital sobrando pode ser usado como input para verificar se o botão x ou y foi ou não pressionado e alterar o valor ou fazer o que o programinha mandar.

 

Penso em dar um delay de 1 segundo no loop do programa. Assim, embora fique um pouquinho mais lento na definição manual dos parâmetros (nos botões), fica mais fácil inserir um contador de tempo. Estou pensando em fazer o mais simples possível.

 

Aquela caixa é boa porque, no que se relaciona aos botões, posso adicioná-los com pequenos furos (broca nº 3 ou 4). Penso em afixá-los no case com cola quente, que é o comumente usado em se tratando de equipamentos feitos em casa, por ser o método mais fácil e relativamente resistente.

Link para o comentário
Compartilhar em outros sites

Aquela caixa do primeiro post eu comprei no ebay. A segunda tem na adafruit (se prepare que o frete e a carrier ou courier são de matar). Pesquise por lcd arduino enclosure.

Link para o comentário
Compartilhar em outros sites

Guilherme, as imagens estao com pau.

eu ja tenho um lcd com botoes que tinha comprado quando ia fazer algo na LP dai pensei em fazer na gaggia e ficou guardado

tenho os arduinos uns sensores lcd, so falta coragem...

Link para o comentário
Compartilhar em outros sites

Guilherme, estou usando LM35 na Mini e na máquina em desenvolvimento. É uma baba interfacear bastando ligar direto no AD do uC. Só é um pouco chata a fixação pois os mais baratos tem encapsulamento TO92.

Link para o comentário
Compartilhar em outros sites

Na PI vc pode ler no uC o zero crossing da rede e ligar o rele somente durante alguns ciclos. Ou seja, faz PWM granulado e sincronizado nos ciclos.

 

Em pressão menor poderia ser 5 ciclos ligados e 3 ciclos desligados. Ou qualquer proporção que fique adequada.

 

Outro método é usar um resistor em série com a bomba. Basta descobrir o valor da resistência que deixe com pressão adequada para a PI. Daí só usar um relé mecânico (ou outro componente) para fazer o bypass desse resistor para a extração.

Link para o comentário
Compartilhar em outros sites

Acho que o bypass é muito mais fácil de implementar. Boa idéia. Vou tentar ambas as abordagens e ver qual vai resultar melhor na prática.

O sensor LM é muito mais barato e suporta essa faixa de temperatura de máquinas de espresso. Valeu tb.

Acho que tenho uns 3 em casa.

 

O mais chato é bolar os menus, integrá-los com os botões. Estou achando que vou usar uma das diversas bibliotecas existentes especificamente para isso.

 

Penso em primeiro definir essa parte do sketch e depois o controle propriamente dito.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Existem vários controladores já prontos na internet para uso em máquinas de espresso.

O mais legal, na minha opinião, é o crema.

No entanto, como é muito difícil importar todos os componentes necessários (listados no site), penso em começar do zero.

Bem, não é, na realidade, do zero.

 

Alguma coisa a gente tem que aproveitar, por exemplo, esqueletos de outros sketchs que tem na WEB para usar como ponto de partida.

 

Resolvi começar do menu, para depois ir introduzindo as demais funções.

 

Esse é um esboço de um sketch de como o menu do controlador seria (usei um LCD I2C para poupar cabos):

 

 

 

/*
   BASE DO MENU
*/
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <wire.h> // wire que precisa ser utilizado junto ao liquidCrystal I2C

#include <LiquidCrystal_I2C.h>

const int buttonPinLeft = 8;      // pin for the Up button
const int buttonPinRight = 9;    // pin for the Down button
const int buttonPinEsc = 10;     // pin for the Esc button
const int buttonPinEnter = 11;   // pin for the Enter button

int lastButtonPushed = 0;

int lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int lastButtonRightState = LOW;   // the previous reading from the Right input pin


long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
long lastEscDebounceTime = 0;  // the last time the output pin was toggled
long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
long lastRightDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 500;    // the debounce time
 

// definção do endereço do adaptador I2C (o meu é esse endereço 0x27)
LiquidCrystal_I2C lcd(0x27,16,2);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
   MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
   MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem2SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");
      MenuItem menuItem3SubItem1 = MenuItem("Item3SubItem3");
      MenuItem menuItem3SubItem2 = MenuItem("Item3SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item3SubItem3");
  MenuItem menu1Item4 = MenuItem("Item4");


void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
 
  lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3).addRight(menu1Item4);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem2SubItem3);
  menu1Item3.add(menuItem3SubItem1).addRight(menuItem3SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  lcd.setCursor(0,0);  
 

}  // setup()...


void loop()
{

  readButtons();  //I splitted button reading and navigation in two procedures because
  navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)
                  
} //loop()...


void menuChanged(MenuChangeEvent changed){
 
  MenuItem newMenuItem=changed.to; //get the destination menu
 
  lcd.setCursor(0,1); //set the start position for lcd printing to the second row
 
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("MENU");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("PREPARAR");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("CURTO");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("LONGO");
  }else if(newMenuItem.getName()=="Item2"){
      lcd.print("CONFIGURAR");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      lcd.print("TEMPO CURTO");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
      lcd.print("TEMPO LONGO");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      lcd.print("TEMPO PREINFUSAO   ");
  }else if(newMenuItem.getName()=="Item3"){
      lcd.print("DEFINIR PID");
  }else if(newMenuItem.getName()=="Item3SubItem1"){
      lcd.print("DEFINIR P");
}else if(newMenuItem.getName()=="Item3SubItem2"){
      lcd.print("DEFINIR I");  
}else if(newMenuItem.getName()=="Item3SubItem3"){
      lcd.print("DEFINIR D");
}else if(newMenuItem.getName()=="Item4"){
      lcd.print("DEFINIR TEMPERATURA");
}
}

// APENAS PARA VER O QUE FOI PRESSIONADO E QUAL O MENU USADO
void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0);  
  lcd.print("FOI USADO       ");
  lcd.setCursor(0,1);
  lcd.print(used.item.getName());
  delay(3000);  //delay to allow message reading
    menu.toRoot();  //back to Main
}


void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter input pin
  int buttonEscState=LOW;             // the current reading from the input pin
  int buttonLeftState=LOW;             // the current reading from the input pin
  int buttonRightState=LOW;             // the current reading from the input pin

  //Enter button
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEnter);

                  // check to see if you just pressed the enter button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEnterState) {
                    // reset the debouncing timer
                    lastEnterDebounceTime = millis();
                  }
                  
                  if ((millis() - lastEnterDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEnterState=reading;
                    lastEnterDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEnterState = reading;
                  

    //Esc button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEsc);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEscState) {
                    // reset the debouncing timer
                    lastEscDebounceTime = millis();
                  }
                  
                  if ((millis() - lastEscDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEscState = reading;
                    lastEscDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEscState = reading;
                  
                     
   //Down button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinRight);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonRightState) {
                    // reset the debouncing timer
                    lastRightDebounceTime = millis();
                  }
                  
                  if ((millis() - lastRightDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonRightState = reading;
                   lastRightDebounceTime =millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonRightState = reading;                  
                  
                  
    //Up button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinLeft);

                  // check to see if you just pressed the Down button
                  // (i.e. the input went from LOW to HIGH),  and you've waited
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonLeftState) {
                    // reset the debouncing timer
                    lastLeftDebounceTime = millis();
                  }
                  
                  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonLeftState = reading;
                    lastLeftDebounceTime=millis();;
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonLeftState = reading;  

                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;

                  }else if(buttonEscState==HIGH){
                    lastButtonPushed=buttonPinEsc;

                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

                  }else if(buttonLeftState==HIGH){
                    lastButtonPushed=buttonPinLeft;

                  }else{
                    lastButtonPushed=0;
                  }                  
}

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();
 
  switch (lastButtonPushed){
    case buttonPinEnter:
      if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
        menu.use();
      }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
        menu.moveDown();
       }
      break;
    case buttonPinEsc:
      menu.toRoot();  //back to main
      break;
    case buttonPinRight:
      menu.moveRight();
      break;      
    case buttonPinLeft:
      menu.moveLeft();
      break;      
  }
 
  lastButtonPushed=0; //reset the lastButtonPushed variable
}


 

Link para o comentário
Compartilhar em outros sites

As libraries necessárias para rodar esse scketh estão no seguinte link:

https://onedrive.live.com/redir?resid=9DF00062C19ACFD2!15018&authkey=!AO2b0bz4M-KiB14&ithint=file%2czip

Link para o comentário
Compartilhar em outros sites

Vou começar a projetar um controlador arduino para máquina de café espresso.

O que vocês gostariam de ver nele?

 

Penso em usar o seguinte case:

 

 

 

 

Até o momento, minha idéia é que ele possua as seguintes funções:

 

A) Medição de temperatura (na gaggia, externamente à caldeira) (tem um buraco para instalar o termostato, que serve para instalar também o sensor termopar (acho que vou usar tipo k, por ser mais barato), mas estou aberto a sugestões;

 

B) Extração cronometrada (você define o número de segundos e o controlador, controla rss);

 

C) Pré-infusão (não sei se vou conseguir essa; penso em usar potência mais baixa (leia-se, menor voltagem ou pulsos de voltagem mais longos) na bomba para diminuir a pressão, mas não tenho idéia se isso vai influenciar na hora de distribuir a água pelo chuveirinho);

 

D) Definição da temperatura a ser mantida (setpoint);

 

Como a gaggia coffee, que vai ser a cobaia desse projeto, não tem válvula solenoide, não vou mexer com isso  nesse primeiro momento (seria muito complicado colocá-la nessa equação. Para usá-la teria que fazer um bypass por todo o sistema elétrico da cafeteira (na prática, retirar a placa controladora que vem nela da equação e controlar totalmente via arduino).

agora que resolvi meramente pidar a minha baby 

você diz que vai aparecer com uma traquitana mega funções.  :lol:

Link para o comentário
Compartilhar em outros sites

Uma idéia: Trocar o termostato de vapor por um sensor de pressão. Desta forma ele poderia controlar tanto a pressão de vaporização quanto a pressão de pré-infusão, que desta forma poderia replicar muito melhor a PI dita "verdadeira"

Link para o comentário
Compartilhar em outros sites

Certo. Poderia até usar o logaritmo PID para manter a pressão estável.

Mas, onde comprar e onde instalar o sensor?

 

Estimo que seja na tubulação que sai da bomba.

Link para o comentário
Compartilhar em outros sites

Seria algo assim:

Mas esse não serve porque só vai até 7bar

 

http://produto.mercadolivre.com.br/MLB-587880455-sensor-de-presso-para-arduino-mcu-pic-em-recife-_JM

 

 

Guilherme

Link para o comentário
Compartilhar em outros sites

A não ser que eu o utilize para a pre infusão ou para vapor.

 

Mas, se eu colocar uma pressão nominal maior do que ele é capaz de medir, não avariaria o equip?

Link para o comentário
Compartilhar em outros sites

O sensor não é tanto o problema quanto o controle decente da bomba que deve funcionar bem antes de mais nada.

 

Na minha máquina estou usando esse. Aguenta só 125 C portanto teria que instalar longe da caldeira. Logo na saída da bomba é um bom ponto.

 

Esse precisa de um opamp para amplificar o sinal. A configuração dele é em ponte de Wheatstone.

Link para o comentário
Compartilhar em outros sites

Sérgio,

Se puder, depois manda (via mp ou por aqui) um tutorial de como fazer a ligação dele (vcc, gnd, analog in) que eu estudo como adicioná-lo no controlador.

Pesquisei outros sensores na faixa de 0 a 10 bar e esse é o que se apresenta mais em conta.

Valeu.

Guilherme.

Link para o comentário
Compartilhar em outros sites

Dá uma olhada na datasheet do AD623.

 

O sensor que tenho aqui, que passei o link, não tem um gel para isolar da água. Eles tem modelos que tem e parecem ser mais adequados.

Link para o comentário
Compartilhar em outros sites

Achei esse aqui também. Parece ser um bom custo benefício, uma vez que posso conectar diretamente na tubulação (talvez mediante uso de um adaptador - redutor).

Suporta até 12 bar.

 

http://www.dx.com/p/carbon-steel-alloy-variable-pump-water-air-pressure-sensor-silver-black-dc-5v-343234#.VBdLPUD3Th4

 

sku_343234_2.jpg

 

Pelo que depreendi, você conecta os fios vermelho (vcc 5v) e preto (gnd) e o amarelo em uma porta analógica (input). De acordo com a pressão, haverá variação de voltagem entre 0,5 e 4.5vdc. Aí, para fazer a correpondência com a pressão (setpoint), basta usar o parâmetro map (). Por exemplo: map(ANALOG1, 0.5, 4.5, 0, 12);

 

De qualquer forma, já postei uma pergunta lá no forum do DX questionando as conexões, o que corresponderia a cada fio.

Link para o comentário
Compartilhar em outros sites

Acho que a ligação é assim:

 

15250892112_50608ceabe_b.jpg[/url]

 

A vantagem desse sensor do DX, além do preço não ser elevado, é que é muito fácil programar com base apenas na variação de voltagem.

Link para o comentário
Compartilhar em outros sites

Sim, parece legal.

 

Mas não adianta muito ter leitura de pressão se não há controle preciso da bomba. A não ser que o objetivo seja apenas mostrar a pressão e não controlá-la.

Link para o comentário
Compartilhar em outros sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Processando...
×
×
  • Criar Novo...