First project almost complete; RunningAverage not averaging

The goal here is a bath water temperature alarm that buzzes when my water gets to the perfect temp (note, in the code below, the tempset is set for 90 so I can test code with monitor at dining room table without needing 114F water).

I’ve pasted here two sets of code. The first one “A” isn’t averaging the temps any more and when I look at the serial Monitor, it shows the same temperature continuously. It never changes. The buzzer just buzzes at its interval, but the program isn’t really monitoring my temperature any more; meaning when the temp goes above tempset it doesn’t turn off. And if the program begins with the thermocouple already reading above tempset, the buzzer doesn’t start when the temperature goes below. It’s stuck somewhere.

The second code “B” has a delay (which I’m trying to get rid of in “A”) in it and this one works fine; that is, it’s averaging and displaying the changing temps on the Monitor and the buzzer is buzzing when it’s supposed to.

I’m really stumped about how to get rid of that delay. I understand the Blind_without_delay principle and have applied to the buzzer, but why is it messing up the program now?

A

// code for bath water temperature alarm. 

//include Max6675 library
#include "max6675.h"

//include RunningAverage library
#include "RunningAverage.h"


//Constants won't change

const int tempset = 90; //temp alarm setpoint
const int buzzerPin = 9; //buzzer pin

const int thermoDO = 4; //these are for MAX6675
const int thermoCS = 5;
const int thermoCLK = 6;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const int vccPin = 3;
const int gndPin = 2;


//Variables will change:
int buzzerState = LOW;    //buzzerState used to set the buzzer

unsigned long previousMillis = 0;  // will store last time buzzer was updated
unsigned long previousMillis_Serial = 0;  // will store last time sent to Serial Monitor

unsigned long interval = 750;    // interval at which to buzz buzzer (milliseconds) for primary alarm
unsigned long interval_Serial = 1000;    // interval at which to send to Serial Monitor

RunningAverage myRA(20); //Running Average



void setup() {

  Serial.begin(9600);
  myRA.clr(); // explicitly start clean

  // use Arduino pins
  pinMode(buzzerPin, OUTPUT);      
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  
  // wait for MAX chip to stabilize
  delay(500);
}


void loop() {

   myRA.add(thermocouple.readFarenheit());
   
   unsigned long currentMillis = millis(); 
  
   if(currentMillis - previousMillis_Serial > interval_Serial) {
    
      // save the last send to Serial 
      previousMillis_Serial = currentMillis;   
   
      Serial.print("Running Average F = ");
      Serial.println(myRA.avg());
       
      } 
   

 
//check average temp versus tempset and buzz alarm if so

   if (myRA.avg() < tempset){

 
      if(currentMillis - previousMillis > interval) {
    
        // save the last time buzzed buzzer 
        previousMillis = currentMillis;   

         // if the buzzer is off turn it on and vice-versa:
         if (buzzerState == LOW)
           buzzerState = HIGH;
         else
            buzzerState = LOW;

      // set the buzzer with the buzzerState of the variable:
      digitalWrite(buzzerPin, buzzerState);
      }
    
   }
   else
        buzzerState = LOW;
  
 
}

B

// code for bath water temperature alarm. 

//include Max6675 library
#include "max6675.h"

//include RunningAverage library
#include "RunningAverage.h"


//Constants won't change

const int tempset = 90; //temp alarm setpoint
const int buzzerPin = 9; //buzzer pin

const int thermoDO = 4; //these are for MAX6675
const int thermoCS = 5;
const int thermoCLK = 6;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const int vccPin = 3;
const int gndPin = 2;


//Variables will change:
int buzzerState = LOW;    //buzzerState used to set the buzzer

unsigned long previousMillis = 0;  // will store last time buzzer was updated

unsigned long interval = 1000;    // interval at which to buzz buzzer (milliseconds) for primary alarm

RunningAverage myRA(20); //Running Average




void setup() {

  Serial.begin(9600);
  myRA.clr(); // explicitly start clean

  // use Arduino pins
  pinMode(buzzerPin, OUTPUT);      
  pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);
  
  // wait for MAX chip to stabilize
  delay(500);
}


