Trigger event if a value stays the same for x amount of time

Hi guys, I am working on a project which takes a temperature reading every 500ms from sensor A.
Sensor B measures ambient temperature every 1000ms (both use millis, not delays :slight_smile: )

Sensor A will be used for measuring purposes, so I would like to trigger an event (some haptics for example) when the measured value settles after the sensor is inserted into the medium.

The medium being measured will always be warmer than ambient temperature, I would simply use the ambient temp as reference, so that the value of sensor A has to be more than the value of sensor B for the trigger to take place. Its a K-type sensor, so it reacts quickly.

Therefore I would like to trigger the feedback event if the value of sensor A is more than sensor B, and remains the same, lets say +/- 2°c or so, for either x amount of time or x amount of readings (I think a few seconds, or 6 or so readings should be fine).

What would be the best way to approach this?

Thanks

for the time condition, capture the time, millis(), when there is a change. that condition is met when the time since that capture exceeds you requirement.

@gcjr do you mean something like this?

Unsigned long currentMillis;
unsigned long startMillis
uint16_t triggermillis = 2500;
uint8_t tempA;
uint8_t tempAcompare;
unit8_t tempB

void setup (){
startMillis = millis();
}

void loop (){
//other code 
//...//

if (tempA >= tempB +2){ //Code only runs if probe temp is a few degrees above ambient
if (tempA != tempAcompare){//reset if temperature comparison is not same
tempA = tempAcompare;
startMillis = currentMillis;
}
If (tempA == tempAcompare){
if (currentMillis-startMillis >= triggerMillis){
//if value is the same after 2.5seconds trigger event
triggerEvent();
//reset timer
startMillis = currentMillis;
}
}
}

How could I build in a tolerance, that the event trigger will still occur if there is some small fluctuation of say +/- 2 degrees or so?

mickymik:
@gcjr do you mean something like this?

yes
except you have the test for the stable conditions inside the test for > 2.
and shouldn't your test for a change in temp be an absolute

if (ABS(temp - tempLst) > 2)

and the else condition consider the time?

Yeah you’re right, looks good. Thanks!

gcjr:
and the else condition consider the time?

can you explain what you mean exactly? Im not 100% sure what you’re saying.

mickymik:
can you explain what you mean exactly? Im not 100% sure what you’re saying.

sorry, i misunderstood the purpose of the >2 test, that you only want to do anything if the temp is above a threshold.

and the two other if conditions do what i was suggesting. but i believe the following code is clearer

   if (tempA < (tempB +2)
        return;

    if (tempA != tempAcompare){//reset if temperature comparison is not same
        tempA = tempAcompare;
        startMillis = currentMillis;
    }

    else if (currentMillis-startMillis >= triggerMillis){
        //if value is the same after 2.5seconds trigger event
        triggerEvent();
        //reset timer
        startMillis = currentMillis;
    }

in the above, do you want triggerEvent () to repeat periodically if the temperature remains unchanged?

The simple way to do something when a value has been consistent for a period is like this pseudo code (the logic may appear backwards).

if (condition is not met) {
   lastTimeConditionWasWrong = millis();
}

if (millis() - lastTimeConditionWasWrong >= interval) {
  // condition has been correct throughout the interval
  // so do something.
}

…R

@gcjr I see. At the moment I am undecided if I want the event to a) repeat continually, or b) only run once, and then reset if once the temperature comaprison no longer matches. I guess it would be nice to test both and see which one I like more.

To put things into context I will briefly explain the project:
Its a tyre pyrometer used for measuing tyre temperature with a k-type thermocouple probe. In the device I have also added haptics. I would like the device to vibrate once the probe has reached the teperature of the tire, to signal that the reading can be saved. (The same code may be used for an autosave function in the future). I figure if the temperature remains stable for a given time period then I can assume I have an accurate representation of the tire temperature. The amout of time needed for the trigger, and the tolerance for fluctiations can be figured out with some trial and error. To avoid triggering the event when the probe has cooled down to a stable temperature, I will only allow the event to be triggered if the temperature is more than ambient temperature.

to put it simply, I need both conditions to be met to trigger the event.

  1. tempA must be at least 2 degrees higher than tempB.
  2. the value from tempA must not fluctiate more than x degrees during a given time frame.

Did you have something in mind regarding adding a boolean? I'd be interested to see your solution. I already see some differences in your example, I think it'd be nice to see you you would approach the second variation, I could possibly learn something new, or think about the problem in another way.

@Robin2, thanks for the reply, my diffuculty was more regarding adding some tolerance for the fluctuations, which grjc answerd with this:

if (ABS(temp - tempLst) > 2)

Nonetheless I appreciate your reply. I like seeing how others solve problems, as there are often more than one way :slight_smile:

mickymik:
@Robin2, thanks for the reply, my diffuculty was more regarding adding some tolerance for the fluctuations, which grjc answerd with this:

I had envisaged that "condition is not met" would take account of the tolerance.

...R

This is what I have so far, seems to be working ok. Will need some fine tuning though…
Thoughts?

else if (gslc_GetPageCur(&m_gui) == PG_Temp && pauseTemp == false) {
    if (currentMillis - startMillisA >= 500) {
      GetTemperature();
      gslc_ElemSetTxtStr(&m_gui, tempGauge, tempBuf);
      gslc_ElemXRingGaugeSetVal(&m_gui, tempGauge, gaugeVal);
      startMillisA = currentMillis;

    }
    if ((gaugeVal - ambTemp) > 5) {
      if (abs(lastVal - gaugeVal) > 1) {
        lastVal = gaugeVal;
        startMillisD = currentMillis;
      }
      else if (currentMillis - startMillisD >= 3000) {
        if (abs(lastVal - gaugeVal) < 1) {
          triggerStableHaptic();
          startMillisD = currentMillis;
        }
      }
    }
  }

isn’t the following redundant?

if (abs(lastVal - gaugeVal) < 1) {

since there’s an earlier > test?
or a i missing something?

I figured the tolerance is required in both parts, since the timer is reset in both parts. I don’t want to reset the timer if the value remains within +/- the desired range. Resetting the timer in the second part gives the haptics a short pause if the sensor remains inserted in the medium.
Does it make sense, or did I missunderstand something?

Referring to Reply #9

I think this code

    if ((gaugeVal - ambTemp) > 5) {
        if (abs(lastVal - gaugeVal) > 1) {
            lastVal = gaugeVal;
            startMillisD = currentMillis;
        }
        else if (currentMillis - startMillisD >= 3000) {
            if (abs(lastVal - gaugeVal) < 1) {
                triggerStableHaptic();
                startMillisD = currentMillis;
            }
        }
    }

could be replaced with this

    if ((gaugeVal - ambTemp) > 5) {
        if (abs(lastVal - gaugeVal) > 1) {
            lastVal = gaugeVal;
            startMillisD = currentMillis;
        }
    }
    if (currentMillis - startMillisD >= 3000) {
        triggerStableHaptic();
        startMillisD = currentMillis;
    }

…R

Aha I see, I only need to rely on the timer because if the value doesn’t change the timer won’t be reset.

Thanks!