Rieccomi con un nuovo mega progetto: Beerino

Buongiorno a tutti,

Innanzi tutto scusate per la presenza discontinua.. vorrei poter essere più presente, ma proprio non ci riesco.
Il progetto della serra poi l'ho finito e una volta nati i peperoncini, l'ho smontato perchè mi era un po' passato.
Ora mi sono messo a fare la birra in casa con il metoto all grain, che vi spiegherò in breve.

Si prende una ricetta, si macinano i malti e si mettono in una pentola a vari step di temperatura (previsti dalla ricetta). Ogni step di temperatura ha una sua tempistica.
Finita questa fase si procede con il lavaggio delle trebbe e si versa tutto nella pentola per la bollitura in cui avviene la luppolatura.
quando il mosto bolle si fanno varie gettate di luppoli che devono stare in pentola per un tempo determinato dalla ricetta e dallo stile della birra che si vuole fare.
Terminata questa fase si fredda il mosto luppolato, si mette in fermentatore e si inocula il lievito.
Si misura la densità del mosto che potrebbe essere ad esempio 1,080, quando in fermentatore arriva a 1,020 si può imbottigliare e si aspetta qualche mese prima di poterla bere.

Ovviamente ragazzi questo è detto a grandissime linee...

Venendo a noi:

Questo è il mio impianto a caduta a 3 pentole

Questa invece è la centralina che ho pensato e costruito:


.
A cosa serve???

Serve a controllare il processo, saprete meglio di me che con arduino le possibilità di controllo sono infinite e se abbinate ad un raspberry diventano infinite^2.

La schedina verde è una di quelle schedine che permettono di controllare in pwm qualsiasi cosa con un uscita massima di 24V 10A. L'ho presa perchè se per caso si guastasse qualcosa posso terminare la birrificazione ugualmente.

questo è il coperchio della pentola di Mash, dove avviene la fase in cui il malto viene portato a vari step di temperatura per un tempo t.
Come potetevedere, anche se non si vede bene :stuck_out_tongue_closed_eyes:, ci ho montato sopra una ventola e un motore di un tergicristalli.

La mia centralina, tramite lo schedino cinese, controllerà il motore da tergicristallo e ne monitorerà la temperatura.
Infatti questi motori scaldano parecchio, poi hanno una corrente nell'ordine della decina di A e quindi raggiunta la temperatura critica per il motore si azionerà il ventolone.
I sensori di temperatura che userò sono tutti DS18B20.
Il motore del tergicristallo serve per impastare il mosto all'interno di questa pentola detta di Mash. Altrimenti sarei dovuto stare più di un ora a girare tutto a mano perchè la temperatura si sarebbe stratificata.

Internamente potete vedere una Ventolina, quella sarà controllata da un sensore di temperatura interna per il raffreddamento dell'alimentatore e dei mosfet di controllo.

Ci sono due JACK da pannello stereo a cui attaccherò 2 sonde (DS18B20), che mi serviranno a monitorare la temperatura di Mash e quella di Sparge.

Le altre due uscite servono per le pompe che faranno ricircolare il mosto nelle varie pentole e nel circuito di raffreddamento.

Le mie pentole sono dotate di un pozzetto

Detto questo per ora vorrei soltanto controllare soltanto i motori tramite i potenziometri e vedere tutto nello schermo.

In un secondo step controllerò le elettrovalvole del gas dei fornelloni implementando un filtro di tipo PID per compensare l'inerzia termica delle pentole e della massa di acqua.

Successivamente sarà implementato un RTC per i controlli di tempo e in futuro il raspberry mi servirà per connettere questo archibugio a internet e carcicarci le ricette in automatico.

Che ne pensate?

State sintonizzati che se non mi costringono a uscire oggi pomeriggio posto gli schemi elettrici, sennò lo farò a breve.
Non è niente di megacomplicato, semmai sarà difficile reperire i componenti. Io li ho recuperati da alcune schede che stavano buttando via (i soggetti sono sottointesi per evitare problemi).

