Need some help with a timer

I’m having trouble with a timer. I’m making a brewing system and I’m heating up water until it gets to a temp and then keeping it there for an amount of time and then heating up to a different temp.

Below is my code. The problem I’m having is that it seems once I hit the target temperature the time that is being recorded is continually looping so it keeps updating the timer… So when I do the start time minus the time that it hit the correct temperature is the same over and over.

Thanks for any help

#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

//User Inputs:
//MASH TEMP
const int MASHTEMP = 82; // Desired Mash Temp(deg F)
//MASH TIME
const int MASHTIME = 10000; //Desired Mash Time(milli sec.)
//BOIL TIME
const int BOILTIME = 10000; //Desired Boil Time(milli sec.)

boolean MashTimer = false; //used for MASH TIME
long MashStartTime; //used for MASH TIME
boolean BoilTimer = false; //used for BOIL TIME
long BoilStartTime; //used for BOIL TIME
int MASHTANKTEMP;
long startTime;//begins timer

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
const int heater = 12;

void setup(void) {
 Serial.begin(9600);
 pinMode(heater,OUTPUT);
}

void loop(void) {
startTime = millis();
 
 byte i;
 byte present = 0;
 byte type_s;
 byte data[12];
 byte addr[8];
 float celsius, fahrenheit, currentMashTemp;
 
 if ( !ds.search(addr)) {
   Serial.println(" ");
   Serial.println();
   ds.reset_search();
   delay(250);
   return;
 }
 
 Serial.print("ROM =");
 for( i = 0; i < 8; i++) {
   Serial.write(' ');
   Serial.print(addr[i], HEX);
 }

 if (OneWire::crc8(addr, 7) != addr[7]) {
     Serial.println("CRC is not valid!");
     return;
 }
 Serial.println();

 // the first ROM byte indicates which chip
 switch (addr[0]) {
   case 0x10:
     Serial.println("  Chip = DS18S20");  // or old DS1820
     type_s = 1;
     break;
   case 0x28:
     Serial.println("  Chip = DS18B20");
     type_s = 0;
     break;
   case 0x22:
     Serial.println("  Chip = DS1822");
     type_s = 0;
     break;
   default:
     Serial.println("Device is not a DS18x20 family device.");
     return;
 } 

 ds.reset();
 ds.select(addr);
 ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
 delay(1000);     // maybe 750ms is enough, maybe not
 // we might do a ds.depower() here, but the reset will take care of it.
 
 present = ds.reset();
 ds.select(addr);    
 ds.write(0xBE);         // Read Scratchpad

 Serial.print("  Data = ");
 Serial.print(present, HEX);
 Serial.print(" ");
 for ( i = 0; i < 9; i++) {           // we need 9 bytes
   data[i] = ds.read();
   Serial.print(data[i], HEX);
   Serial.print(" ");
 }
 Serial.print(" CRC=");
 Serial.print(OneWire::crc8(data, 8), HEX);
 Serial.println();

 // Convert the data to actual temperature
 // because the result is a 16 bit signed integer, it should
 // be stored to an "int16_t" type, which is always 16 bits
 // even when compiled on a 32 bit processor.
 int16_t raw = (data[1] << 8) | data[0];
 if (type_s) {
   raw = raw << 3; // 9 bit resolution default
   if (data[7] == 0x10) {
     // "count remain" gives full 12 bit resolution
     raw = (raw & 0xFFF0) + 12 - data[6];
   }
 } else {
   byte cfg = (data[4] & 0x60);
   // at lower res, the low bits are undefined, so let's zero them
   if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
   else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
   else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
   //// default is 12 bit resolution, 750 ms conversion time
 }
 celsius = (float)raw / 16.0;
 fahrenheit = celsius * 1.8 + 32.0;
 MASHTANKTEMP = fahrenheit;
 Serial.print(" MASHTANKTEMP ");
Serial.print( MASHTANKTEMP );
 Serial.print("   startTime"   );
Serial.print(startTime);
  
;
if (MASHTANKTEMP < MASHTEMP && MashTimer < MASHTIME) { // Heat on before and during mash
digitalWrite (heater,HIGH);

 }
 

   if (MASHTANKTEMP > MASHTEMP && MashTimer < MASHTIME) { // heat off during mashing
digitalWrite (heater,LOW);
 }
 

 if(MASHTANKTEMP >= (MASHTEMP - 2.0) && MASHTANKTEMP <= (MASHTEMP + 2.0) && MashTimer < MASHTIME){ // starts timer for mash
   MashTimer = true; 
 }  
 
 if (MashTimer){ 
   MashStartTime = millis(); // starts mash timer   
   
   //Test to see if timer is working correctly:
   Serial.print("  MashStartTime  ");
   Serial.print(MashStartTime);
   Serial.print("time elapsed");
   Serial.print(startTime - MashStartTime);
   
 }
    
  if ((startTime-MashStartTime) >= MASHTIME && BoilTimer == false){ //mash is complete and before boil timer starts turns on heat
digitalWrite(heater,HIGH);

    }
    
// THE FOLLOWING CONTINUES AND CONTROLS THE BOIL PROCESS (PROCESS #3)
      
 if ((startTime-MashStartTime) > MASHTIME && MASHTANKTEMP >= 85 && MASHTANKTEMP <= 95){ 
   // Triggers after mash time is complete and once temp range is reached. 
   BoilTimer == true; //SHOULD only trigger the FIRST time this condition is met, not each time

 }
 if (BoilTimer){ ////Starts the Boil Timer if condition above is met (Boil Temp is reached, boolean Boil Timer = true)
    BoilStartTime = millis();
 }
 
 if ((startTime-BoilStartTime) >= BOILTIME && BoilTimer == true){ //Greater than or equal to ensures that you will hit and trigger this function
digitalWrite(heater,LOW);
   }

}

