Første bryggeprosjekt - vvb - Arduino DIY

Amarillo

Norbrygg-medlem
Så vidt jeg ser har du elementOn i funksjonen steps som bør funke?
Pid-koden er ikke akkurat selvforklarende nei, jeg forstår den ikke jeg heller, men den fungerte brillefint på et ssr-relé. Et mekanisk relé vil nok slite litt mer.

Men jeg ville ikke ha tenkt på det nå, det er godt mulig at pid er unødvendig, det vil dere se etterhvert.
 
Så vidt jeg ser har du elementOn i funksjonen steps som bør funke?
Pid-koden er ikke akkurat selvforklarende nei, jeg forstår den ikke jeg heller, men den fungerte brillefint på et ssr-relé. Et mekanisk relé vil nok slite litt mer.

Men jeg ville ikke ha tenkt på den nå, det er godt mulig at pid er unødvendig, det vil dere se etterhvert.

Har elementOn ja, men da starter også tiden å gå i meskeprosessen. Tenkte på å ha en elementOn før step1 for å varme opp vann.
Bruker SSR, men vi prøver uten PID først for enkelhets skyld.
 

Amarillo

Norbrygg-medlem
Skjønner, tenkte dere ville starte styringen etter mash-in.
Mash-in temperatur kan jo legges inn som første steg i hver oppskrift, men da med en stopp etterpå som gir dere tid til å fylle malt og få jevn temperatur, og så gå videre etter et tastetrykk.

Mer elegant vil det kanskje være at koden starter med input av mash-in temperatur via keypad.
Ved oppnådd temperatur går koden videre etter valg av meskeprogram.
 
Skjønner, tenkte dere ville starte styringen etter mash-in.
Mash-in temperatur kan jo legges inn som første steg i hver oppskrift, men da med en stopp etterpå som gir dere tid til å fylle malt og få jevn temperatur, og så gå videre etter et tastetrykk.

Mer elegant vil det kanskje være at koden starter med input av mash-in temperatur via keypad.
Ved oppnådd temperatur går koden videre etter valg av meskeprogram.

Tenker kanskje å lage en buzzer som melder fra når mash-in-temp er oppnådd, og at programmet venter på en push-button før det fortsetter på steg 1.
Jeg er på det nivået at det å registrere tosifret tall fra keypad (for å sette mash-in-temp) er fortsatt litt next level ;)
 

Amarillo

Norbrygg-medlem
Det vil alltid være tre tastetrykk som er nødvendig, to tall og så enten # for å bekrefte, eller * for å starte på nytt.
Kode:
forsteInput();
andreInput();
lcd.print("Bekreft med # eller slett med *");
tredjeInput();

switch (input3) {
case '#':
  break;
case '*':
  forsteInput();
default:
  tredjeInput();
}
int strikeTemp = (tall1 * 10) + tall2;

void forsteInput() {
  lcd.clear()
  char input1 = kpd.getKey();
  int tall1 = input1 - 48;
  lcd.print(tall1);
}

void andreInput() {
  char input2 = kpd.getKey();
  int tall2 = input2 - 48;
  lcd.print(tall2);
}

void tredjeInput() {
  char input3 = kpd.getKey();
}

Tror det vil virke, men har aldri laget kode for display og keypad.
 
Tror det vil virke, men har aldri laget kode for display og keypad.

Funker med litt modifikasjoner (som jeg ikke har fått helt til enda). Det man for øvrig må tenke på når man bruker keypad-biblioteket og skal vente på en input er at det nesten alltid er NO_KEY. Man må altså bruke en:
while(key = NO_KEY) {
int key = kpd.getKey(); //så fort noe annet enn NO_KEY registreres (altså et reelt tastetrykk), hopper man ut av while-loopen.
}
int registeredKey = key; //registeredKey lagres med den verdien som ble trykket for å avslutte while-loopern. Mulig man ikke trenger denne linjen, da 'key' allerede har den verdien, men det går på min konto for uerfarenhet.. :)


Jeg greier å lagre et tosifret tall nå, og jeg greier å trykke # for å bekrefte tallet. Det jeg sliter med er "trykk * for å resette/gå tilbake til "Tast inn onsket mash in-temperatur.""
Sikkert noe unødvendig kode her, men det fungerer, bortsett fra muligheten til å resette altså...
Jeg har ikke brukt switch før, så tips til hvordan det kan brukes på denne koden mottas med takk :)
Kode:
#include <Keypad.h>

