Stuck in a loop - maybe forever

Hi All;
Thank you in advance for your help, and since it's my first post, hope I did it right.
My project wants to watch the temperature of three coolers. A milk container, a freezer, and a refrigerator.
There is an RGB LED. Normally, the led will be blue for normal temperatures, change to green as temperature rises, and a midpoint is reached, and switch to red if the temperature goes over limit. The temperatures will also be displayed on an OLED.
And that's all working just fine.
So here's the problem; I want to display the elapsed time the over-temperature began and ended - that part's also kind of working. However, if the temperature falls back to normal, and later rises again to the over temperature limit, the elapsed timer starts from millis() now, and does not add time to the previous reading, so I never get to see the real elapsed time.
While reviewing my code you will see the attempts I've made, and failed at, and now I'm also beginning to wonder if temperatures are the correct element to use for my decision making since they can be missed during testing.
Really appreciate your ideas

Arduino_forum_help_request.ino (11.4 KB)

I didn't read your sketch. I'm just going to comment that measuring cumulative elapsed time requires the use of some arbitrary fixed time interval. Suppose it's seconds. This should be quite simple. Each second, increment a counter if the test condition is true at that moment, otherwise don't. I don't know if you did it that way, but it is hard to imagine how that approach could become complicated.

that part's also kind of working. However, if the temperature falls back to normal, and later rises again to the over temperature limit, the elapsed timer starts from millis() now, and does not add time to the previous reading

i think you should use a counter to measure how many times temprature is rising from normal to not normal . this way you can do this

if (counter is changed )
 do not start millis from start

karaposu:
i think you should use a counter to measure how many times temprature is rising from normal to not normal . this way you can do this

If the application is to guard against food spoilage, for example, that would not be very useful. "My sandwich became too warm 23 times" vs. "my sandwich was too warm for a total of 3.5 hours". Which metric is more useful?

Thanks all.
Yes, it's about food spoilage. I work in a retirement center. We've already had to throw away food because a refrigerator compressor failed during the night, and nobody knew for how long. I'm volunteering my time and the equipment to try and prevent it from happening again. I'm sure I can do the rest but just can't figure a way out of the clock resetting problem.

It looks like you have tried quite a few things. Good for you. The one that would work easiest for me would be elapsedTime. You just need to make sure you calculate the elapsed time correctly.

Elapsed time is always going to be the difference between two time stamps. But it looks like what you want is the total elapsed time, which is going to be the sum of all the elapsed times that the temperature was too high. Furthermore, you want to display the total elapsed time up to now, regardless of the current temperature. Which means you have to calculate the total elapsed time while it still being increased. There are a couple of ways to do this, but I recommend the following: This is a loose algorithm. Adjust it to make it work.

boolean tempWasTooHigh = false;

unsigned long timeStamp;
unsigned long now;
unsigned long elapsedTime;
unsigned long totalElapsedTime = 0L;

void loop()
{
  if (tempWasTooHigh)
  {
    now = millis();
    elapsedTime = now - timeStamp;
    totalElapsedTime += elapsedTime;
    timeStamp = now;
  }

  ds18process();     // Get the current temp
  FreezeTemp=tempraw[1]/16.0*1.8+32.0;  // Convert raw to F
  if (FreezeTemp < 76)  // or whatever the threshold is
  {
    tempWasTooHigh = false;
    // deal with LEDs here.
  }
  else
  {
    if (tempWasTooHigh == false)
      timeStamp = millis();
    tempWasTooHigh = true;
    // deal with LEDs here.
  }
  DisplayResult();
}

Notice that once you have calculated the elapsed time and added it to the total elapsed time, you reset the time stamp. You don't have to keep the old time stamp around, because you have already dealt with that time and calculated whether the temp was too high or not for that interval.

In your DisplayResult() function, just display the totalElapsedTime. Don't mess with the time stamps there because they have already been handled.

You will need to add additional variables to handle the other two freezers, of course, and figure out how to display them on the displays.

Two other things you should be aware of -- part of this statement is useless:

  if(FreezeTemp <=70 || FreezeTemp < 76){digitalWrite (BlueFreeze, LOW);}
  else if (FreezeTemp >76){digitalWrite (BlueFreeze, HIGH);}             //At the high(Blue) limit Blue LED = OFF

The || operator is a logical OR operator. You can be assured that any time FreezeTemp is <= 70, it is also < 76, so the first part of that conditional is redundant.

What happens if FreezeTemp is exactly 76? It will fail both conditionals and do nothing.

Thanks, and thanks, going to try your suggestions ASAP and I will report back

[

Jimmus:
It looks like you have tried quite a few things. Good for you. The one that would work easiest for me would be elapsedTime. You just need to make sure you calculate the elapsed time correctly.

Elapsed time is always going to be the difference between two time stamps. But it looks like what you want is the total elapsed time, which is going to be the sum of all the elapsed times that the temperature was too high. Furthermore, you want to display the total elapsed time up to now, regardless of the current temperature. Which means you have to calculate the total elapsed time while it still being increased. There are a couple of ways to do this, but I recommend the following: This is a loose algorithm. Adjust it to make it work.

boolean tempWasTooHigh = false;

unsigned long timeStamp;
unsigned long now;
unsigned long elapsedTime;
unsigned long totalElapsedTime = 0L;

void loop()
{
  if (tempWasTooHigh)
  {
    now = millis();
    elapsedTime = now - timeStamp;
    totalElapsedTime += elapsedTime;
    timeStamp = now;
  }

ds18process();    // Get the current temp
  FreezeTemp=tempraw[1]/16.0*1.8+32.0;  // Convert raw to F
  if (FreezeTemp < 76)  // or whatever the threshold is
  {
    tempWasTooHigh = false;
    // deal with LEDs here.
  }
  else
  {
    if (tempWasTooHigh == false)
      timeStamp = millis();
    tempWasTooHigh = true;
    // deal with LEDs here.
  }
  DisplayResult();
}




Notice that once you have calculated the elapsed time and added it to the total elapsed time, you reset the time stamp. You don't have to keep the old time stamp around, because you have already dealt with that time and calculated whether the temp was too high or not for that interval.

In your DisplayResult() function, just display the totalElapsedTime. Don't mess with the time stamps there because they have already been handled.

You will need to add additional variables to handle the other two freezers, of course, and figure out how to display them on the displays.

Two other things you should be aware of -- part of this statement is useless:


if(FreezeTemp <=70 || FreezeTemp < 76){digitalWrite (BlueFreeze, LOW);}
  else if (FreezeTemp >76){digitalWrite (BlueFreeze, HIGH);}            //At the high(Blue) limit Blue LED = OFF



The || operator is a logical OR operator. You can be assured that any time FreezeTemp is <= 70, it is also < 76, so the first part of that conditional is redundant.

What happens if FreezeTemp is exactly 76? It will fail both conditionals and do nothing.

You are certainly correct about the useless code, it's what happens when you bang your head on the table too many times

it's what happens when you bang your head on the table too many times

You gotta knock that off. Wouldn't want you to break the table!

Jimmus:
I think you've got it, or at least very close. I wasn't going to work on it tonight, but tried your code. with a couple of very minor tweaks, it seems to have worked. I think the best part is I've also learned a new piece of the puzzle. Never even thought to use += compound add.
Oh, and I took out "useless code"
Thanks