Here is what I’m getting when I’m receiving the temps and times from my arduino.

ROM = 28 D1 5E B6 6 0 0 93
Chip = DS18B20
Data = 1 67 2 4B 46 7F FF 9 10 7C CRC=7C
MASHTANKTEMP 101 startTime49548 MashStartTime 50592time elapsed-1044

ROM = 28 D1 5E B6 6 0 0 93
Chip = DS18B20
Data = 1 5F 2 4B 46 7F FF 1 10 DC CRC=DC
MASHTANKTEMP 100 startTime50887 MashStartTime 51932time elapsed-1045

ROM = 28 D1 5E B6 6 0 0 93
Chip = DS18B20
Data = 1 56 2 4B 46 7F FF A 10 96 CRC=96
MASHTANKTEMP 99 startTime52228 MashStartTime 53271time elapsed-1043

ROM = 28 D1 5E B6 6 0 0 93
Chip = DS18B20
Data = 1 4E 2 4B 46 7F FF 2 10 9E CRC=9E
MASHTANKTEMP 98 startTime53567 MashStartTime 54610time elapsed-1043

You have posted code without using code tags. This creates certain problems and obstacles for other forum members. The code tags make the code look

like this

when posting source code files. It makes it easier to read, and can be copied with a single mouse click.
If you have already posted without using code tags, open your message and select “modify” from the pull down menu labelled, “More”, at the lower left corner of the message. Before posting the code, use Ctrl-T in the IDE to reformat the code in a standard format, which makes it easier for us to read. Highlight your code by selecting it (it turns blue), and then click on the “</>” icon at the upper left hand corner. Click on the “Save” button. Code tags can also be inserted manually in the forum text using the [code] and [/code] metatags.

When you are finished that, please read this post:

How to use this forum - please read.

When you set MashTimer to true, that is when you should start the timer. When it istrue, don't update the start time.

Any ideas on how I would go about doing that?

zanolazc:
Any ideas on how I would go about doing that?

void loop(void) {
startTime = millis();

If you gave this variable a name that indicated what it really contains, it would be called loopStartTime, and, as you can see, is, therefore, useless.

If you are to keep this name, you need to stop resetting it on every pass through loop().

If you put the code to get the temperature in a function, it would be a lot easier to see where this statement should be.

void loop()
{
    int mashTemp = getMashTemperature();
    if(mashTemp > MashWarmEnough)
    {
        holdMashAtTemp = true;
        startTime = millis();
    }

    if(holdMashAtTemp)
    {
       if(millis() - startTime < timeToHoldMashAtThisTemp)
       {
          // do whatever needs doing to hold the mash at this temp
       }
    }
}

I’m betting that you can guess exactly what each variable and function needs to do.