const byte ROWS = 4; //Keypad has 4 rows
const byte COLS = 3; //keypad has 3 columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},  //defining keypad structure
  {'7','8','9'},
  {'#','0','*'}
};

byte rowPins[ROWS] = { 9, 8, 7, 6 }; // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.

byte colPins[COLS] = { 12, 11, 10 }; // Connect keypad COL0, COL1 and COL2 to these Arduino pins.


Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

char key1;
char key2;
char key3;
char digit1;
char digit2;
char digit3;
char digit1FromFunction;
char digit2FromFunction;
char digit3FromFunction;
int mashInTemp;
int twoDigits;

void setup() {
Serial.begin(9600);

getTwoDigitNumber(); //Registers two digits from keypad

Serial.println();
Serial.println("Du har valgt denne temperaturen: ");
Serial.print(twoDigits); //prints chosen temperature
Serial.println(" grader Celsius. Bekreft med # eller reset med *");

keypadInput3(); //waiting for button to confirm or discard chosen temperature
if(digit3FromFunction=='*'){ // '#' registers as '*' - clueless as to why. If * (# IRL) is pressed, chosen temperature is confirmed.
  mashInTemp = twoDigits;
}
else if(digit3FromFunction=='#'){  // if # (* IRL) is pressed, I want the sequence to start over (from getTwoDigitNumber)
}


Serial.println();
Serial.print("Du har bekreftet denne temperaturen: ");
Serial.print(mashInTemp);
Serial.println(" grader Celsius");
delay(5000);
Serial.print("Oppvarming starter");
}


void loop() {
}

void keypadInput1() { //Function to get first digit of two digit number.
  while(key1==NO_KEY){
    key1 = kpd.getKey();
  }
  digit1FromFunction = (key1 - 48);
}

void keypadInput2() { //Function to get second digit of two digit number
  while(key2==NO_KEY){
    key2 = kpd.getKey();
  }
  digit2FromFunction = (key2 - 48);
}

void keypadInput3(){ //Function to get third digit (* or #) to confirm or discard two digit number
  while(key3==NO_KEY){
    key3 = kpd.getKey();
  }
  digit3FromFunction = key3;
}

void getTwoDigitNumber(){ //Function to get a to digit number called twoDigits
Serial.println("Tast inn onsket mash in-temperatur.");
keypadInput1();
digit1 = (digit1FromFunction);
keypadInput2();
digit2 = (digit2FromFunction);
twoDigits = ((digit1*10) + (digit2));

}
 
Sist redigert:

Amarillo

Norbrygg-medlem
int registeredKey = key; //registeredKey

Grunnen til denne biten er at du må gjøre om input fra keypad som alltid er formatert som tekst, til et tall. Når du gjør om tekst til int-variabel direkte får du ascii-nummeret til tegnet som er tastet inn. Derfor må det trekkes fra 48 for å få riktig tall.

I keypadInput3 trenger du ikke å gjøre om til tall, fordi du bare er ute etter # eller *, hvis tall tastes skal det ignoreres. Det er det switch/case gjør. Du kan gjøre akkurat det samme med if/elseif. Switch/case er kjekt å bruke hvis det er mange valg som kan gjøres, her er det bare 3 så if er egentlig like greit.

Ved tastetrykk # gjør 'break' at switch/case avsluttes og koden fortsetter.

Ved '*' skal tekst på displayet slettes og koden starter på nytt med input av første tall. Jeg ser ikke at du har lagt inn noe kode for dette? Hvis du bruker min switch/case kode her tror jeg det skal fungere.

Ved inntasting av et tredje tall skal det ignoreres og funksjonen for tredje input skal kjøres på nytt.

Håper dette var forståelig.

Ellers er det forståelig at det må brukes en while-loop for å vente på input fra keypad.
 
Tusen takk for fyldig respons, karer - lærer veldig mye av dere!
Jeg sliter fortsatt med å få flyt i det tilfellet at man trykker "reset" eller et tall når man får spørsmål om å bekrefte temperatur.
Om man putter getTwoDigitNumber() i case '#', vil man bare kjøre den funksjonen, uten å få spørsmålet om bekreftelse på nytt. Det samme om man putter keypadInput3 som default.
For å komme videre nå tror jeg bare jeg dropper bekreftelsen, så får jeg heller printe valgt temperatur ganske lenge for å være sikker på at vi får med oss valgt temp, og kan restarte programmet om det blir feil :rolleyes:

Kode:
//chosing of mash-in-temp initiates
 Serial.println("Tast inn onsket mash in-temperatur."); //prints request to enter mash-in-temp
getTwoDigitNumber(); //Registers two digits from keypad

