Timer not shutting down

no i just have it at the same time for testing purposes one is 10 hours and one is 4 hours

It needs ti be chanageble in the loop

Let me try thank you

look this over

# include <LiquidCrystal_I2C.h>
# include <Wire.h>
# include <OneWire.h>
# include <DallasTemperature.h>

LiquidCrystal_I2C lcd (0X27, 20, 4); // Adjust the LCD size to 20x4

#define COOKER  6
#define PROGRAM_PIN 4  // Pin to select program (HIGH: Program 1, LOW: Program 2)
#define bt_set    9
#define bt_up     10
#define bt_down   11
#define bt_start  12

unsigned long currentMillis = 0;

#define DS18B20_PIN 2  // Change this to the actual pin you're using
OneWire oneWire (DS18B20_PIN);
DallasTemperature ds18b20 (&oneWire);

enum ProgramState {
    GOURMET,
    MAGICS
};
ProgramState currentProgram;

// -----------------------------------------------
unsigned int gourmetTime_h = 0; // Set the desired time for Gourmet program
unsigned int gourmetTime_m = 0;
unsigned int gourmetTime_s = 30;

unsigned int magicsTime_h = 0;  // Set the desired time for Magics program
unsigned int magicsTime_m = 1;
unsigned int magicsTime_s = 0;

unsigned long cookTime [] = {
    (((gourmetTime_h * 60) + magicsTime_m * 60) + gourmetTime_s) * 1000,
    (((magicsTime_h  * 60)  + magicsTime_m * 60) + magicsTime_s)  * 1000,
};

// -----------------------------------------------
const float gourmetDesiredTemperature = 96.0;
const float magicsDesiredTemperature = 60.0;
float tempDesired [] = { gourmetDesiredTemperature, magicsDesiredTemperature};

enum { Off, Warming, Cook, Done };
int state;

unsigned long timerStart;

// -----------------------------------------------------------------------------
void loop ()
{
    ds18b20.requestTemperatures ();
    float currentTemperature = ds18b20.getTempCByIndex (0); 

    lcd.setCursor (0, 0);
    lcd.print (currentProgram == GOURMET ? "Gourmet" : "Magics");
    lcd.setCursor (0, 3);
    lcd.print ("Temp: ");
    lcd.print (currentTemperature);
    lcd.print ("C");

    // Display the selected program time
    lcd.setCursor (0, 1);
    lcd.print ("Time:");
    printSelectedProgramTime ();

    unsigned long currentMillis = millis ();

    switch (state) {
    case Warming:
        if (currentTemperature >= tempDesired [currentProgram]) {
            state      = Cook;
            timerStart = currentMillis;
            Serial.println ("Cook");
        }
        break;

    case Cook:
        if (currentMillis - timerStart >= cookTime [currentProgram])  {
            state = Done;
            digitalWrite (COOKER, LOW);
            Serial.println ("Done");
        }

        lcd.setCursor (9, 0);
        if (currentTemperature < tempDesired [currentProgram])  {
            digitalWrite (COOKER, HIGH);
            lcd.print ("Heat");
        }
        else if (currentTemperature > tempDesired [currentProgram])  {
            digitalWrite (COOKER, LOW);
            lcd.print ("Cool");
        }

        lcd.setCursor (0, 2);
        lcd.print ("Remaining:");
        printTime (currentMillis - timerStart);
        break;

    case Off:       // placeholder
    case Done:
    default:
        break;
    }

    delay (1000);       // avoid too many prints
}

// -----------------------------------------------------------------------------
void printTime (unsigned long timeInMillis) {
    unsigned int hours = timeInMillis / 3600000UL;
    unsigned int minutes = (timeInMillis % 3600000UL) / 60000UL;
    unsigned int seconds = (timeInMillis % 60000UL) / 1000UL;

    if (hours < 10) lcd.print("0");
    lcd.print (hours);
    lcd.print (":");
    if (minutes < 10) lcd.print("0");
    lcd.print (minutes);
    lcd.print (":");
    if (seconds < 10) lcd.print("0");
    lcd.print (seconds);
}