Il progetto ha un costo che si aggira intorno ai 100 euro.

I materiali delle pentole e di tutto ciò che viene a contatto con il mosto devono essere rigorosamente acciaio inox 304 o 316, roba alimentare e quindi megacostosa :cold_sweat:. Questa esperienza è molto divertente perchè a volte mi sono sentito un po' un mix tra mac Guyver, un BlackSmith e un pazzo.

Lo stato attuale di avanzamento è che sono fermo perchè mi è entrato un 12V nel 5 volt di arduino mega e i ha fritto il chip.
Martedì arriva quello nuovo, speriamo in bene ahahaha

complimenti! $)

Complimenti anche da parte mia, mi preoccupa solo una cosa, leggendo la premessa della serra.... tutto sto bordello per stancarti al secondo bicchiere di birra? :stuck_out_tongue_closed_eyes:

visto che siamo conterranei, aspetto la prossima infornata...... sempre che ti serva un giudizio qualitativo

Non hai tutti i torti, ma ormai é da gennaio che faccio birra e il progetto è quasi finito quindi penso che lo finirò... Ho il problema che quando una cosa l ho finita poi perdo di interesse perché la fase che preferisco è quella creativa... Credo come tutti i maker...

Brunello:
visto che siamo conterranei, aspetto la prossima infornata...... sempre che ti serva un giudizio qualitativo

Avoglia se passi dalle parti di arezzo, ti fermi e si beve un birrino... Ne ho alcune già pronte fatte con altri metodi...

La cosa che mi preoccupa ora è una strana oscillazione del 5 volt quando aziono i pwm. Penso di averla risolta usando una nuova scheda perché quella vecchia aveva il mosfet della selezione dell alimentazione scoppiato. Questa oscillazione mi fa impazzire il display e perdo la comunicazione con le sonde... Ora devo solo fare qualche prova poi vi posto tutto...

ecco per ora sono arrivato fino a qui...

Da quando ho fatto il video ho implementato la funzione per visualizzare le temperature premendo OK nella schermata Monitor e ho implementato la funzione per visualizzare la potenza delle pompe nella schermata pompe, sempre premendo OK.

A breve gli schemi, per ora non c'è nulla di definitivo quindi preferisco aspettare un pochino prima di darveli. Niente di trascendentale tutta roba semplice, a progetto finito avrete tutto.

#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
#include <DallasTemperature.h>
#include <OneWire.h>

#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

int t_mash;
int t_sparge;
int t_int;
int t_mot;

int var = 0;

const int pot_p1 = A1;
const int pot_p2 = A0;

const int vi = 12;
const int vm = 10;
const int p1 = 9;
const int p2 = 11;

const int led_d = 13;
DeviceAddress tm, ts, ti, Tmot;

const int buttonPinLeft = 28;      // pin for the Up button
const int buttonPinRight = 26;    // pin for the Down button
const int buttonPinEsc = 24;     // pin for the Esc button
const int buttonPinEnter = 22;   // pin for the Enter button
int var_menu[] = {0,0};
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 = 275;    // the debounce time

unsigned long previousMillis = 0; //will store last time LED was updated
unsigned long interval = 150; //interval at which to blink (milliseconds)

int set = 0;
// LiquidCrystal display with:
// rs on pin 7
// rw on ground
// enable on pin 6
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(53,51,49,47,45,43);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Mash");
      MenuItem menuItem1SubItem1 = MenuItem("Set Timer Mash");
      MenuItem menuItem1SubItem2 = MenuItem("Go Timer Mash");
    MenuItem menu1Item2 = MenuItem("Boil");
      MenuItem menuItem2SubItem1 = MenuItem("Set Timer Boil");
      MenuItem menuItem2SubItem2 = MenuItem("Go Timer Boil");
    MenuItem menu1Item3 = MenuItem("Potenza Pompe");
    MenuItem menu1Item4 = MenuItem("Monitor");


