Variable timer / constant amount of Pixels available drawing issue?

Hello Everyone

I’ve got a bit of complex code (Well for me it is) that I’m struggling to get my head around or to find an alternative way of how to accomplish it.

The dilema:
I’m drawing a graph and the amount of pixels for each specific stage is limited so that the graphing will be accurate and not run off the screen. The time that it takes to draw the specific part of the graph can be set and is changeable. So how it makes sense to me is:

Graphing function Time for specific section / pixels = time of delay between graphing points. (I’m working with milliseconds to avoid working with floats)

Now this makes sense to me and is all good, but I have a count down timer which I’m displaying as well. The count down timer is decremented each time a second passes. I detect this by testing whether the delay times added together is >= 1000 (1 sec) and if it is I decrement my timer. Now this works well for when your delay is less than 1000 ms but when it is more you will always have a certain left over amount of milliseconds.

To resolve this I test whether my added delay is >= 2000 to detect whether the left over amounts have added together enough so that another second have passed. If so I decrement my timer by 2 in stead of 1. I believe I can get it to work like this but it seems like the solution wont be very fluent. i.e. The timer would count down once every loop but then every now and again when the loop finishes the counter would count down twice. This doesn’t seem like smooth operation to me.

So I was wondering whether anyone out there might think of a different way on how to accomplish this so that the operation and execution will be more fluent?

O and I’m trying to do this on an Arduino UNO.

My test code below:

  #include <glcd.h>                // include the library header
  #include <fonts/allFonts.h>      // include the Fonts
  
  int HEAT_Temp       = 180;

  int Temp                    = 200;      // Random variable to test whether it will compile or not.
  int Seconds                 =   0;
  int Minutes                 =   0;
  
  int HEAT_Keep_SEC   = 20;

  int HEAT_Keep_Pixals = 15;

  int Increment_Variable = 1;
  int Increment_Detector = 1;
  int Ramp_Temp_Range    = 1;

  int Pixals_Test = 1;
  int Time_Increment = 1;  
  
  int Timer_Decrement_Detector = 0;
  int Second_Detector = 0;
  
  int Void_Time;

void setup() 
{
  // put your setup code here, to run once:
    GLCD.Init(NON_INVERTED);     // Initialize the GLCD 
    GLCD.ClearScreen(); 
    GLCD.Init();
    
    GLCD.SelectFont(System5x7);                                                                       
    
    
    GLCD.CursorToXY(5, 2);
    GLCD.print("Sec      : "); 
    GLCD.CursorToXY(5, 11);
    GLCD.print("Sec Det  : ");     
    GLCD.CursorToXY(5, 20);
    GLCD.print("Inc Det  : ");     
    GLCD.CursorToXY(5, 29);
    GLCD.print("Void Time: ");     
    GLCD.CursorToXY(5, 38);
    GLCD.print("Time Det : ");   
  
    Seconds = HEAT_Keep_SEC;  
}

void loop() 
{
  
    Temp_Constant_Graph_Validator ( HEAT_Keep_SEC, HEAT_Keep_Pixals); 
    
    
    
     if( Minutes >= 0 && Seconds >= 0 && Second_Detector >= 1 )    
     { 
       if ( Second_Detector == 1 )
       {
         HEAT_Keep_SEC--;
       }

       if ( Second_Detector == 2 )
       {
         HEAT_Keep_SEC = HEAT_Keep_SEC - 2;
       }       
     }    
    
    
     delay(Increment_Variable);          
    
    GLCD.CursorToXY(70, 2);
    Print_Scpacing_Calculator( HEAT_Keep_SEC );
    
    GLCD.CursorToXY(70, 11);

    Print_Scpacing_Calculator( Second_Detector );
    
    GLCD.CursorToXY(70, 20);
    Print_Scpacing_Calculator( Increment_Detector );
    
    GLCD.CursorToXY(70, 29);
    Print_Scpacing_Calculator( Void_Time );
    
    GLCD.CursorToXY(70, 38);
    Print_Scpacing_Calculator( Timer_Decrement_Detector );
    
    
}