void printSelectedProgramTime () {
    unsigned int programHours, programMinutes, programSeconds;

    if (currentProgram == GOURMET) {
        programHours   = gourmetTime_h;
        programMinutes = gourmetTime_m;
        programSeconds = gourmetTime_s;
    } else if (currentProgram == MAGICS) {
        programHours = magicsTime_h;
        programMinutes = magicsTime_m;
        programSeconds = magicsTime_s;
    }

    if (programHours < 10) lcd.print("0");
    lcd.print (programHours);
    lcd.print (":");
    if (programMinutes < 10) lcd.print("0");
    lcd.print (programMinutes);
    lcd.print (":");
    if (programSeconds < 10) lcd.print("0");
    lcd.print (programSeconds);
}


// -----------------------------------------------------------------------------
void setup () {
    // Initialize setup code here
    lcd.init ();
    lcd.backlight ();
    ds18b20.begin ();
    pinMode (bt_set, INPUT_PULLUP);
    pinMode (PROGRAM_PIN, INPUT_PULLUP);
    pinMode (DS18B20_PIN, INPUT_PULLUP);
    pinMode (COOKER, OUTPUT);
    lcd.setCursor (0, 1);

    currentProgram = (ProgramState) digitalRead (PROGRAM_PIN);

    lcd.print ("Welcome To Pasturizer");
    lcd.clear ();  // Clear the screen

    state = Warming;
    digitalWrite (COOKER, HIGH);
}

i have tried this and uploaded it to my arduino, i do like how the timer counts up however it still does not switch the cooker off when the timer is done, it does stoop the timer now

but in saying that i used the setup you did and incorapted it into my program and fixed thank you for the input

Just a guess, you want gourmetTime_m in the first initial value expression.

Those expressions will overflow for times later in the day.

Also, they are just plain wrong. There is a misplaced parenthesis in each expression.

Fixes:

unsigned long gourmetTime_h = 20; // Set the desired time for Gourmet program
unsigned long gourmetTime_m = 0;
unsigned long gourmetTime_s = 30;

unsigned long magicsTime_h = 18;  // Set the desired time for Magics program
unsigned long magicsTime_m = 1;
unsigned long magicsTime_s = 0;

unsigned long cookTime [] = {
    (((gourmetTime_h * 60) + gourmetTime_m) * 60 + gourmetTime_s) * 1000,
    (((magicsTime_h  * 60) + magicsTime_m) * 60 + magicsTime_s)  * 1000,
};

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

  Serial.println(cookTime[0]);
  Serial.println(cookTime[1]);
}

void loop(){}

HTH

a7

did you see the "Done" on the serial monitor console?

It did not

then how do you know the timer stopped?

do you see how the code starts in the "Warming" state until it reaches the desired temp and then captures a time stamp and enters the "Cook" state

in the Cook state, it toggles the "COOKER" on/off to maintain the desired temp and waits for the specified time since timerStart to expire. when it does, it turns off the COOKER and enters the "Done" state

isn't this what you want to happen?

The timer on the display stops at the desired time but the cooker does not stop heating, i did see how you have written the code and it is very clearly done

No it does not enter the done state

i'm guessing you mean that you stop seeing the "Remaining:" time stop changing

are you looking for "Done" on the serial monitor or the LCD?

i see that the code that turns off the COOKER is before the simple controller code that turns on/off the COOKER depending on temperature. it can turn the COOKER back on. the simple fix is to move the code under the Cook case when state = Done that turns the COOKER off to under the Off/Done/default case

the Remaining time is counting up rather than down. it should be

        printTime (timerStart - currentMillis);

it is counting up which i like but it gets to the specified number and stops but the cooker remains on

i doubble checked now and the serial monitor was not enabled. i did enable it now and it is showing done but is not switching off the relay
but also if i change the time to so\ay 4 hours it only counts 1 minute then stops

did you implement this change?

did you make the corrections posted by @alto777 ?

I did yes, but will continue to play tomorrow thanks guys

Was the original code, at least in part, composed by ChatGPT ?
The way the thread has developed and the interactions by the OP seem to imply that the OP was not the original author.

This was my original code i did ot use chargpt at all

Doesn't work well. Those are going to be huge numbers. Like weeks.

To get a count down I used a finishTime set when the Cook state is entered, then display with

    if (finishTime >= currentMillis)
      printTime (finishTime - currentMillis);

I see it count down to zero, announce done and I print that it passed on turning off the cooker and then I do turn off the cooker in the Off/Done area.

The bang-bang on the heater was brutal so I added a bit of hysteresis I can never pass up an opportunity.

a7