Serial.println();
Serial.println("Du har valgt denne temperaturen: ");
Serial.print(twoDigits); //prints chosen temperature 
Serial.println(" grader Celsius. Bekreft med # eller reset med *");

keypadInput3(); //waiting for button to confirm or discard chosen temperature

switch(digit3FromFunction) {

case '*':
  break;
case '#':
//GÅ TILBAKE TIL "TAST INN ONSKET MASH IN-TEMP"

default:
//INGENTING SKAL SKJE. EVENTUELT GÅ TILBAKE TIL "TAST INN ONSKET MASH IN-TEMP"
}

mashInTemp = twoDigits;
Serial.println();
Serial.print("Du har bekreftet denne temperaturen: ");
Serial.print(mashInTemp);
Serial.println(" grader Celsius");
delay(5000);
Serial.print("Oppvarming starter");

//Heating water to mash-in-temp initiates
 
Da har jeg laget en temperaturstyring for gjæringsskap (kjøleskap + en liten ekstern varmekilde). Den ble prioritert over en enhet som styrer meskeprosessen, da jeg har skjønt at gjæringstemp er enda viktigere (meskestyringen skal også gjøres ferdig).
Tempstyringen slår på en kotakt (til kjøleskap), om temp stiger over ønsket verdi+0,3 grader, og slår på den andre kontakten (til varmekilde) om tempen synker under ønsket verdi-0,3 grader. Dette funker fint, men jeg ønsker å ha varme/kjøling på helt til temp er akkurat på ønsket verdi, ikke bare til ønsket verdi +-0,3 grader (om det gir mening). Jeg har prøvd med en if { while {, men da slutter programmet å oppdatere temp.

Kode:
#include <Keypad.h>
#include <LiquidCrystal.h>  //includes libraries for hardware
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2 //datacable for temp.sensor on digital pin 2
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature sensors(&oneWire); //send oneWire-reference to Dallas Temperature

float tempInC;  //decimal to us for printing temp i deg C

char key1;               //characters for use in keypad-set-desired-temp
char key2;
char key3;
char digit1FromFunction;
char digit2FromFunction;
char digit3FromFunction;
int twoDigits;
int tempLimit;

int greenLed = 1;
int redLed = 3;
int whiteLed = 13;
int coolRelay = 4;
int heatRelay = 5;


byte Lae[8] = {B00000,B00000,B11010,B00101,B01111,B10100,B11111,B00000}; //æ
byte Loe[8] = {B00000,B00001,B01110,B10101,B10101,B01110,B10000,B00000}; //ø

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);//lcd(13, 14, 15, 16, 17, 18); //digital pins for LCD

char key; //1 digit from keypad
const byte ROWS = 4; //Keypad has 4 rows
const byte COLS = 3; //keypad has 3 columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},  //defining keypad structure
  {'7','8','9'},
  {'*','0','#'}
};

byte rowPins[ROWS] = { 9, 8, 7, 6 }; // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.

byte colPins[COLS] = { 12, 11, 10 }; // Connect keypad COL0, COL1 and COL2 to these Arduino pins.


Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); //constructing keypad

void setup() {
//Serial.begin(9600); //cannot be used witch digital pin 0 and 1 on digitalRead
sensors.begin();
lcd.begin(16,2);

pinMode(redLed, OUTPUT);
pinMode(greenLed, OUTPUT);
pinMode(whiteLed, OUTPUT);
pinMode(coolRelay, OUTPUT);
pinMode(heatRelay, OUTPUT);


lcd.createChar (1, Lae); //æ
lcd.createChar(2, Loe); //ø

lcd.clear();


unsigned long now = millis();

while(millis()-now < 4000){   //blinky "loading"
digitalWrite(redLed, HIGH);
delay(90);
digitalWrite(redLed, LOW);

digitalWrite(greenLed, HIGH);
delay(90);
digitalWrite(greenLed, LOW);

digitalWrite(whiteLed, HIGH);
delay(90);
digitalWrite(whiteLed, LOW);}



  sensors.requestTemperatures();
  lcd.print("Temperatur: ");
  lcd.print(sensors.getTempCByIndex(0));
  delay(5000);
  lcd.clear();
//Serial.println("Velg ønsket temperatur");
lcd.print("Velg ");
lcd.write(2);
lcd.print("nsket");
lcd.setCursor(0,1);
lcd.print("temperatur.");

getTwoDigitNumber();
tempLimit = twoDigits;
lcd.clear();
lcd.print("Du har valgt:");
lcd.setCursor(0,1);
lcd.print(tempLimit);
lcd.print(" grader C");
//Serial.print("Du har valgt ");
//Serial.print(tempLimit);
//Serial.println(" grader");
delay(5000);
lcd.clear();
lcd.print("Temp-styring");
lcd.setCursor(0,1);
lcd.print(tempLimit);
lcd.print(" grader kj");
lcd.write(2);
lcd.print("rer");
//Serial.print("Temperaturstyring ");
//Serial.print(tempLimit);
//Serial.println(" grader starter.");
delay(5000);


}