void loop() {

   myRA.add(thermocouple.readFarenheit());

  
   Serial.print("Running Average F = ");
   Serial.println(myRA.avg());

   delay(1000);
 

 
//check agerage temp versus tempset and buzz alarm if so

   if (myRA.avg() < tempset){
       unsigned long currentMillis = millis();
 
      if(currentMillis - previousMillis > interval) {
    
        // save the last time buzzed buzzer 
        previousMillis = currentMillis;   

         // if the buzzer is off turn it on and vice-versa:
         if (buzzerState == LOW)
           buzzerState = HIGH;
         else
            buzzerState = LOW;

      // set the buzzer with the buzzerState of the variable:
      digitalWrite(buzzerPin, buzzerState);
      }
    
   }
   else
        buzzerState = LOW;
        digitalWrite(buzzerPin, buzzerState);
 
}

Not having a max6675 I looked at the code B and removed the delay && I changed the temperature test . For the rest it looks OK

give it a try,

// code for bath water temperature alarm. 

//include Max6675 library
#include "max6675.h"

//include RunningAverage library
#include "RunningAverage.h"


//Constants won't change

const int tempset = 90; //temp alarm setpoint
const int buzzerPin = 9; //buzzer pin

const int thermoDO = 4; //these are for MAX6675
const int thermoCS = 5;
const int thermoCLK = 6;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

const int vccPin = 3;
const int gndPin = 2;


//Variables will change:
int buzzerState = LOW;              // buzzerState used to set the buzzer
unsigned long previousMillis = 0;   // will store last time buzzer was updated
unsigned long interval = 1000;      // interval at which to buzz buzzer (milliseconds) for primary alarm

RunningAverage myRA(20);            // Running Average

unsigned long lastDisplay = 0;
#define DISPLAYTIMEOUT 500

void setup() 
{
  Serial.begin(9600);
  myRA.clr(); // explicitly start clean

  // use Arduino pins
  pinMode(buzzerPin, OUTPUT);      
  pinMode(vccPin, OUTPUT); 
  digitalWrite(vccPin, HIGH);
  pinMode(gndPin, OUTPUT); 
  digitalWrite(gndPin, LOW);

  // wait for MAX chip to stabilize
  delay(500);
}

void loop() 
{
  // MAKE MEASUREMENT
  myRA.add(thermocouple.readFarenheit());

  // DISPLAY IT
  if (millis() - lastDisplay > DISPLAYTIMEOUT)
  {
    Serial.print("Running Average F = ");
    Serial.println(myRA.avg());
    lastDisplay = millis();
  }

  // CHECK IT 
  //check average temp versus tempset and buzz alarm if so
  if (myRA.avg() < tempset)
  {
    buzzerState = LOW;
  }
  else
  {
    if(millis() - previousMillis > interval) 
    {
      // save the last time buzzed buzzer 
      previousMillis = millis();   
      
      // if the buzzer is off turn it on and vice-versa:
      if (buzzerState == LOW)
        buzzerState = HIGH;
      else
        buzzerState = LOW;
    }
  }
  digitalWrite(buzzerPin, buzzerState);
}

Hey Rob,

Thanks for the help. But it's still doing the same thing. Oh, and you reversed the conditions when checking the temperature - I actually want it to come on when the average temperature is BELOW the temp set.

Anyhow, I'm really stumped here.

It seems to be getting stuck in the display or something, it only reads the temperature when I open the monitor. For example, if I upload the program and start, it buzzes as expected, but when I open the monitor, it reads a static temperature - if I put the thermocouple in my mouth to raise its temp, no changes are shown in the monitor. However, if I then close the monitor window, it instantly stops buzzing, and when I open monitor again, it shows the temperature in my mouth - but again, if I then remove the thermocouple, there is not changed shown.

I'm completely lost now.

any ideas?

EJ

However, if I then close the monitor window, it instantly stops buzzing, and when I open monitor again, it shows the temperature in my mouth

Opening and closing the monitor will reset the Arduiono, so it seems tha what you are seeing is the temp reading working once after reset and never again.


Rob

Looking at the code I’d say that once the temp is over the threshold and you turn the buzzer on you are constantly resetting previousMillis so the

if(millis() - previousMillis > interval)

test is always true and the buzzer will never turn off. Try this

if(millis() - previousMillis > interval)
{

// if the buzzer is off turn it on and vice-versa:
if (buzzerState == LOW) {
previousMillis = millis(); // only reset previousMillis if the buzzer is not already on
buzzerState = HIGH;
} else
buzzerState = LOW;
}
}


Rob