void setup()
{
  Serial.begin(9600);
  sensors.begin();
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
  Serial.println(sensors.getDeviceCount(), DEC);
    
    if (!sensors.getAddress(tm, 0)) Serial.println("Unable to find address for Device 0");
    if (!sensors.getAddress(ts, 1)) Serial.println("Unable to find address for Device 1"); 
    if (!sensors.getAddress(ti, 2)) Serial.println("Unable to find address for Device 2"); 
    if (!sensors.getAddress(Tmot, 3)) Serial.println("Unable to find address for Device 3"); 
    
    sensors.setResolution(tm, TEMPERATURE_PRECISION);
    sensors.setResolution(ts, TEMPERATURE_PRECISION);
    sensors.setResolution(ti, TEMPERATURE_PRECISION);
    sensors.setResolution(Tmot, TEMPERATURE_PRECISION);
    
    sensors.getResolution(tm);
    sensors.getResolution(ts);
    sensors.getResolution(ti);
    sensors.getResolution(Tmot);
    
  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);
  menu.toRoot();
  lcd.setCursor(0,0);
  lcd.print("      I'M            ");
  lcd.setCursor(0,1);
  lcd.print("   THE KING             ");
  delay(3000);
  lcd.setCursor(0,0);
  lcd.print("   BREW-DUINO   ");
  lcd.setCursor(0,1);
  lcd.print("                 ");
  
}  // setup()...


void loop()
{
     switch(var){
      case 5:
      if(millis() - previousMillis > interval) {
      richiedi_t();
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("T_int = ");
      lcd.setCursor(9,0);
      lcd.print(t_int);
      lcd.setCursor(0,1);
      lcd.print("T_Mot = ");
      lcd.setCursor(9,1);
      lcd.print(t_mot);
      previousMillis = millis();
      }
      readButtons();
      break;
       
      case 6:
      if(millis() - previousMillis > interval) {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Pompa 1 = ");
      lcd.setCursor(9,0);
      lcd.print(leggi_pot(pot_p1));
      lcd.setCursor(0,1);
      lcd.print("Pompa 2 = ");
      lcd.setCursor(9,1);
      lcd.print(leggi_pot(pot_p2));
      previousMillis = millis();
      }
      readButtons();
      break;
      
      default:
        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,0); //set the start position for lcd printing to the second row
  
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("   BREW-DUINO   ");
      lcd.setCursor(0,1);
      lcd.print("                 ");
  }else if(newMenuItem.getName()=="Mash"){
      lcd.print("Mash           ");
  }else if(newMenuItem.getName()=="Set Timer Mash"){
      lcd.setCursor(0,0);
      lcd.print("Mash Menu");
      lcd.setCursor(0,1);
      lcd.print("Set Timer Mash");
  }else if(newMenuItem.getName()=="Go Timer Mash"){
      lcd.setCursor(0,0);
      lcd.print("Mash Menu");
      lcd.setCursor(0,1);
      lcd.print("Go Timer Mash   ");
  }else if(newMenuItem.getName()=="Boil"){
      lcd.print("Boil           ");
  }else if(newMenuItem.getName()=="Set Timer Boil"){
      lcd.setCursor(0,0);
      lcd.print("Boil Menu");
      lcd.setCursor(0,1);
      lcd.print("Set Timer Boil   ");
  }else if(newMenuItem.getName()=="Go Timer Boil"){
    lcd.setCursor(0,0);
    lcd.print("Boil Menu");
    lcd.setCursor(0,1);
    lcd.print("Go Timer Boil   ");
  }else if(newMenuItem.getName()=="Potenza Pompe"){
      lcd.print("Potenza Pompe      ");
  }
  else if(newMenuItem.getName()=="Monitor"){
      lcd.print("Monitor      ");
  }
} 
  
