So close! (problems with millis and timer)

So very close to completing this project…

The idea is basically a fan timer and speed controller with 5 buttons and an lcd display.

Button1: Runs a small start up sequence.
Button2: Increase the speed in 10% increments then back to 10%.
Button3: Increase the time the fan is on in 15 minute increments then hourly increments after 1 hour.
Button4: Change the amount of time the fan is off with same increments as above.
Button5: Stop button.

Everything works perfect except the timer bit, any help would be appreciated. Code is as follows:

#include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

int fan = 6;
int fanStart = 220;
volatile int fanSpeed = 0;
int onOff = 0;
volatile int percent = 0;
volatile int onMins = 0;
volatile int onHours = 0;
volatile int offMins = 15;
volatile int offHours = 0;
unsigned long previousMillis = 0;
volatile long offMinsTimer = 0;
volatile long onMinsTimer = 0;
volatile long onHoursTimer = 0;
volatile long offHoursTimer = 0;
long m = 600000;
long h = 3600000;
volatile int onCount = 0;
volatile int offCount = 0;

void setup() {
Serial.begin(9600);
lcd.begin(16,2);
pinMode (5, INPUT);
pinMode (4, INPUT);
pinMode (3, INPUT);
pinMode (2, INPUT);
pinMode (fan, OUTPUT);
attachInterrupt(digitalPinToInterrupt(3),button2_ISR, RISING);
}

void loop() {

////////////////On Button////////////////////////

int press1 = digitalRead(5);

if (press1 == HIGH && fanSpeed ==0)
{
onOff = 1;
analogWrite (fan, fanStart);
delay (500);
fanSpeed = 186;
analogWrite (fan, fanSpeed);
if (press1 == HIGH && fanSpeed ==186)
percent = 10;
}

/////////////On Timer Button/////////////////////

int press3 = digitalRead(4);

if (press3 == HIGH && onCount ==0)
onMins = onMins+15;

if (onMins > 45)
{
onMins = 0;
onCount = 1;
}
if (press3 == HIGH && onCount == 1)
{
onHours = onHours+1;
if (onHours > 12)
{
onHours = 0;
onCount = 0;
}
}
/////////////Off Timer Button//////////////////////
int press4 = digitalRead(2);

if (press4 == HIGH && offCount ==0)
offMins = offMins+15;

if (offMins > 45)
{
offMins = 15;
offCount = 1;
}

if (press4 == HIGH && offCount == 1)
offHours = offHours+1;

if (offHours > 12)
{
offHours = 0;
offCount = 0;
}
/////////////Stop Button/////////////////////

int press5 = digitalRead(7);

if (press5 == HIGH && onOff == 1)
{
onOff = 0;
fanSpeed = 0;

}
if (press5 == HIGH && onOff == 0)
percent = 0;

///////////////LCD Display///////////////////

if (fanSpeed == 0)
{
lcd.setCursor(0,0);
lcd.print(“Fan Off “);
lcd.setCursor(0,1);
lcd.print(” “);
}
else
{
lcd.setCursor(0,0);
lcd.print(“Fan Speed:”);
lcd.print(percent);
lcd.print(”%”);
lcd.print(" ");
lcd.setCursor(0,1);
if (onMins == 0 && onHours == 0)
{
lcd.print ("Continuous ");
}
lcd.print(“On:”);
if (onMins < 61 && onCount == 0)
{
if (onMins < 10)
lcd.print(“0”);
lcd.print(onMins);
lcd.print("M ");
}
else if (onCount > 0)
{
if (onHours < 10)
lcd.print(“0”);
lcd.print(onHours);
lcd.print("H ");
}
lcd.print(“Off:”);
if (offMins < 61 && offCount == 0)
{
if (offMins < 10)
lcd.print(“0”);
lcd.print(offMins);
lcd.print("M ");
}
else if (offCount > 0)
{
if (offHours < 10)
lcd.print(“0”);
lcd.print(offHours);
lcd.print("H ");
}

}

///////////////Timer Calculations/////////////////////

onMinsTimer = onMinsm;
onHoursTimer = onHours
h;
offMinsTimer = offMinsm;
offHoursTimer = offHours
h;

/////////////Serial Monitor For Debug/////////////////

Serial.print( " FanSpeed:");
Serial.print(fanSpeed);
Serial.print( " onOff:");
Serial.print(onOff);
Serial.print(" Percent:");
Serial.print(percent);
Serial.print(" Mins:");
Serial.print(onMins);
Serial.print(" Hours:");
Serial.print(onHours);
Serial.print(" onCount:");
Serial.print(onCount);
Serial.print(" onMins:");
Serial.print(onMinsTimer);
Serial.print(" onHours:");
Serial.print(onHoursTimer);
Serial.print(" offMins:");
Serial.print(offMinsTimer);
Serial.print(" offHours:");
Serial.println(offHoursTimer);

////////////////On/Off Timer//////////////////////////

while (onMins>0 || onHours>0)
{
unsigned long currentMillis = millis();
if(onMins>0 && onHours ==0)
{
if(currentMillis - previousMillis > onMinsTimer)
{
previousMillis = currentMillis;
analogWrite(fan,fanSpeed);
}
}

if(onMins==0 && onHours>0)
{
if(currentMillis - previousMillis > onHoursTimer)
{
previousMillis = currentMillis;
analogWrite(fan,fanSpeed);
}
}

if (onMins>0 || offHours>0 && offMins>0)
{
if(currentMillis - previousMillis > offMinsTimer)
{
previousMillis = currentMillis;
analogWrite(fan,LOW);
}
}

if (onMins>0 || onHours>0 && offHours>0)
{
if(currentMillis - previousMillis > offHoursTimer)
{
previousMillis = currentMillis;
analogWrite(fan,LOW);
}
}
}
/////////////////////////////////////////////////////

analogWrite(fan,fanSpeed);

delay (200);
}

