Analog sampling at time instances and calculate slope of temperature

Hello I've been having a lot of trouble with something that i'm very sure will prove quite simple for most of the experts here.

I want to calculate the slope of a variable (temperature) to see how quickly temperature is changing and make a fan react accordingly.
I wanted to sample the the temperature at two separate instances in time then calculate the slope Delta temp/Delta time. With minimal impact on the speed of the program i.e. minimal delays.
here is what I have so far and it doesn't work :). your help is greatly appreciated.

unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
    float temp1 = temperatureC;  }
    
      if (currentMillis - previousMillis > interval2){
      float temp2 = temperatureC;
      unsigned int tempfinal = (temp2 - temp1)/(interval2 + interval);
      
        if(tempfinal >= 0.6) 
        speedCommand = 80;
      previousMillis = currentMillis; }
  unsigned int tempfinal = (temp2 - temp1) / (interval2 + interval);

You probably should subtract the intervals here, not add.

Where does temperatureC get updated? You code doesn't seem to acquire a new value from the sensor.

Thanks for the quick response MorganS.
your right that + is a typo after much frustration it was a - one point. Below is the tab of the code. hopefully enough to give you a better idea. It runs in the main Void loop.
I find that once I start reading the temperatureC value it continually updates the same in temp1 & 2. i.e. its not a snapshot at two different times giving me two values to calculate. ie example 23.1C-23.1C/ 3000mills-1000mills = 0.

Hope that make sense.

 void temp() {
//getting the voltage reading from the temperature sensor
 int reading = analogRead(sensorPin);  
 
 float voltage = reading * 5.0;
 voltage /= 1024.0; 
 // now convert to Fahrenheight
  float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((volatge - 500mV) times 100)
 float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 
 if (temperatureC  > 22){ 
digitalWrite (fanon, HIGH);}// turn on TIP122 fan at 750RPM (low)
else {digitalWrite (fanon, LOW);}


 
 unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
    float temp1 = temperatureC;  }
    
      if (currentMillis - previousMillis > interval2){
      float temp2 = temperatureC;
      unsigned int tempfinal = (temp2 - temp1)/(interval2 - interval);
      
        if(tempfinal >= 0.6) 
        speedCommand = 80;
      previousMillis = currentMillis; }
   
    float Constrainedtemp = constrain(temperatureC, 23, 27);
    speedCommand = map(Constrainedtemp,23,27,0,80);// Map the constraint temp to the speed  0 -80 or 0- 100 percent
   
  
  OCR2B = speedCommand; // set the PWM out to the mapped value or 80 max 
  


 delay(10);    
 }

With minimal impact on the speed of the program i.e. minimal delays.

How often and how quick does changing a fan speed need to happen ? Seconds ? Tenths of a second ? Milliseconds ?

There is no point obsessing over whether you can change the speed of a fan 200 or 500 times each second, if it actually takes about 3 second to change.

You also don't want to waste your time over-reacting to every random tenth of a degree fluctuation in the sensor output, unless it is a very precise process you are trying to control, and you have a very precise and stable sensor to match.

You are probably better off looking at this problem using words like "trend estimate", "filtering" and "feedback control", than trying to "calculate the slope", which is not really going to be relevant.

To calculate the time for the denominator of your deltaTemp / deltaTime calculation of the "slope", I'd suggest using the actual time that you got the readings.

Suppose your interval is 100 milliseconds and your interval2 is 200 milliseconds.

If your code is "doing other things" as well as this, then it might not actually get temp1 and temp2 at exactly those times.

If you capture temp1 after 101 milliseconds and temp2 after 212 milliseconds, then the denominator ( interval2 - interval1 ) should be (212-101) = 0.111 seconds, not 0.100 seconds.

This would also depend on how your temperature measurements were actually being obtained.

Fair point michinyon,the post naming conventions is important.

Its not so much about doing this really quickly I just found using delays added a real lag, so I tried to get around that.
Anyway, the main thing was I have the fan mapped to the temperature. I wanted if there was a sudden drastic change in the rate of temp change that the fan program left the mapping and went straight to max speed to better control over shoot. Perhaps crude, perhaps over excessive. but I have have to overcome this worth it or not, on a mission now. :wink:

I was thinking more of several seconds in between measurements, as much as 5 to 10s.

A limit to this process will be how rapidly the temperature sensor can respond to changes in the air temperature, so you should investigate that.

I am looking to do the 2 temp samples over 5 to 10 second. The sensor sampling is good during that span.
The issue is much simpler than that and is liking due to my programming skills, or lack thereof.

We can ignore the code I posted if need be. the logic of what I want to do in simple terms is.

  • minimize the use of the delay function if it can be avoided. delaying for 5-10s really bogged the program down.
  • Take a snapshot of temperature at point temp1. then take the temperature at a point ten seconds after that temp2
    -then perform the calculation (temp2-temp1)/(time2-time1) to see slope of the temp and how fast it is changing.

The issue i'm having with my limited coding skills is that. excerpt:

unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
float temp1 = temperatureC; }

///When I run the above: temp1 starts sampling temperatureC continuously (not a static snapshot in time).

///Then when the below portion runs with interval2=10000. after 10s temp2 starts sampling temperatureC continuously and with the same values as temp1. I need both values to be static snapshots for the calculation to work.

if (currentMillis - previousMillis > interval2){
float temp2 = temperatureC;
unsigned int tempfinal = (temp2 - temp1)/(interval2 - interval);

if(tempfinal >= 0.6)
speedCommand = 80;
previousMillis = currentMillis; }

Any direction, help, logic adjustments or examples would be appreciated.

@Navigator_x2, do not cross-post. Other thread removed.

If you're taking two different readings at two different times, wouldn't you have two different variables for the "previousMillis" where the last reading was taken? One for the reading from sensor 1 and one for the reading from sensor 2. It sounds like you need to know how long ago both of those things happened.

Thanks very much for the reply. I think as mills() increment it would show different times at the two different intervals. Also I got the code to capture two different values at at two different instances in time by adding a >interval && <interval to exit the if statement. Still not happy with the results through as
A. the mills() tend to jump and missing the interval constrained in the above and statement.
B. Because of A its not very reliable or accurate.

Need more time to play with it. If anyone has some constructive comments or examples i’m open to anything.

If anyone has some constructive comments or examples i'm open to anything.

Even posting the code you are not happy with?

    unsigned int tempfinal = (temp2 - temp1)/(interval2 - interval);
     
        if(tempfinal >= 0.6)

I think part of your problem is that you are mixing integers with float variables. "tempfinal" should probably be a float in this instance, but to do that temp2, temp1 and the intervals also need to be made into floats so that the divide works as expected.