void menuUsed(MenuUseEvent used){

    if(used.item.getName() =="Monitor"){
      var =5;
    }if(used.item.getName() == "Set timer Mash"){
      var = 1;
    }else if(used.item.getName() == "Go timer Mash"){
      var = 2;
    }else if(used.item.getName() == "Set timer Boil"){
      var = 3;
    }else if(used.item.getName() == "Go timer Boil"){
      var = 4;
    }else if(used.item.getName() == "Potenza Pompe"){
      var = 6;
    }

    //situazioni

}


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;
                    var = 0;

                  }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();    
      break;
    case buttonPinRight:
      menu.moveRight();
      break;      
    case buttonPinLeft:
      menu.moveLeft();
      break;      
  }
  
  lastButtonPushed=0; //reset the lastButtonPushed variable
}

void richiedi_t(){
    sensors.requestTemperatures();
    t_mash = sensors.getTempC(tm);
    t_sparge = sensors.getTempC(ts);
    t_int =  sensors.getTempC(ti);
    t_mot = sensors.getTempC(Tmot);
}

int leggi_pot(int p){
    return map(analogRead(p),0,1023,0,255);
}

Ciao, sono niubbo in materia arduino (sto leggendo in proposito da un paio di settimane soltanto) ma faccio birra da sette anni e stavo pensando di automatizzare il processo di mash (per intanto 'solo' quello) con arduino. Sono in attesa del clone del mega2560 in arrivo dalla Cina e ho già anche comprato un po' di materiale come sonde, transistor, diodi e resistenze varie. La mia idea sarebbe di gestire un Rims tube elettrico da 2500 W con le librerie pid di arduino, inserire una sonda nel rims e una nella pentola di mash e, più avanti anche una nella pentola di sparge. In futuro poi l'idea è quella di gestire anche il riscaldamento della pentola di sparge con arduino ma senza pid; la logica di funzionamento sarebbe di scaldare l'acqua col gas nella pentola di sparge, quando arriva a T di mash in attivare la pompa che la porta nella pentola di mash, fare mash in e quindi passare al controllo del rims tramite pid per il controllo delle T di conversione e intanto gestire il riscaldamento dell'acqua di sparge. Se sei interessato a qualcosa di simile potremmo lavorare un po' insieme... A livello di programmazione son a zero (mi sto documentando), ma riguardo birrificazione e fai da te non ho problemi e una laurea in ingegneria mi può dare una mano...

nnc6:
Ciao, sono niubbo in materia arduino (sto leggendo in proposito da un paio di settimane soltanto) ma faccio birra da sette anni e stavo pensando di automatizzare il processo di mash (per intanto 'solo' quello) con arduino. Sono in attesa del clone del mega2560 in arrivo dalla Cina e ho già anche comprato un po' di materiale come sonde, transistor, diodi e resistenze varie. La mia idea sarebbe di gestire un Rims tube elettrico da 2500 W con le librerie pid di arduino, inserire una sonda nel rims e una nella pentola di mash e, più avanti anche una nella pentola di sparge. In futuro poi l'idea è quella di gestire anche il riscaldamento della pentola di sparge con arduino ma senza pid; la logica di funzionamento sarebbe di scaldare l'acqua col gas nella pentola di sparge, quando arriva a T di mash in attivare la pompa che la porta nella pentola di mash, fare mash in e quindi passare al controllo del rims tramite pid per il controllo delle T di conversione e intanto gestire il riscaldamento dell'acqua di sparge. Se sei interessato a qualcosa di simile potremmo lavorare un po' insieme... A livello di programmazione son a zero (mi sto documentando), ma riguardo birrificazione e fai da te non ho problemi e una laurea in ingegneria mi può dare una mano...

di dove sei? mi farebbe piacere incontrarti per fare 2 chiacchiere...
almeno tu mi dici i segreti della birrificazione e io ti aiuto col programma..

