not looping correctly

Hi. I'm new to the Arduino community and I have limited knowledge of Arduino programming.
I'm currently working on a project that I need to get done asap for work. I wrote a code to record the temperature of a grill (using a temperature sensor) and it triggers certain things (Leds, a fan, a valve, a buzzer) depending on whether the grill temperature is higher or lower than the set temperature which I can set manually using two push buttons for up and down. I'm using a 16 X 2 lcd display to show the grill temp and the set temp. Instead of the delay function, I'm using millis() in order to be able to run different tasks at the same time.
Everything seems to be working as it should but the problem is that my grill temp does not update every 3000ms. If I use the first millis() function for displaying the grill temp at the beginning of the loop to encompass everything under the loop (all the if statements underneath) than the grill temp gets updated but makes everything update every 3000ms which is not ideal.
Can you please help me sort this out? Thank you.

Code attached.

FINAL_GRILL_CODE.ino (4.19 KB)

  • ensure all timing elements are unsigned long

  • don't write  if (millis() > lastlcd + setvaluelcd) {because in ~50 days you'll run in trouble when the addition overflows. Write it this way:  if (millis() - lastlcd > setvaluelcd) {

  • whilst this works, make your conditions clear. Don't write  if (millis() >= lastbutton + setvaluebutton && digitalRead(up) == LOW)and prefer

  if ((millis() -  lastbutton>= setvaluebutton) && (digitalRead(up) == LOW))
  • this sounds really weird    if (millis() > (lastbuzzer * increase)) {

please don't post code as a file attachment when it's small, just post it inline using code tags (read how to use the forum)

I'd expect the temperatures to be displayed as expected every ~3000mS except when you're over temperature and executing all those delays.

What is actually happening?

serial.begin can be moved to setup and it could/should be running at a much higher baud rate.

Usually you would put something like this:

lastlcd = millis();

At the end of the if block, not the beginning.

Thanks for your reply.
I will go ahead and do those modifications, but will this fix the looping problem?

P.S. The "if (millis() > (lastbuzzer * increase)) {" is the only way that I could get the buzzer to stop buzzing and not continue to buzz when the grill temp is stays greater than the set temp.

wildbill:
I'd expect the temperatures to be displayed as expected every ~3000mS except when you're over temperature and executing all those delays.

What is actually happening?

serial.begin can be moved to setup and it could/should be running at a much higher baud rate.

Usually you would put something like this:

lastlcd = millis();

At the end of the if block, not the beginning.

So basically everything works as intended but the grill temp (the temp readout of the sensor) does not update. It stays at one value. It only updates if I restart the whole program again or if I bracket everything that I have under the void loop and assign it a delay using the delay function or the millis().

What does the serial output show you? Do temperatures change there?

wildbill:
What does the serial output show you? Do temperatures change there?

The serial monitor shows the same thing. Same problem.

wildbill:
I'd expect the temperatures to be displayed as expected every ~3000mS except when you're over temperature and executing all those delays.

What is actually happening?

serial.begin can be moved to setup and it could/should be running at a much higher baud rate.

Usually you would put something like this:

lastlcd = millis();

At the end of the if block, not the beginning.

Also, what would you suggest for the baud rate?
Thanks.

I usually use 115200.

What do you get if you run one of the examples that show how to use the library?

Thanks. If I run just the library for the temp sensor, the temp updates just fine.

I suggest that you reduce your main program to something that does nothing but read and display the temp every 3000mS and see what that does.

If it works, gradually put the other stuff back in until it fails.

If it fails, make it even more simple.

I can't see a bug there, but hopefully the methods above will cause it to become more obvious.

rbarcan:
I took your advice and here's what happens.

You did not take our advice to read the forum rules...

Please correct your post above and add code tags around your code:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

Sorry. I corrected the code below.

When I write just this portion of code to display the grill temp, set temp, and control set temp with the buttons, everything works as it should.

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include "max6675.h"

int ktcSO = 8;
int ktcCS = 9;
int ktcCSK = 10;

MAX6675 ktc(ktcCSK, ktcCS, ktcSO);

const int up = A5;    // Push button up
const int down = A4;  // Push button down
const int valve = A2; // Valve
const int buzzer = A3; // Buzzer

int SetTemp = 100;    // Set Temperature at the beginning of the program

unsigned long int increase = 0;
unsigned long int lastbuzzer = 0;
unsigned long int lastbutton = 0;
unsigned long int lastlcd = 0;
unsigned long int setvaluebutton = 100;
unsigned long int setvaluelcd = 1000;
void setup() {

  Serial.begin(9600);// initialize serial monitor with 9600 baud
  pinMode(up, INPUT);
  pinMode(down, INPUT);
  pinMode(5, INPUT_PULLUP); // Enable internal pull-up resistor on pin 5
  pinMode(4, INPUT_PULLUP); // Enable internal pull-up resistor on pin 4


  pinMode(6, OUTPUT);       // Red Led on digital pin 6
  pinMode(7, OUTPUT);       // Blue Led on digital pin 7
  pinMode(13, OUTPUT);      //Fan on digital pin 13
  pinMode(valve, OUTPUT);
  pinMode(buzzer, OUTPUT);

  digitalWrite(up, HIGH);
  digitalWrite(down, HIGH);
  digitalWrite(valve, LOW);
  digitalWrite(buzzer, LOW);

  lcd.begin(16, 2);
  lcd.print("   INOVO INC.");
  lcd.setCursor(0, 1);
  lcd.print("Coolest O2 Grill");

  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(13, LOW);

  delay(3000);
}

void loop()

// First if statement for lcd display to show the sensor temp (grill temp) and the initial set temp. This repeats every 3000ms.
{
  if (millis() - lastlcd > setvaluelcd) {
    lcd.clear();
    lcd.print(ktc.readFahrenheit());
    lcd.setCursor(6, 0);
    lcd.print("deg F");
    lcd.setCursor(0, 1);
    lcd.print("Set Temp = ");
    lcd.print(SetTemp);

    Serial.println("INOVO INC. Coolest O2 Grill");
    Serial.print("Set Temperature = ");
    Serial.println(SetTemp);
    Serial.print("C = ");
    Serial.println(ktc.readCelsius());
    Serial.print("F = ");
    Serial.println(ktc.readFahrenheit());
    lastlcd = millis();
  }

  // Second if statement is to enable the down pushbutton to decrease the set temp when pressed. This repeats every 100ms.


  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(down) == LOW))
  {
    if (SetTemp >= 0)
    {
      SetTemp -= 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }

  // Third if statement is to enable the up pushbutton to increase the set temp when pressed. This repeats every 100ms.

  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(up) == LOW))
  {
    if (SetTemp <= 600)
    {
      SetTemp += 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }

As soon as I add the next if statement ("if(ktc.readFahrenheit() >= SetTemp)"), the grill temp stops updating. See below.

Something seems to be wrong with this if statement...

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include "max6675.h"

int ktcSO = 8;
int ktcCS = 9;
int ktcCSK = 10;

MAX6675 ktc(ktcCSK, ktcCS, ktcSO);

const int up = A5;    // Push button up
const int down = A4;  // Push button down
const int valve = A2; // Valve
const int buzzer = A3; // Buzzer

int SetTemp = 100;    // Set Temperature at the beginning of the program

unsigned long int increase = 0;
unsigned long int lastbuzzer = 0;
unsigned long int lastbutton = 0;
unsigned long int lastlcd = 0;
unsigned long int setvaluebutton = 100;
unsigned long int setvaluelcd = 1000;
void setup() {

  Serial.begin(9600);// initialize serial monitor with 9600 baud
  pinMode(up, INPUT);
  pinMode(down, INPUT);
  pinMode(5, INPUT_PULLUP); // Enable internal pull-up resistor on pin 5
  pinMode(4, INPUT_PULLUP); // Enable internal pull-up resistor on pin 4


  pinMode(6, OUTPUT);       // Red Led on digital pin 6
  pinMode(7, OUTPUT);       // Blue Led on digital pin 7
  pinMode(13, OUTPUT);      //Fan on digital pin 13
  pinMode(valve, OUTPUT);
  pinMode(buzzer, OUTPUT);

  digitalWrite(up, HIGH);
  digitalWrite(down, HIGH);
  digitalWrite(valve, LOW);
  digitalWrite(buzzer, LOW);

  lcd.begin(16, 2);
  lcd.print("   INOVO INC.");
  lcd.setCursor(0, 1);
  lcd.print("Coolest O2 Grill");

  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(13, LOW);

  delay(3000);
}

void loop()

// First if statement for lcd display to show the sensor temp (grill temp) and the initial set temp. This repeats every 3000ms.
{
  if (millis() - lastlcd > setvaluelcd) {
    lcd.clear();
    lcd.print(ktc.readFahrenheit());
    lcd.setCursor(6, 0);
    lcd.print("deg F");
    lcd.setCursor(0, 1);
    lcd.print("Set Temp = ");
    lcd.print(SetTemp);

    Serial.println("INOVO INC. Coolest O2 Grill");
    Serial.print("Set Temperature = ");
    Serial.println(SetTemp);
    Serial.print("C = ");
    Serial.println(ktc.readCelsius());
    Serial.print("F = ");
    Serial.println(ktc.readFahrenheit());
    lastlcd = millis();
  }

  // Second if statement is to enable the down pushbutton to decrease the set temp when pressed. This repeats every 100ms.


  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(down) == LOW))
  {
    if (SetTemp >= 0)
    {
      SetTemp -= 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }

  // Third if statement is to enable the up pushbutton to increase the set temp when pressed. This repeats every 100ms.

  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(up) == LOW))
  {
    if (SetTemp <= 600)
    {
      SetTemp += 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }
  // Forth if statement is to control the leds, buzzer, valve, and fan if the grill temp is greater or smaller than the set temp.
  // If the grill temp is greater than set temp, the buzzer will be on and off every 500ms and the lcd will display "OPEN LID !!!" on and off every 500ms as well as "millis() > (lastbuzzer * increase)" remains true.

  if (ktc.readFahrenheit() >= SetTemp)
  {
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(13, HIGH);
    digitalWrite(valve, LOW);
  }


}