void button2_ISR() {
if (onOff == 1)
fanSpeed = fanSpeed+3;
if (onOff == 1)
percent = percent+10;

if (fanSpeed > 213)
fanSpeed = 186;

if (percent == 110)
percent = 10;

}

Everything works perfect except the timer bit

It might help to know what the "timer bit" is doing that is not perfect.

Please read the "how to use the forum" stickies to see how to format and post code.

Please use code tags (</> button on the toolbar) when you post code or warning/error messages. The reason is that the forum software can interpret parts of your code as markup (the smiley face in your code above for example), leading to confusion, wasted time, and a reduced chance for you to get help with your problem. This will also make it easier to read your code and to copy it to the IDE or editor. Using code tags and other important information is explained in the How to use this forum post. Please read it.

Please always do a Tools > Auto Format on your code before posting it. This will make it easier for you to spot bugs and make it easier for us to read. If you’re using the Arduino Web Editor you will not have access to this useful tool. I recommend you to use the standard IDE instead.

Please remove unnecessary blank lines from your code before posting to the forum. One or two to separate code into logical sections is fine but large spaces for no reason just make for more scrolling when we’re trying to read your code.

pwatsoon:

long m = 600000;

1000 ms/s * 60 s/minute = 60000 ms/minute
You have an extra order of magnitude.

Apologies I haven’t used the forum much. Hopefully this is a bit clearer?

So all the lcd code and hour and minute counters are working fine.

I am looking for the fan to run for x amount of time then stop for x amount of time depending on the on and off minute and hour variables in a continuous loop. Hopefully this makes more sense.

#include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

int fan = 6;                  
int fanStart = 220;
volatile int fanSpeed = 0;
int onOff  = 0;
volatile int percent = 0;
volatile int onMins = 0;
volatile int onHours = 0;
volatile int offMins = 15;
volatile int offHours = 0;
unsigned long previousMillis = 0;
volatile long offMinsTimer = 0; 
volatile long onMinsTimer = 0;
volatile long onHoursTimer = 0;
volatile long offHoursTimer = 0;
long m = 600000;
long h = 3600000;
volatile int onCount = 0;
volatile int offCount = 0;

void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  pinMode (5, INPUT);
  pinMode (4, INPUT);
  pinMode (3, INPUT);
  pinMode (2, INPUT);
  pinMode (fan, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(3),button2_ISR, RISING);
}