void loop() {

  getTempPrintLcd();
if (tempInC < (tempLimit-0.3)){                      //dette fungerer nå, men om while inkluderes, gjøres ingen av operasjonene under.
 //while(tempInC < tempLimit);{                 
  digitalWrite(coolRelay, LOW);
  digitalWrite(heatRelay, HIGH);
  digitalWrite(redLed, HIGH);
  digitalWrite(whiteLed, LOW);
  digitalWrite(greenLed, LOW);
 //  getTempPrintLcd();
 //}
}
else if (tempInC > (tempLimit+0.3)){
 //while(tempInC > tempLimit){
  digitalWrite(heatRelay, LOW);
  digitalWrite(coolRelay, HIGH);
  digitalWrite(whiteLed, HIGH);
  digitalWrite(redLed, LOW);
  digitalWrite(greenLed, LOW);
  //  getTempPrintLcd();
  //}
}
else {
  digitalWrite(heatRelay, LOW);
  digitalWrite(coolRelay, LOW);
  digitalWrite(greenLed, HIGH);
  digitalWrite(whiteLed, LOW);
  digitalWrite(redLed, LOW);
  }
}


void getTempPrintLcd() {    //function to read and print temp from sensor
  sensors.requestTemperatures();
  tempInC = sensors.getTempCByIndex(0);
  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  lcd.print(tempInC);
  lcd.print("     ");
  lcd.setCursor(0,1);
  lcd.print("Idealtemp: ");
  lcd.print(tempLimit);
  lcd.print("   ");
  //Serial.print("Temperatur: ");
  //Serial.print(tempInC);
  //Serial.print(". Ideell temperatur: ");
  //Serial.println(tempLimit);
}

void keypadInput1() { //Function to get first digit of two digit number.
  while(key1==NO_KEY){
    key1 = kpd.getKey();
  }
  digit1FromFunction = (key1 - 48);
}

void keypadInput2() { //Function to get second digit of two digit number
  while(key2==NO_KEY){
    key2 = kpd.getKey();
  }
  digit2FromFunction = (key2 - 48);
}

void getTwoDigitNumber(){ //Function to get a to digit number called twoDigits
 keypadInput1();
 keypadInput2();
 twoDigits = ((digit1FromFunction*10) + (digit2FromFunction));
}

Om noen ser en logisk brist, setter jeg umåtelig pris på tilbakemelding.
Det kan for så vidt være hensiktsmessig at oppvarming/nedkjøling skrus av når 0,3 grader før ønsket temp er oppnådd, men jeg ønsker uansett å kunne teste uten at dette er tilfelle.

PS: beklager dårlig kommentering!
 





Slik ser for øvrig enheten ut


Sent from my iPhone using Tapatalk
 

TorfinnS

Norbrygg-medlem
Ser at du gjør som svært mange andre, du bruker for liten kapsling. Da får du hull i kapslingen som ikke er tilsiktet. Dette er ment som konstruktiv kritikk. Jeg jobber blant annet med dette. Har bygget mange skap opp gjennom tiden. Skjønner at skap og kapslinger kan være dyrt men man må tenke elsikkerhet, varmeutvikling osv.
 
Ser at du gjør som svært mange andre, du bruker for liten kapsling. Da får du hull i kapslingen som ikke er tilsiktet. Dette er ment som konstruktiv kritikk. Jeg jobber blant annet med dette. Har bygget mange skap opp gjennom tiden. Skjønner at skap og kapslinger kan være dyrt men man må tenke elsikkerhet, varmeutvikling osv.

Takk for tilbakemelding. Det er dog ingen utilsiktede hull. To hull til arduinotilkobling (usb og DC). Det ser riktignok ikke helt bra ut på baksiden med litt smeltet plast - dette pga at jeg måtte kappe/slipe bort en del "nupper" for å få jevn overflate.
Mener du at det kan bli for varmt inni boksen? Det som evt genererer varme er Arduino uno (minimalt) og to stk SSR. Bør det investeres i større kapsling før dette settes på over 14 dager? [emoji23]