void Temp_Constant_Graph_Validator ( int Time_Range, int Keep_Pixals )
{ 
  
  int Void_Time_Elapsed;                                                         
 
  Second_Detector = 0;                                            

  Time_Range = Time_Range * 1000;                    
  Increment_Variable = ( Time_Range / Keep_Pixals );                                                                                                      
  
//  Graphing_Function();                                                         

  Void_Time_Elapsed = Increment_Variable * Increment_Detector;       
                                                                                     
  Void_Time = Void_Time_Elapsed;

  if (( Void_Time_Elapsed - Timer_Decrement_Detector ) >= 1000 )              
  {                                                                                 
    if (( Void_Time_Elapsed - Timer_Decrement_Detector ) >= 2000 )       
    {
      Timer_Decrement_Detector =  Timer_Decrement_Detector + 2000;                  

      Second_Detector = 2;                                                         
    }
    
    else
    {
      Timer_Decrement_Detector =  Timer_Decrement_Detector + 1000;        
      Second_Detector = 1;                                                           
    }                                                          
  }

  Increment_Detector++;                                       
      
  if ( Increment_Detector >= Keep_Pixals && Void_Time_Elapsed >= Time_Range )   
  {                                                                                     
    Increment_Detector = Keep_Pixals;             
    
    Increment_Variable = Increment_Variable - ( Void_Time_Elapsed - Time_Range ); 
  }                                                                                    
}

void Print_Scpacing_Calculator( int Variable )
{
    if ( Variable < 0 )
    {
      Variable = 0;
    }

    if ( Variable < 10 && Variable >= 0 )
    {
      GLCD.print("    ");
      GLCD.print(Variable);
    }
    
    if ( Variable < 100 && Variable >= 10  )
    {
      GLCD.print("   ");
      GLCD.print(Variable);
    }

    if ( Variable < 1000 && Variable >= 100 )
    {
      GLCD.print("  ");
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }

    if ( Variable < 10000 && Variable >= 1000 )
    {
      GLCD.print(" ");
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }
    
    if ( Variable >= 10000 )
    {
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }    
    
}

Adding up delays is not an accurate way of keeping time since it ignores the time taken with instructions between the delay() calls. Use the millis() function for timing. It gives you the number of milliseconds since the Arduino started. To measure a time interval you create an unsigned long variable to contain the time at the start of the interval:

unsigned long StartOfTimer = millis();

Then subtract that from the current time to determine the length of the interval.

unsigned long interval = millis() - StartOfTimer;

If you want to count off seconds:

    if (millis() - StartOfTimer > 1000) {
        // A second has passed
        SecondsCounter++;
        // Display the seconds here
       StartOfTimer += 1000;
    }

Hello John

Thanks for the feedback. I will try and implement your advice and then revert back once I made some progress. Much appreciated.

Dirk

Hello John

I considered making it work with delays but after implementing what you’ve mentioned I realized that it would be taking the long hard way around. Thanks for the advise, I got the code working. Below is the working code:

  #include <glcd.h>                // include the library header
  #include <fonts/allFonts.h>      // include the Fonts
  
  
  unsigned long StartofTimer_Seconds;
  unsigned long StartofTimer_Graphing_Interval;
  
  int PREH_Temp       = 150;
  int HEAT_Temp       = 180;
  int SLDR_Temp       = 210;
  int KEEP_Temp       = 180;
  int COOL_Temp       = 150;

//********************************************************************************************************************

  int Temp                    = 200;      // Random variable to test whether it will compile or not.
  int Seconds                 =   0;
  int Minutes                 =   0;
  
//********************************************************************************************************************
  
  int PREH_Keep_SEC   = 10;
  int PREH_Keep_MIN;
  
  int HEAT_Keep_SEC   = 30;
  int HEAT_Keep_MIN;
  
  int SLDR_Keep_SEC   = 10;
  int SLDR_Keep_MIN;

//********************************************************************************************************************

  int PREH_Pixals = 18;
  int PREH_Keep_Pixals = 14;          //   Check values
    
  int HEAT_Pixals = 8;
  int HEAT_Keep_Pixals = 15;
  
  int SLDR_Pixals = 9;
  int SLDR_Keep_Pixals = 9;
  
  int KEEP_Pixals = 16;
  int COOL_Pixals = 6;
  int DONE_Pixals = 21;

//********************************************************************************************************************

  int Increment_Variable = 1;
  int Increment_Detector = 1;
  int Ramp_Temp_Range    = 1;

  int Pixals_Test = 1;
  int Time_Increment = 1;  
  
  int Timer_Decrement_Detector = 0;
  int Second_Detector = 0;
  
  int Void_Time;
  int Loop_Through_Detector = 1;

//********************************************************************************************************************