nel frattempo ho abbandonato la libreria menubackend e ho sviluppato un programma in cui implemento un "albero" con gli switch case. Roba da matti.
per ora ho solo implementato lo scorrimento dei menu e qualche funzione, ma il grosso ancora è da finire.

ecco il link al codice perchè non posso postarlo direttamente sul forum...

con l'array Var_menu[] mi sposto nei vari meandri del menu e in ogni parte del menu viene ricontrollata e settata in modo che vada nella posizione richiesta.
In ogni parte è possibile tornare al padre, andare a destra o a sinistra o scendere al figlio.

probabilmente detto a parole non si capisce, vi faccio uno schema oggi nel pomeriggio se trovo 10minuti

Calamaro:

nnc6:
Ciao, sono niubbo in materia arduino (sto leggendo in proposito da un paio di settimane soltanto) ma faccio birra da sette anni e stavo pensando di automatizzare il processo di mash (per intanto 'solo' quello) con arduino. Sono in attesa del clone del mega2560 in arrivo dalla Cina e ho già anche comprato un po' di materiale come sonde, transistor, diodi e resistenze varie. La mia idea sarebbe di gestire un Rims tube elettrico da 2500 W con le librerie pid di arduino, inserire una sonda nel rims e una nella pentola di mash e, più avanti anche una nella pentola di sparge. In futuro poi l'idea è quella di gestire anche il riscaldamento della pentola di sparge con arduino ma senza pid; la logica di funzionamento sarebbe di scaldare l'acqua col gas nella pentola di sparge, quando arriva a T di mash in attivare la pompa che la porta nella pentola di mash, fare mash in e quindi passare al controllo del rims tramite pid per il controllo delle T di conversione e intanto gestire il riscaldamento dell'acqua di sparge. Se sei interessato a qualcosa di simile potremmo lavorare un po' insieme... A livello di programmazione son a zero (mi sto documentando), ma riguardo birrificazione e fai da te non ho problemi e una laurea in ingegneria mi può dare una mano...

di dove sei? mi farebbe piacere incontrarti per fare 2 chiacchiere...
almeno tu mi dici i segreti della birrificazione e io ti aiuto col programma..

nel frattempo ho abbandonato la libreria menubackend e ho sviluppato un programma in cui implemento un "albero" con gli switch case. Roba da matti.
per ora ho solo implementato lo scorrimento dei menu e qualche funzione, ma il grosso ancora è da finire.

Sono del lago maggiore, tu??
Per qualsiasi cosa riguardante la birra chiedi pure, ciò che so te lo posso spiegare...
Comunque la mia idea era di partire dal progetto ardbir (lo trovi sul forum di areabirra) e modificare codice è pcb di quello dato che è concepito per arcuino uno r3 ed impianto single vessel...cosa ne pensi?

Ciao. :smiley:

Ciao PaoloP

nnc6, quel progetto secondo me è grandioso, ma conta che è più di un anno che ci lavorano sopra e quindi devi capire il loro programma.

Secondo me, prendendo spunto da quello, però facendo una cosa tua, fai prima e meglio.

All'inizio devi cercare di risolvere problemi semplici e poi ne aumenti la complessità. Se ti butti subito in una cosa del genere ti scoraggi prima di finirla. (consiglio personale)

Comunque è un peccato, io sono di Arezzo...

si si, chiaro che non è possibile partire in quinta direttamente, infatti pensavo di avere quello a riferimento, studiarlo per capirne il codice e poi adattarlo al mio!
Per ora attendo l'arrivo del Mega e una volta arrivato inizio a monitorare le temperature durante il processo e altre piccole cose, poi pensavo di creare uno sketch nel quale inserisco i parametri della ricetta (per semplicità credo, anche se dovrei cambiare lo sketch per ogni ricetta) e faccio gestire la fase di ammostamento, può essere una road map verosimile? o conviene iniziare già implementando una sorta di menu per gestire tutto dall'LCD di arduino?