Does anybody have any suggestions please?

what's attached to your pins 6,7,13 and valve?

is there enough power to make it al work together?

6 and 7 are two leds (blue and red), 13 is a Fan that runs on AC, and valve is a solenoid valve that runs on 12V DC. I have enough power to run all of them because I'm using a relay and an AC to DC converter. They all power on/off as they should.

J-M-L:
what's attached to your pins 6,7,13 and valve?

is there enough power to make it al work together?

As soon as I add the last If statement, "if (ktc.readFahrenheit() >= SetTemp)", in the code below, the grill temp, "ktc.readFahrenheit()", stops updating. The buttons work fine, the leds work fine, but the sensor temp is stuck in one value.
I don't know what's the problem.

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include "max6675.h"

int ktcSO = 8;
int ktcCS = 9;
int ktcCSK = 10;

MAX6675 ktc(ktcCSK, ktcCS, ktcSO);

const int up = A5;    // Push button up
const int down = A4;  // Push button down
const int valve = A2; // Valve
const int buzzer = A3; // Buzzer

int SetTemp = 100;    // Set Temperature at the beginning of the program

unsigned long int increase = 0;
unsigned long int lastbuzzer = 0;
unsigned long int lastbutton = 0;
unsigned long int lastlcd = 0;
unsigned long int setvaluebutton = 100;
unsigned long int setvaluelcd = 3000;
void setup() {

  Serial.begin(115200);// initialize serial monitor with 115200 baud
  pinMode(up, INPUT);
  pinMode(down, INPUT);
  pinMode(5, INPUT_PULLUP); // Enable internal pull-up resistor on pin 5
  pinMode(4, INPUT_PULLUP); // Enable internal pull-up resistor on pin 4


  pinMode(6, OUTPUT);       // Red Led on digital pin 6
  pinMode(7, OUTPUT);       // Blue Led on digital pin 7
  pinMode(13, OUTPUT);      //Fan on digital pin 13
  pinMode(valve, OUTPUT);
  pinMode(buzzer, OUTPUT);

  digitalWrite(up, HIGH);
  digitalWrite(down, HIGH);
  digitalWrite(valve, LOW);
  digitalWrite(buzzer, LOW);

  lcd.begin(16, 2);
  lcd.print("   INOVO INC.");
  lcd.setCursor(0, 1);
  lcd.print("Coolest O2 Grill");

  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(13, LOW);

  delay(3000);
}