void setup() 
{
  // put your setup code here, to run once:
    GLCD.Init(NON_INVERTED);     // Initialize the GLCD 
    GLCD.ClearScreen(); 
    GLCD.Init();
    
    GLCD.SelectFont(System5x7);                                                                       
    
    
    GLCD.CursorToXY(5, 2);
    GLCD.print("Sec      : ");    
    GLCD.CursorToXY(5, 11);
    GLCD.print("Inc Var  : ");     
    GLCD.CursorToXY(5, 20);
    GLCD.print("Graph Int: "); 
    GLCD.CursorToXY(5, 29);
    GLCD.print("Inc Det  : "); 
    
    Seconds = HEAT_Keep_SEC;  
    
    StartofTimer_Seconds = millis();
    StartofTimer_Graphing_Interval = millis();    
}

void loop() 
{
    Temp_Constant_Graph_Validator ( Seconds, HEAT_Keep_Pixals ); 
    
    if( Minutes >= 0 && Seconds >= 0 && Second_Detector >= 1 )      //    Will require a third validator. MilliSeconds tester to see whether a second have really passed or not.
    {
      Seconds--;       
    }      
    
//****************************************************************************************************************************************************************************    
    
    GLCD.CursorToXY(70, 2);
    Print_Scpacing_Calculator( Seconds );
    
    GLCD.CursorToXY(70, 11);
    Print_Scpacing_Calculator( Increment_Variable );

    GLCD.CursorToXY(70, 20);
    Print_Scpacing_Calculator( StartofTimer_Graphing_Interval );

    GLCD.CursorToXY(70, 29);
    Print_Scpacing_Calculator( Increment_Detector ); 
}


//****************************************************************************************************************************************************************************
//***********************************                      Graphing function qualifier during constant temp stages                ********************************************
//****************************************************************************************************************************************************************************  

void Temp_Constant_Graph_Validator ( int Time_Range, int Keep_Pixals )
{ 
  
  int Void_Time_Elapsed;                                                              //  Variable to store the total time that have elapsed in the constant temp function.
 
  Second_Detector = 0;                                                                //  Set the Second_Detector back to zero each time the loop loops through

//****************************************************************************************************************************************************************************  
  Time_Range *= 1000;                                                                //  Multiply Time_Range with 1000 to change the increment unit of measurement from seconds to milliseconds to prevent working with a float and rather with an integer.

  if ( Loop_Through_Detector == 1 )
  {
    Increment_Variable = ( Time_Range / Keep_Pixals );                               //  Devides the time range by the amount of pixals to get an incremental time amount which will be incremented and looped by the amount of pixals available.                                                                                      
    Loop_Through_Detector = 0;
  }
  
//****************************************************************************************************************************************************************************  
 
  if ( Increment_Detector <= Keep_Pixals )
  {
    if ( millis() - StartofTimer_Graphing_Interval >= Increment_Variable )                //  Test whether millis() - StartifTimer_Graphing_Interval is greater than Increment_Variable or not, if so call the Graphing_Function
    {
//    Graphing_Function();                                                                //  We call the graphing function so that we can graph each time the loop is looped through.
      StartofTimer_Graphing_Interval += Increment_Variable;                               //  We increment the timer with the test value i.e. Increment_Variable so that we will be able to detect it again.
      Increment_Detector++;
    }
  }
//**************************************************************************************************************************************************************************** 
  if ( Seconds > 0 )
  {
    if ( millis() - StartofTimer_Seconds >= 1000 )                                       //  Test whether millis() - StartifTimer_Seconds is greater than 1000 or not, if so make Second_Detecto 1 so that we can decrement seconds.
    {
      StartofTimer_Seconds += 1000;
      Second_Detector = 1;                                                               //  We call the graphing function so that we can graph each time the loop is looped through.
    }
  }

//****************************************************************************************************************************************************************************  
  
}


//****************************************************************************************************************************************************************************
//***********************************                  Correct Printing Function i.e. whether to insert a space or not            ********************************************
//****************************************************************************************************************************************************************************  

void Print_Scpacing_Calculator( int Variable )
{
    if ( Variable < 0 )
    {
      Variable = 0;
    }

    if ( Variable < 10 && Variable >= 0 )
    {
      GLCD.print("    ");
      GLCD.print(Variable);
    }
    
    if ( Variable < 100 && Variable >= 10  )
    {
      GLCD.print("   ");
      GLCD.print(Variable);
    }

    if ( Variable < 1000 && Variable >= 100 )
    {
      GLCD.print("  ");
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }

    if ( Variable < 10000 && Variable >= 1000 )
    {
      GLCD.print(" ");
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }
    
    if ( Variable >= 10000 )
    {
      GLCD.print(Variable);                                                                                         // Print the Temp. reading
    }

Thanks again.
Dirk