Io ti consiglio di suddividere il lavoro in parti.

  1. fai un circuito di prova per un un pid (mi sfugge cosa sia Vessel, a memoria forse un'approssimazione???)
    puoi anche collegare la resistenza e la sonda di temperatura e ti guardi bene come funziona.

2.Provi a fare un programma per la gestione dell'ammostamento

  1. Provi a gestire un LCD con 4 bottoni (sembra facile ma in realtà è una menata incredibile).

  2. metti tutto insieme e "fixi" i bug

perlomeno io faccio sempre così.

tornando al mio programma incredibilmente lungo e poco efficiente ho buttato giù uno schema per farvi capire meglio cosa fa. Non so se ci sono parole strane dentro, ma a volte sclero quindi perdonatemi.

In pratica 0000 è la root, se premi destra o sinistra vai a scorrere i figli della root, se premi invio vai nei figli dei figli della root. se premi indietro torni ai padri. Un padre ha tanti figli ma ogni figlio ha un solo padre.

e lo schema a grandi linee dell'oggetto è questo:

M è il motore di mash da 20Adc da tergicristallo
Vi è la ventola interna e P1 e P2 sono le pompe che ancora devono arrivarmi da HK.

Il motore di Mash lo piloto tramite una schedina a parte.

Ho usato delle prese Jack per le sonde con DS18B20

perchè hanno 3 poli e la controparte è composta da un cavo tripolare e dalla sonda stessa:

mentre per pompe e motore ho usato delle prese bipolari di questo tipo:


con relativa controparte.
Probabilmente sono sottodimensionate per il motore da mash ma lo vedrò durante la prova generale quindi per ora stiamo alla sorte.

PS se qualcuno ha voglia di ottimizzare il programmone per me non ci sono problemi eh ahahahah

Aggiornata funzione per visualizzazione di mash con implementazione di funzione void buzza(int x); che deve ancora essere scritta, per fare un suono ogni volta che viene chiamata. con X si cambia la tipologia di suono.

int timer = 0;
int a = 0;
void timer_mash(){
  tot_tmash = step_t[0] + step_t[1] + step_t[2] + step_t[3];
  timer = (tot_tmash * 60) - a;
  lcd.setCursor(14,0);
  lcd.print(t_mash);
  lcd.setCursor(0,0);
  if(t_mash > 46 && t_mash < 57) lcd.print("Proteasi");
  if(t_mash > 55 && t_mash < 66) lcd.print("β-amilasi");
  if(t_mash > 67 && t_mash < 75) lcd.print("α -amilasi");
  if(t_mash >= 78) lcd.print("Mash Out");
  
  if(timer > (tot_tmash - step_t[0])*60 && timer < (tot_tmash-step_t[1])*60 && t_mash< step_c[0] - 2 && t_mash> step_c[0]  + 2) buzza(1);
  if(timer > (tot_tmash - step_t[1])*60 && timer < (tot_tmash-step_t[2])*60 && t_mash< step_c[1] - 2 && t_mash> step_c[1]  + 2) buzza(1);
  if(timer > (tot_tmash - step_t[2])*60 && timer < (tot_tmash-step_t[3])*60 && t_mash< step_c[2] - 2&& t_mash> step_c[2]  + 2) buzza(1);
  if(timer > (tot_tmash - step_t[3])*60 && t_mash< step_c[3] - 2 && t_mash> step_c[3]  + 2) buzza(1);
  
  if(timer > (tot_tmash - step_t[0])*60 && timer < (tot_tmash-step_t[0])*60-10) buzza(2);
  if(timer > (tot_tmash-step_t[1])*60 && timer < (tot_tmash-step_t[1])*60-10) buzza(2);
  if(timer > (tot_tmash-step_t[2])*60 && timer < (tot_tmash-step_t[2])*60-10) buzza(2);
  if(timer > (tot_tmash-step_t[3])*60 && timer < (tot_tmash-step_t[3])*60-10) buzza(2);
  lcd.setCursor(0,1);
  lcd.print(timer/60);
  lcd.print(":");
  lcd.print(timer%60);

  if(millis() - previousMillis > 1000 && set == 1) {
   if(timer > 1){
    a++;
    lcd.clear();
    previousMillis = millis();
   }else {
     timer = 0;
     lcd.clear();
     buzza(2);
     lcd.setCursor(0,0);
     lcd.print("MASH FINITO");
   }
  }
}

ok grazie, seguo la tua road map allora, solo mi sa che inizio con un semplice termometro...;-))
Dell'ultimo codice che hai postato non ho capito a cosa servono le righe che fanno buzza(2), o meglio ho capito che che fa suonare col tono 2 ma mi sfugge il motivo dell'istruzione...
Se riesci mi spiegheresti un po' anche l'if che hai messo dopo come funziona per favore?