void loop()

// First if statement for lcd display to show the sensor temp (grill temp) and the initial set temp. This repeats every 3000ms.
{
  if (millis() - lastlcd >= setvaluelcd) {
    lcd.clear();
    lcd.print(ktc.readFahrenheit());
    lcd.setCursor(6, 0);
    lcd.print("deg F");
    lcd.setCursor(0, 1);
    lcd.print("Set Temp = ");
    lcd.print(SetTemp);

    Serial.println("INOVO INC. Coolest O2 Grill");
    Serial.print("Set Temperature = ");
    Serial.println(SetTemp);
    Serial.print("C = ");
    Serial.println(ktc.readCelsius());
    Serial.print("F = ");
    Serial.println(ktc.readFahrenheit());

    lastlcd = millis();
  }

  // Second if statement is to enable the down pushbutton to decrease the set temp when pressed. This repeats every 100ms.


  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(down) == LOW))
  {
    if (SetTemp >= 0)
    {
      SetTemp -= 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }

  // Third if statement is to enable the up pushbutton to increase the set temp when pressed. This repeats every 100ms.

  if ((millis() - lastbutton >= setvaluebutton) && (digitalRead(up) == LOW))
  {
    if (SetTemp <= 600)
    {
      SetTemp += 10;
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbutton = millis();
    }
  }

  if (ktc.readFahrenheit() >= SetTemp)
  {

The final if tries to read the temperature on every iteration of loop. Maybe there's an issue with reading so frequently. Try using millis as you have elsewhere to wait a while between checks.

That is correct but the problem is that it makes the buzzer beep on/off continuously if I use a millis() fuction on the last if statement. Basically, adding the millis() to the last if statement, enables the temp to update correctly but when the sensor temp > SetTemp, the buzzer beeps twice and keeps on beeping indefinitely. The dilemma is that if I don't use the millis(), as you stated, probably the sensor reading is too fast and its stuck in one value, but my buzzer works correctly (beeps twice and then stops).
Maybe there is a better way of making the buzzer stop after two beeps than using the function "millis() > (lastbuzzer * increase)" .

Below is the updated code for the last if statement with the added millis() function.

if ((millis() - lastlcd > setvaluelcd) && ktc.readFahrenheit() >= SetTemp)
  {
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(13, HIGH);
    digitalWrite(valve, LOW);
    lastlcd = millis();
    
    increase += 1;
    if (millis() > (lastbuzzer * increase)) {

      digitalWrite(buzzer, HIGH);
      lcd.clear();
      lcd.print("  OPEN LID !!!");
      delay(500);
      digitalWrite(buzzer, LOW);
      lcd.clear();
      delay(200);
      digitalWrite(buzzer, HIGH);
      lcd.print("  OPEN LID !!!");
      delay(500);
      digitalWrite(buzzer, LOW);
      lcd.clear();
      delay(200);
      digitalWrite(buzzer, HIGH);
      lcd.print("  OPEN LID !!!");
      delay(500);
      digitalWrite(buzzer, LOW);
      lcd.clear();
      delay(200);
      digitalWrite(buzzer, HIGH);
      lcd.print("  OPEN LID !!!");
      delay(500);
      digitalWrite(buzzer, LOW);
      lcd.clear();
      lcd.print(ktc.readFahrenheit());
      lcd.setCursor(6, 0);
      lcd.print("deg F");
      lcd.setCursor(0, 1);
      lcd.print("Set Temp = ");
      lcd.print(SetTemp);
      lastbuzzer = millis();
    }

  } else {

    digitalWrite(buzzer, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(13, LOW);
    digitalWrite(valve, HIGH);
    increase = 0;
    lastbuzzer = 0;
  }
}

When you detect over temperature, set a bool as a flag and perhaps a count of the number of beeps you want.

Check the bool with another millis guarded if and turn the buzzer on if it's off and vice versa. Decrease the beep count. When it's zero, clear the flag.

You may want to ignore the over temp condition when you're beeping. You may also want to ignore it for a little while after you're done beeping, but I'd do that last.

Could you please attach an example code?