void loop() {

////////////////On Button////////////////////////

 int press1 = digitalRead(5);

 if (press1 == HIGH && fanSpeed ==0)  
 {
 onOff = 1;
 analogWrite (fan, fanStart);
 delay (500);
 fanSpeed = 186;
 analogWrite (fan, fanSpeed);
if (press1 == HIGH && fanSpeed ==186)
percent = 10;
}

/////////////On Timer Button/////////////////////

int press3 = digitalRead(4);

if (press3 == HIGH && onCount ==0)
  onMins = onMins+15;
  
  if (onMins > 45)
  {
    onMins = 0;
    onCount = 1;
  }
    if (press3 == HIGH && onCount == 1)
  {
  onHours = onHours+1;
  if (onHours > 12)
    {
    onHours = 0;
    onCount = 0;
    }
  }
/////////////Off Timer Button//////////////////////
int press4 = digitalRead(2);

if (press4 == HIGH && offCount ==0)
  offMins = offMins+15;
   
  if (offMins > 45)
  {
    offMins = 15;
    offCount = 1;
  }
    
 if (press4 == HIGH && offCount == 1)
  offHours = offHours+1;
  
  if (offHours > 12)
    {
    offHours = 0;
    offCount = 0;
    }
/////////////Stop Button/////////////////////

int press5 = digitalRead(7);
 
if (press5 == HIGH && onOff == 1)
{
  onOff = 0;
  fanSpeed = 0;
  
}
if (press5 == HIGH && onOff == 0)
percent = 0;

///////////////LCD Display///////////////////

if (fanSpeed == 0)
{
  lcd.setCursor(0,0);
  lcd.print("Fan Off         ");
  lcd.setCursor(0,1);
  lcd.print("                ");
}
else
{
     lcd.setCursor(0,0);
     lcd.print("Fan Speed:");
     lcd.print(percent);
     lcd.print("%");
     lcd.print("   ");
     lcd.setCursor(0,1);
      if (onMins == 0 && onHours == 0)
       {
        lcd.print ("Continuous      ");
       }
     lcd.print("On:");
     if (onMins < 61 && onCount == 0)
     { 
     if (onMins < 10)
     lcd.print("0");
     lcd.print(onMins);
     lcd.print("M ");
     }
      else if (onCount > 0)
     {
      if (onHours < 10)
      lcd.print("0");
      lcd.print(onHours);
      lcd.print("H ");
     }
     lcd.print("Off:");
     if (offMins < 61 && offCount == 0)
     { 
        if (offMins < 10)
        lcd.print("0");
        lcd.print(offMins);
        lcd.print("M ");
     }
          else if (offCount > 0)
     {
      if (offHours < 10)
      lcd.print("0");
      lcd.print(offHours);
      lcd.print("H ");
     }
     
} 
    
///////////////Timer Calculations/////////////////////

  onMinsTimer = onMins*m;
  onHoursTimer = onHours*h;
  offMinsTimer = offMins*m;
  offHoursTimer = offHours*h;

/////////////Serial Monitor For Debug/////////////////  
  
     Serial.print( " FanSpeed:");
     Serial.print(fanSpeed);
     Serial.print( " onOff:");
     Serial.print(onOff);
     Serial.print(" Percent:");
     Serial.print(percent);
     Serial.print(" Mins:");
     Serial.print(onMins);
     Serial.print(" Hours:");
     Serial.print(onHours);
     Serial.print(" onCount:");
     Serial.print(onCount);
     Serial.print(" onMins:");
     Serial.print(onMinsTimer);
     Serial.print(" onHours:");
     Serial.print(onHoursTimer);
     Serial.print(" offMins:");
     Serial.print(offMinsTimer);
     Serial.print(" offHours:");
     Serial.println(offHoursTimer);

////////////////On/Off Timer//////////////////////////
  
while (onMins>0 || onHours>0)
{
  unsigned long currentMillis = millis();
  if(onMins>0 && onHours ==0)
  {
    if(currentMillis - previousMillis > onMinsTimer)
    {
    previousMillis = currentMillis;
    analogWrite(fan,fanSpeed);
    }
  }
  
  if(onMins==0 && onHours>0)
  {
    if(currentMillis - previousMillis > onHoursTimer)
    {
    previousMillis = currentMillis;
    analogWrite(fan,fanSpeed);
    }
  }

  if (onMins>0 || offHours>0 && offMins>0)
  {
    if(currentMillis - previousMillis > offMinsTimer)
    {
    previousMillis = currentMillis;
    analogWrite(fan,LOW);
    }
  }

  if (onMins>0 || onHours>0 && offHours>0)
  {
    if(currentMillis - previousMillis > offHoursTimer)
    {
    previousMillis = currentMillis;
    analogWrite(fan,LOW);
    }
  }
}
/////////////////////////////////////////////////////

  analogWrite(fan,fanSpeed);

  delay (200);
}

void button2_ISR() {
  if (onOff == 1)
   fanSpeed = fanSpeed+3;
  if (onOff == 1)
   percent = percent+10;

  if (fanSpeed > 213)
     fanSpeed = 186;

  if (percent == 110)
  percent = 10;  
}
  if (onOff == 1)
   fanSpeed = fanSpeed+3;
  if (onOff == 1)
   percent = percent+10;

Oh, really? Do you know how to use brackets {}?

You have made the task of timing intervals much more complicated by creating hour and minute timers. If you need to track hours and minutes, you can still do that but it must be easier to time the intervals by adding hours and minutes and using the result as a single interval that you can test with millis(). Don't try to count them out with the "clock" you've created.