Arduino no delay timer and counter functions

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I wrote a couple of functions that work similar to PLC timers and counters.
When the condition comes true, they time to the preset value and turn on a
done DN bit.  I used Allen Bradley PLC timers as a general reference.
Anyway, you can have all your control in your loop and use the timers
control or delay the execution of events.  In the example below I have a
timer that is enabled because the 2nd timer isn't done, the 2nd timer starts
when the first timer is done.

The slow part in the loop is the Serial.print functions but you can see how
it goes through the loop fast but times events based on the preset and time
base.  The time base is the number of milliseconds per preset count.  With
the base set to 1, you have 1 millisecond resolution with a maximum unsigned
int time of 65535 milliseconds.  With the time base set to 10, the timer
resolution is 10 milliseconds, 1000 gives 1 second resolution, 60,000 give
you 1 minute resolution, you can time up to 65535 minutes.

Anyway, if you want to take temperature readings every hour or update R/C
servos every 20 milliseconds these timers should do the job without halting
the program.

The timerdata elements
.starttime - this is the time the timer started timing in millis()/base
.accum     -  the accumulated time, starts at zero and times up to the
preset value
.EN   -  Timer ENabled bit, set when the timer is enabled, i.e. the enable
condition is true
.TT -  Timer is Timing, the enable bit is ON but the done DN bit is not ON.
.DN  - ON when the timer is enabled and done.

TON is a time on delay
CTU is a count up counter
RES resets a timer or counter

I used the same data structure for the counter.  Counter gets reset to zero
and counts up to the preset at 1 count per low to high transition of the
enable bit.

The performance of these depend on the speed of the loop so you write the
code to not hold up processing but control processing by conditions.

Here's a little loop that flashes the LCD, counts with a preset of 1000 but
resets the counter after accumulated value becomes 20.

// The naming comes from PLC's that I'm familiar with, strange for an
Arduino sketch

struct timerdata
{
  unsigned int accum, starttime;
  boolean TT,DN,EN;
}
T4_0, T4_1,C5;


void setup()
{
  Serial.begin(57600);
  pinMode(13,OUTPUT);
}

void loop()
{
  //Serial.print(millis());
  Serial.print(T4_0.accum);
  Serial.print("  ");
  TON(&T4_0,!T4_1.DN,500,1);
  TON(&T4_1,T4_0.DN,500,1);
  digitalWrite(13, T4_0.DN);
  CTU(&C5,T4_0.DN,1000);
  Serial.println(C5.accum);
  if(C5.accum>20%)RES(&C5);
}

int TON(struct timerdata *sp, int EN, int preset, byte base)
{
  if(!base)base=1; // no divide by zero if base unspecified
  if(!sp->EN && EN)// Enable has transitioned from falset to true
  {
    sp->starttime = millis()/base;
    sp->EN = EN;
    sp->accum = 0;
  }
  if(EN && !sp->DN)
  {
    sp->accum = millis()/base-sp->starttime;
    sp->DN=sp->accum >= preset;
    sp->TT = 1;
  }
  if(sp->DN)sp->TT=0;
  if(!EN)
  {
    sp->EN=0;
    sp->DN=0;
    sp->TT=0;
  }

}

int CTU(struct timerdata *sp, int EN, int preset)// Count Up Counter
{
  //sp->preset = preset;
  if(!sp->EN && EN)// Enable has transitioned from falset to true
  {
    sp->accum++;
    sp->EN = EN;
    if(sp->accum>=preset)sp->DN=1;
  }
  if(!EN)sp->EN=0;
  if(sp->DN)sp->TT=0;
}

void RES(struct timerdata *sp)
{
  sp->accum=0;
  sp->EN=0;
  sp->TT=0;
  sp->DN=0;
}



Re: Arduino no delay timer and counter functions
Hello RogerN,

After following your project about timer and counter functions in the arduino i made a TOF function and would like to say thanks and share the code with you.


int TOF(struct timerdata *sp, int EN, int PRE, byte base)
{
  if(!base)
  {
   base = 1; // No divide by zero if base unspecified.
  }
  
  if(sp->EN && !EN)// Falling edge detection, enable has transitioned from true to false.
  {
    sp->starttime = (millis() / base); // Take the starting time.
    sp->EN = EN;
    sp->TT = 1;   // As long as the timer is counting TT is true.  
  }    
    
  if(!EN && sp->TT) // Continue counting.
  {
   sp->ACC = (millis() / base) - sp->starttime; // Update the accumulator.
   if  (sp->ACC > PRE) // If the accumulator is greater then the preset value the timer is done.
   {
    sp->DN = 0;
   }  
  }  
  else
  {
   sp->DN = 1;
  }
  
  if(!sp->DN) // If the timer is done.
  {
  sp->TT=0; // When the timer is done and is nolonger counting TT is false
  }
    
  if(EN) // If the timer is not enabled then reset the variables
  {
    sp->EN = 1;
    sp->ACC = 0; // Reset the accumulator.
    sp->TT = 0;
  }
  
}  





Thank you and greets

Robbert-Jan Vermeer

Site Timeline