Browse Source

general bugfixes to temperature controller

master
Barb 9 months ago
parent
commit
38ee9df40d
5 changed files with 1068 additions and 1033 deletions
  1. +63
    -55
      PyCoffeeESP8266/PyCoffeeESP8266.ino
  2. BIN
      PyCoffeeESP8266/PyCoffeeESP8266.ino.d1_mini.bin
  3. +48
    -42
      PyCoffeeNano/PyCoffeeNano.ino
  4. +479
    -468
      PyCoffeeNano/PyCoffeeNano.ino.eightanaloginputs.hex
  5. +478
    -468
      PyCoffeeNano/PyCoffeeNano.ino.with_bootloader.eightanaloginputs.hex

+ 63
- 55
PyCoffeeESP8266/PyCoffeeESP8266.ino View File

@ -9,6 +9,17 @@
AsyncWebServer server(80); AsyncWebServer server(80);
// coffee times (in seconds) and temperature (in C) settings:
//int rist = 15;
//int espr = 20;
//int lung = 25;
//int amer = 60;
int desiredTemp = 70;
// support variables used by checktraywater() to interact with EEPROM
int mem0 = 0;
int mem1 = 0;
// This next variable is used to get current "time" in ms and break out of while cycles that need a time limit safeguard // This next variable is used to get current "time" in ms and break out of while cycles that need a time limit safeguard
unsigned long startTime; unsigned long startTime;
@ -63,10 +74,10 @@ const char index_html[] PROGMEM = R"rawliteral(
<option value="heat">Heat Boiler</option> <option value="heat">Heat Boiler</option>
<option value="grin">GrindPowder</option> <option value="grin">GrindPowder</option>
<option value="drop">Drop Powder</option> <option value="drop">Drop Powder</option>
<option value="rist">setRistretto-10s</option>
<option value="espr">setEspresso-15s</option>
<option value="long">setLungo-20s</option>
<option value="amer">setAmericano-50s</option>
<option value="rist">setRistretto-15s</option>
<option value="espr">setEspresso-20s</option>
<option value="long">setLungo-25s</option>
<option value="amer">setAmericano-60s</option>
</select><br><br> </select><br><br>
<input type="submit" value="Invia Comando"> <input type="submit" value="Invia Comando">
</form> </form>
@ -103,7 +114,7 @@ String type = "Espresso";
int coffeesDone = 0; int coffeesDone = 0;
int pumpedS = 0; int pumpedS = 0;
const int MaxCoffees = 10; const int MaxCoffees = 10;
const int MaxPumped = 205;
const int MaxPumped = 500;
// Support string to store stuff to be sent over serial // Support string to store stuff to be sent over serial
String serialOUTbuffer = "none"; String serialOUTbuffer = "none";
@ -144,8 +155,20 @@ void notFound(AsyncWebServerRequest *request) {
void setup(void) { void setup(void) {
// check how many coffees were done and seconds of pumped water from EEPROM // check how many coffees were done and seconds of pumped water from EEPROM
coffeesDone = (EEPROM.read(0));
pumpedS = (EEPROM.read(1));
mem0 = (EEPROM.read(0));
mem1 = (EEPROM.read(1));
// protect against under/over-flow due to errors or memory location never having been used
if (mem0 < 0 or mem0 > MaxCoffees + 1) {
EEPROM.write(0, 0);
mem0 = 0;
}
if (mem1 < 0 or mem1 > MaxPumped + 50) {
EEPROM.write(1, 0);
mem1 = 0;
}
coffeesDone = mem0;
pumpedS = mem1;
// Set buttons as inputs with internal pull-ups // Set buttons as inputs with internal pull-ups
pinMode(enter, INPUT_PULLUP); pinMode(enter, INPUT_PULLUP);
@ -215,13 +238,18 @@ void setup(void) {
serialOUTbuffer = "read"; serialOUTbuffer = "read";
delay(100); delay(100);
writeSerial(); writeSerial();
type = "Espresso";
line1 = "Selection";
line2 = type;
LCDprint();
delay(500);
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void loop() { void loop() {
// the loop function runs over and over again forever // the loop function runs over and over again forever
checkTrayWater();
delay(10); delay(10);
serialFromHTTP(); serialFromHTTP();
@ -306,7 +334,7 @@ void bootAnimation() {
delay(1000); delay(1000);
line1 = "ESP_Coffee"; line1 = "ESP_Coffee";
line2 = "Release 1.1";
line2 = "Release 1.1e";
LCDprint(); LCDprint();
delay(1000); delay(1000);
line1 = "JIMBO"; line1 = "JIMBO";
@ -465,60 +493,40 @@ void serialFromHTTP() {
void checkTrayWater() { void checkTrayWater() {
// section dedicated to empty tray and refill water messages // section dedicated to empty tray and refill water messages
if ((EEPROM.read(0)) < 0 or (EEPROM.read(0)) > MaxCoffees + 1) {
EEPROM.write(0, 0);
EEPROM.commit();
}
else if ((EEPROM.read(0)) < coffeesDone) {
EEPROM.write(0, coffeesDone);
EEPROM.commit();
}
if ((EEPROM.read(1)) < 0 or (EEPROM.read(1)) > MaxPumped + 1) {
EEPROM.write(1, 0);
EEPROM.commit();
}
else if ((EEPROM.read(1)) < pumpedS) {
EEPROM.write(1, pumpedS);
EEPROM.commit();
}
if (coffeesDone > (MaxCoffees - 1)) {
if (coffeesDone == MaxCoffees) {
lcd.clear(); lcd.clear();
while (digitalRead(enter) == HIGH) { while (digitalRead(enter) == HIGH) {
lcd.setCursor(0, 0); // move cursor to (0, 0)
lcd.print("Empty Tray"); // print line1
delay(10);
lcd.setCursor(0, 1); // move cursor to (0, 1)
lcd.print("Then hold Make"); // print line2
delay(10);
line1 = "Empty Tray";
line2 = "Then hold Make";
delay(500);
LCDprint();
} }
coffeesDone = 0; coffeesDone = 0;
EEPROM.write(0, coffeesDone);
EEPROM.commit();
delay(500);
EEPROM.write(0, 0);
line1 = "Tray emptied";
line2 = "continuing...";
delay(1000);
LCDprint(); LCDprint();
delay(500);
printed = 1;
} }
if (pumpedS > (MaxPumped + 1)) {
if (pumpedS > MaxPumped) {
lcd.clear(); lcd.clear();
while (digitalRead(enter) == HIGH) { while (digitalRead(enter) == HIGH) {
lcd.setCursor(0, 0); // move cursor to (0, 0)
lcd.print("Refill Water"); // print line1
delay(10);
lcd.setCursor(0, 1); // move cursor to (0, 1)
lcd.print("Then hold Make"); // print line2
delay(10);
line1 = "Refill Water";
line1 = "Then hold Make";
delay(500);
LCDprint();
} }
pumpedS = 0; pumpedS = 0;
EEPROM.write(1, pumpedS);
EEPROM.commit();
delay(500);
EEPROM.write(1, 0);
line1 = "Water Refilled";
line2 = "continuing...";
delay(1000);
LCDprint(); LCDprint();
delay(500);
printed = 1;
} }
delay(500);
printed = 1;
EEPROM.commit();
line1 = "Selection"; line1 = "Selection";
line2 = type; line2 = type;
} }
@ -530,19 +538,19 @@ void serialCoffeeCommandLCDInterface() {
httpCoffee = 0; httpCoffee = 0;
if (type == "Espresso") { if (type == "Espresso") {
serialOUTbuffer = "espr"; serialOUTbuffer = "espr";
pumpedS = pumpedS + 15;
pumpedS = pumpedS + 20;
} }
else if (type == "Lungo") { else if (type == "Lungo") {
serialOUTbuffer = "long"; serialOUTbuffer = "long";
pumpedS = pumpedS + 20;
pumpedS = pumpedS + 25;
} }
else if (type == "Ristretto") { else if (type == "Ristretto") {
serialOUTbuffer = "rist"; serialOUTbuffer = "rist";
pumpedS = pumpedS + 10;
pumpedS = pumpedS + 15;
} }
else if (type == "Americano") { else if (type == "Americano") {
serialOUTbuffer = "amer"; serialOUTbuffer = "amer";
pumpedS = pumpedS + 50;
pumpedS = pumpedS + 60;
} }
writeSerial(); writeSerial();
delay(500); delay(500);


BIN
PyCoffeeESP8266/PyCoffeeESP8266.ino.d1_mini.bin View File


+ 48
- 42
PyCoffeeNano/PyCoffeeNano.ino View File

@ -9,9 +9,8 @@ String readString;
// Code must be adjusted accordingly if a PTC resistor is used once more! // Code must be adjusted accordingly if a PTC resistor is used once more!
int Vo; int Vo;
float R1 = 10000; // <-- change this value to the resistance of the fixed resistor (so don't change PLS!) float R1 = 10000; // <-- change this value to the resistance of the fixed resistor (so don't change PLS!)
float logR2, R2, T, Tc, Told;
float logR2, R2, T, Tc, Tp, Tstart, Told;
float c1 = 8.5e-04, c2 = 1.85e-04, c3 = 2e-07; // Here's where you can perform actual calibration float c1 = 8.5e-04, c2 = 1.85e-04, c3 = 2e-07; // Here's where you can perform actual calibration
// Variable to store desired Max boiler Temp // Variable to store desired Max boiler Temp
int desiredTemp = 70; int desiredTemp = 70;
@ -19,7 +18,6 @@ int desiredTemp = 70;
int unrecoverableErr = 0; int unrecoverableErr = 0;
int warning = 0; int warning = 0;
int warned = 0; // support variable needed to prevent arduino from making second coffee after refill. this is a shitty hack and resets the board. int warned = 0; // support variable needed to prevent arduino from making second coffee after refill. this is a shitty hack and resets the board.
// Variables for cleaning and other maintenance // Variables for cleaning and other maintenance
int dry = 0; int dry = 0;
int noCoffee = 0; int noCoffee = 0;
@ -31,13 +29,11 @@ int timeratio = 1;
int pumpRatio = 15; // warning: there is usually ~5s dead time from pump startup to water flowing out of nozzle int pumpRatio = 15; // warning: there is usually ~5s dead time from pump startup to water flowing out of nozzle
// This next variable is used to get current "time" in ms and break out of while cycles that need a time limit safeguard // This next variable is used to get current "time" in ms and break out of while cycles that need a time limit safeguard
unsigned long startTime; unsigned long startTime;
unsigned long pMillis;
//_____________________________________________________________________________ //_____________________________________________________________________________
void(* resetFunc) (void) = 0; // declare reset fuction at address 0 void(* resetFunc) (void) = 0; // declare reset fuction at address 0
//_____________________________________________________________________________ //_____________________________________________________________________________
void setup() { void setup() {
// put your setup code here, to run once: // put your setup code here, to run once:
// first we set pins as I/O and initialize outputs LOW // first we set pins as I/O and initialize outputs LOW
@ -53,7 +49,6 @@ void setup() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void loop() { void loop() {
// put your main code here, to run repeatedly: // put your main code here, to run repeatedly:
digitalWrite(greenLED, HIGH); digitalWrite(greenLED, HIGH);
@ -86,33 +81,32 @@ void loop() {
//if (incomingData == "read") { //if (incomingData == "read") {
//digitalWrite(greenLED, HIGH); //digitalWrite(greenLED, HIGH);
//} //}
if (incomingData == "rist") { if (incomingData == "rist") {
// set parameters for ristretto: // set parameters for ristretto:
delay(100); delay(100);
Serial.write("Ristretto\n"); Serial.write("Ristretto\n");
pumpRatio = 10;
pumpRatio = 15;
} }
if (incomingData == "espr") { if (incomingData == "espr") {
// set parameters for espresso: // set parameters for espresso:
delay(100); delay(100);
Serial.write("Espresso\n"); Serial.write("Espresso\n");
pumpRatio = 15;
pumpRatio = 20;
} }
if (incomingData == "long") { if (incomingData == "long") {
// set parameters for lungo: // set parameters for lungo:
delay(100); delay(100);
Serial.write("Lungo\n"); Serial.write("Lungo\n");
pumpRatio = 20;
pumpRatio = 25;
} }
if (incomingData == "amer") { if (incomingData == "amer") {
// set parameters for lungo: // set parameters for lungo:
delay(100); delay(100);
Serial.write("Americano\n"); Serial.write("Americano\n");
pumpRatio = 50;
pumpRatio = 60;
} }
// check if the incoming data is "make": // check if the incoming data is "make":
@ -187,7 +181,7 @@ void loop() {
// making steam: // making steam:
while (digitalRead(vaporSensorPin) == HIGH) { while (digitalRead(vaporSensorPin) == HIGH) {
desiredTemp = 90;
desiredTemp = 100;
Serial.write("Vapor heating\n"); Serial.write("Vapor heating\n");
delay(500); delay(500);
Heat(); // Heat the boiler to vapor temperature Heat(); // Heat the boiler to vapor temperature
@ -201,7 +195,6 @@ void loop() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
// this is how we read the input // this is how we read the input
void serialRead() { void serialRead() {
while (Serial.available()) { while (Serial.available()) {
@ -213,7 +206,6 @@ void serialRead() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void Grind() { void Grind() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
delay(100); delay(100);
@ -242,7 +234,6 @@ void Grind() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void Drop() { void Drop() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
delay(100); delay(100);
@ -256,18 +247,19 @@ void Drop() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void Heat() { void Heat() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
digitalWrite(redLED, HIGH); digitalWrite(redLED, HIGH);
startTime = millis(); startTime = millis();
pMillis = startTime; // value to store
delay(100); delay(100);
Serial.write("Heating to "); Serial.write("Heating to ");
delay(100); delay(100);
Serial.print(desiredTemp); Serial.print(desiredTemp);
delay(100); delay(100);
Tc = 0;
Told = - 100;
Tc = 0; // current temperature
Tp = -10; // temperature at previous cycle
Tstart = - 100; // temperature at start of Heat() function
// monitor temperature and adjust boilerPin as needed: // monitor temperature and adjust boilerPin as needed:
while (true) { while (true) {
@ -280,56 +272,76 @@ void Heat() {
Tc = (T - 273.15); Tc = (T - 273.15);
if (millis() - startTime == 1000) { if (millis() - startTime == 1000) {
Told = Tc; // support variable to store temp at beginning, so that we can be sure it's increasing
Tstart = Tc; // support variable to store temp at beginning, so that we can be sure it's increasing
} }
// check if temperature is within the acceptable range and break out of the loop without error if done heating: // check if temperature is within the acceptable range and break out of the loop without error if done heating:
if (Tc > desiredTemp) { if (Tc > desiredTemp) {
// temperature is within range, so break out of the loop: // temperature is within range, so break out of the loop:
digitalWrite(boilerPin, LOW);
delay(100); delay(100);
Serial.write("reached desired temp\n"); Serial.write("reached desired temp\n");
delay(100); delay(100);
Serial.print(Tc); Serial.print(Tc);
delay(100);
digitalWrite(redLED, LOW);
break; break;
} }
if (Tc < -100) { if (Tc < -100) {
delay(100); delay(100);
Serial.write("u-Thermocouple: unplugged or failed\n"); Serial.write("u-Thermocouple: unplugged or failed\n");
digitalWrite(boilerPin, LOW);
unrecoverableErr = 1; unrecoverableErr = 1;
break; break;
} }
if (millis() - startTime > 20000 && Tc - Told < 1) {
if (millis() - startTime > 20000 && Tc - Tstart < 1) {
delay(100); delay(100);
Serial.write("p-Thermocouple: positioning or relay fault\n"); Serial.write("p-Thermocouple: positioning or relay fault\n");
digitalWrite(boilerPin, LOW);
unrecoverableErr = 1; unrecoverableErr = 1;
break; break;
} }
if (millis() - startTime > 30000) {
if (millis() - startTime > 60000) {
delay(100); delay(100);
Serial.write("h-taking too long, continuing...\n"); Serial.write("h-taking too long, continuing...\n");
digitalWrite(boilerPin, LOW);
digitalWrite(redLED, LOW);
break; break;
} }
// We do this at the end so that the relay is not uselessly cycled
digitalWrite(boilerPin, HIGH);
// actual heater logic follows:
// check aprox. derivative every second and shut off heater if temperature is increasing too quickly!
// conversely, heater is turned on if temperature is not incresing quickly enough
if (millis() > (pMillis + 1000)){
if (Tc < (desiredTemp - 20)) {
digitalWrite(boilerPin, HIGH);
}
else if ((Tc - Tp) < 0.5) {
digitalWrite(boilerPin, HIGH);
}
//else if ((Tc - Tp) > 1) {
// digitalWrite(boilerPin, LOW);
//}
else {
digitalWrite(boilerPin, LOW);
}
Tp = Tc;
pMillis = millis();
}
delay(milliseconds); delay(milliseconds);
} }
digitalWrite(boilerPin, LOW);
digitalWrite(redLED, LOW);
digitalWrite(greenLED, HIGH); digitalWrite(greenLED, HIGH);
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void Press() { void Press() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
delay(100); delay(100);
@ -364,7 +376,6 @@ void Press() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void unPress() { void unPress() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
delay(100); delay(100);
@ -399,7 +410,6 @@ void unPress() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void Pump() { void Pump() {
digitalWrite(greenLED, LOW); digitalWrite(greenLED, LOW);
delay(100); delay(100);
@ -416,17 +426,15 @@ void Pump() {
} }
//_____________________________________________________________________________ //_____________________________________________________________________________
void makeCoffee() { void makeCoffee() {
// code to make coffee goes here... // code to make coffee goes here...
// It would be much smarter to break down complicated functions into subroutines: press/unpress etc... // It would be much smarter to break down complicated functions into subroutines: press/unpress etc...
// Hence that's what we'll have done by the time the first release goes public ;) // Hence that's what we'll have done by the time the first release goes public ;)
// makeCoffee() can still run all the same, but clean() can use the same press/unpress code! // makeCoffee() can still run all the same, but clean() can use the same press/unpress code!
// care must be taken to place these functions earlier in the code, or the compiler will rightfully freak out // care must be taken to place these functions earlier in the code, or the compiler will rightfully freak out
while (true) { while (true) {
desiredTemp = 75;
desiredTemp = 85;
Heat(); // First we pre-heat the boiler Heat(); // First we pre-heat the boiler
if (unrecoverableErr == 1) { if (unrecoverableErr == 1) {
break; break;
@ -479,19 +487,18 @@ void makeCoffee() {
delay(1000); delay(1000);
Press(); // Self explainatory Press(); // Self explainatory
if (unrecoverableErr == 1) { if (unrecoverableErr == 1) {
break; break;
} }
desiredTemp = 85;
desiredTemp = 95;
Heat(); // First we pre-heat the boiler Heat(); // First we pre-heat the boiler
if (unrecoverableErr == 1) { if (unrecoverableErr == 1) {
break; break;
} }
if (dry == 0) { if (dry == 0) {
digitalWrite(boilerPin, HIGH);
//digitalWrite(boilerPin, HIGH);
delay(100); delay(100);
Pump(); // Pump ratio (in seconds) will be read from serial input in final release Pump(); // Pump ratio (in seconds) will be read from serial input in final release
digitalWrite(boilerPin, LOW); digitalWrite(boilerPin, LOW);
@ -499,7 +506,6 @@ void makeCoffee() {
delay(3000); // Allow pressure to wane delay(3000); // Allow pressure to wane
unPress(); // unpressing the press to reset the machine unPress(); // unpressing the press to reset the machine
if (unrecoverableErr == 1) { if (unrecoverableErr == 1) {
break; break;
} }


+ 479
- 468
PyCoffeeNano/PyCoffeeNano.ino.eightanaloginputs.hex
File diff suppressed because it is too large
View File


+ 478
- 468
PyCoffeeNano/PyCoffeeNano.ino.with_bootloader.eightanaloginputs.hex
File diff suppressed because it is too large
View File


Loading…
Cancel
Save