Sent from my iPhone using Tapatalk
 

TorfinnS

Norbrygg-medlem
Om det blir for varmt vet jeg ikke. Det får du jo bare prøve. Men disse ssr avgir endel varme. Vi bruker beregningsprogrammer for å beregne hvor stor kapsling man trenger i forhold til ønsket temperatur på utstyret inni. Ja var den smeltede plasten jeg tenkte på.
 
Om det blir for varmt vet jeg ikke. Det får du jo bare prøve. Men disse ssr avgir endel varme. Vi bruker beregningsprogrammer for å beregne hvor stor kapsling man trenger i forhold til ønsket temperatur på utstyret inni. Ja var den smeltede plasten jeg tenkte på.

Ok, takk for heads up! Skal følge nøye med temp før utstyret forlates på.


Sent from my iPhone using Tapatalk
 

Amarillo

Norbrygg-medlem
//while(tempInC < tempLimit);{

Du har et semikolon som ikke skal være der, ellers ser jeg ikke noe annet som er feil. Bortsett fra at du har kommentert ut while-loopen, men det er du vel klar over :)

Jeg har laget samme kode i et prosjekt jeg holder på med, bare med styring via Blynk i stedet for keypad og display. Du tenker riktig, først en if som har med hysterese, og så en while-loop uten. Så hvorfor det ikke virker er ikke lett å si. Jeg har ikke filen min her, men er rimelig sikker på at det er akkurat samme kode som jeg har i mitt prosjekt.
 
Du har et semikolon som ikke skal være der, ellers ser jeg ikke noe annet som er feil. Bortsett fra at du har kommentert ut while-loopen, men det er du vel klar over :)

Jeg har laget samme kode i et prosjekt jeg holder på med, bare med styring via Blynk i stedet for keypad og display. Du tenker riktig, først en if som har med hysterese, og så en while-loop uten. Så hvorfor det ikke virker er ikke lett å si. Jeg har ikke filen min her, men er rimelig sikker på at det er akkurat samme kode som jeg har i mitt prosjekt.

Takk! Brukte 3-4 timer på små forandringer for å løse problemet, uten å klare det.. programmet ville ikke kjøre loopen med if while. Ett semikolon mindre, og alt fungerer perfekt[emoji4]
Blynk ser kult ut, spørs om det må læres og integreres som fjernovervåking..:)

Til det mer gjærfaglige: 0,3 grader +-, er det for mye slingringsmonn?


Sent from my iPhone using Tapatalk
 
Sist redigert:

Amarillo

Norbrygg-medlem
Ok, så semikolonet stoppet hele if-rekka? Trodde det bare stoppet den ene while-loopen. Men det er det som både er fascinerende og irriterende med koding, ett tegn på feil plass kan gi uante konsekvenser. :mad:

0,3 grader slingringsmonn er det jeg alltid har brukt på mine STC-1000 og det funker bra.
 
Ok, så semikolonet stoppet hele if-rekka? Trodde det bare stoppet den ene while-loopen. Men det er det som både er fascinerende og irriterende med koding, ett tegn på feil plass kan gi uante konsekvenser. :mad:

0,3 grader slingringsmonn er det jeg alltid har brukt på mine STC-1000 og det funker bra.

Stoppet hele if-rekka, ja. Irriterende og fascinerende [emoji4]
Prøver med 0,3 - må vel uansett tørrtrene litt med skapet først for å finne ut hva som bør stå.


Sent from my iPhone using Tapatalk
 
Da er første sats satt til gjæring! Vi prøvde oss på en IPA etter Ægirs oppskrift, men jeg tror neppe vi ligner på originalen når det skal smakes på [emoji4]
En del barnesykdommer på bryggeriet som gjorde at vi blant annet endte opp med en OG på rundt 1.040(!) i stedet for 1.064 - så det spørs om det blir en butikkvennlig variant.
Tempstyringa til kjøleskapet fungerer utmerket! Merker dog stor forskjell i temperatur om sensoren blir plassert på en av glasshyllene eller oppå en av dunkene (har to dunker over hverandre). Har lagt sensoren oppå den nedereste dunken nå, der er det opp mot 4-5 grader varmere enn på hylla, og stillt inn tempen på 18 grader de første fem dagene. Oppskrifta sier 20 grader i ølet under gjæring. Høres det innafor ut?
Skal lage ferdig styreprogrammet for mesking og koking når jeg får kloa i et rimelig stålskap - og får tid til å bygge det opp[emoji4]



Sent from my iPhone using Tapatalk
 
Topp