Arduino no delay timer and counter functions

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; }

Reply to
Loading thread data ...

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

Reply to

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.