dimenticavo: single vessel = singolo tino, si tratta della tipologia impiantistica, il mio impianto è invece a tre tini...

hai ragione l'ho padellata... dammi 5 min che la correggo

int timer = 0;
int a = 0;
void timer_mash(){
  tot_tmash = step_t[0] + step_t[1] + step_t[2] + step_t[3];
  timer = (tot_tmash * 60) - a;
  lcd.setCursor(14,0);
  lcd.print(t_mash);
  lcd.setCursor(0,0);
  if(t_mash > 46 && t_mash < 57) lcd.print("Proteasi");
  if(t_mash > 55 && t_mash < 66) lcd.print("β-amilasi");
  if(t_mash > 67 && t_mash < 75) lcd.print("α -amilasi");
  if(t_mash >= 78) lcd.print("Mash Out");
  
  if(timer < (tot_tmash)*60 && timer > (tot_tmash-step_t[0])*60 && (t_mash < step_c[0] - 2 || t_mash> step_c[0]  + 2)) buzza(1);
  if(timer < (tot_tmash-step_t[0])*60 && timer > (tot_tmash-step_t[0]-step_t[1])*60 && (t_mash < step_c[1] - 2 || t_mash> step_c[1]  + 2)) buzza(1);
  if(timer < (tot_tmash-step_t[0]-step_t[1])*60 && timer > (tot_tmash-step_t[0]-step_t[1]-step_t[2])*60 && (t_mash < step_c[2] - 2 || t_mash> step_c[2]  + 2)) buzza(1);
  if(timer < (tot_tmash-step_t[0]-step_t[1]-step_t[2])*60 && timer > (tot_tmash-step_t[0]-step_t[1]-step_t[2]-step_t[3])*60 && (t_mash < step_c[3] - 2 || t_mash> step_c[3]  + 2)) buzza(1);
  
  if(timer > (tot_tmash - step_t[0])*60 && timer < (tot_tmash-step_t[0])*60-10) buzza(2);
  if(timer > (tot_tmash-step_t[1]- step_t[0])*60 && timer < (tot_tmash-step_t[1]- step_t[0])*60-10) buzza(2);
  if(timer > (tot_tmash-step_t[2]-step_t[1]- step_t[0])*60 && timer < (tot_tmash-step_t[2]-step_t[1]- step_t[0])*60-10) buzza(2);

  lcd.setCursor(0,1);
  lcd.print(timer/60);
  lcd.print(":");
  lcd.print(timer%60);

  if(millis() - previousMillis > 1000 && set == 1) {
   if(timer > 1){
    a++;
    lcd.clear();
    previousMillis = millis();
   }else {
     timer = 0;
     lcd.clear();
     buzza(2);
     lcd.setCursor(0,0);
     lcd.print("MASH FINITO");
   }
  }
}

ho fatto un esempio scritto sulla mia lavagna per provare la teoria :smiley: