If statement at specific time

apparently this one is escaping me today.

I have an RTC setup but I want to trigger a relay at a specific time. any suggestions on how to go about this one?

I am trying to set it up with the command below that will essentially enable a pump for 15 seconds.

dpr.enable(0); delay(15000);

thanks!

Get rid of the delay. Call dpr.enable(0), note the time it. Keep reading the RTC, when 15 seconds have passed, call dpr.enable(1) or whatever turns it off.

Then the uC can be doing other things in the meantime.

Great idea, I think this solves another issue for me too.

How would I implement this into code?

thanks again!

Something like this quasi-pseudo code:

void loop(){

if (condition for drp.enable(0) & drp_flag == 0){  // check is supposed to run , & not running already
// add drp_start_time =  RTC command to read the time
drp_flag = 1; // set flag to show its running
drp.enable(0); // turn it on
} // end start check

if (drp_flag == 1){ // still running?
// add  RTC command to read the time
if (RTC time >= (drp_start_time + 15 seconds) {  // check if long enough
drp_flag = 0; // turn it off
drp.enable(1); // clear the flag
} // end time check 
} // end running check
} // end loop

I took a slightly different approach, which started with three basic functions and later added a fourth:

(1) mst() - returns current date/time (unix-type time) in milliseconds.

(2) schd(when,what) - inserts a schedule entry into a time-ordered list of schedule requests.

(3) dispatch() - calls scheduled functions when they become "ripe"

(4) after(delay,what) - adds the delay value to the current time and calls schd().

Benefits: No delay() calls in any of my code, no flags/semaphores needed to maintain timing, and my loop() function is reduced to:

void loop(void)
{  dispatch();
}

and it has become a lot easier to add new features to my code. :grin:

Sounds like a software approach ;)

As a hardware engineer writing code, I think I tend to end up with a less neat, but still workable, approach.

Been Arduino-ing since August 2010, have yet to write a function, library, or class. I use some of the existing (SPI, I2C, Keypad, VirtualWire, Fat16Lib), but I've not written any.

I can understand library and class, but you've never written a function? Assuming you mean aside from setup() and loop(), you have all your code inline in one or other of those?

@CrossRoads

Let me encourage you to give it a try - it’s every bit as much fun to watch software run that first time as it is to fire up a brand new circuit without smoke. :slight_smile:

(screen shot of first test run attached - click thumbnail to see full size)

SerialLog.gif

CrossRoads: Sounds like a software approach ;)

As a hardware engineer writing code, I think I tend to end up with a less neat, but still workable, approach.

Been Arduino-ing since August 2010, have yet to write a function, library, or class. I use some of the existing (SPI, I2C, Keypad, VirtualWire, Fat16Lib), but I've not written any.

I come from a similar background and approach. However I often write simple C functions and paste them into the tabbed edit windows of the IDE. I've done if frequently for supporting things like external I2C and SPI A/D and D/A modules. It can save a lot of time and debugging when writing later sketches using such parts and makes the main sketch smaller and easier to manage and understand. Now libraries and C++ classes and such I have yet to try and play with.

Lefty

@retrolefty

That’s pretty much what I’m up to today. Among other things, I need to control a couple of stepper motors, so just drafted a minimal driver for my “scheduled” environment:

/*----------------------------------------------------------------------------*/
/* Global Variables (Translation Unit Scope)                                  */
/*----------------------------------------------------------------------------*/
static unsigned count = 0;             /* Number of steps in this move        */
static time_t   snext;                 /* Time of next step                   */
static unsigned char sbusy = 0;        /* Stepper busy indicator              */
/*----------------------------------------------------------------------------*/
/* stepper() - Cause stepper to move one step (Translation Unit Scope)        */
/*----------------------------------------------------------------------------*/
static void stepper(void)
{  if (count)                          /* Are there any steps left in move?   */
   {  digitalWrite(STP,HIGH);          /* If so, output a step control pulse  */
      digitalWrite(STP,LOW);           /* (Direction already set up)          */
      --count;                         /* Decrement steps remaining           */
      schd(snext+=STT,stepper);        /* Schedule next step                  */
   }                                   /*  end: if steps remain               */
   else sbusy = 0;                     /* Else Indicate stepper not busy      */
}                                      /*  end: stepper()                     */
/*----------------------------------------------------------------------------*/
/* step() - initiate a stepper motor move (Global Scope)                      */
/*----------------------------------------------------------------------------*/
void step(unsigned dir,unsigned steps)
{  while (sbusy) dispatch();           /* Until previous move completes       */
   if (count = steps)                  /* Is the caller's count non-zero?     */
   {  sbusy = ~0;                      /* Indicate stepper busy               */
      snext = mst();                   /* Initialize step base time           */
      digitalWrite(STD,dir & 1);       /* Set up the step direction           */
      stepper();                       /* Take the first step, schedule next  */
   }                                   /*  end: if there's work to do         */
}                                      /*  end: step()                        */

Once I have drivers for all of the devices, I can begin testing and fine-tuning the actual application program. One of the benefits is that all of the code (except probably the application code) will be reusable “as is” for other projects.

[quote author=Morris Dovey link=topic=89554.msg673067#msg673067 date=1328032713] @retrolefty

That's pretty much what I'm up to today. Among other things, I need to control a couple of stepper motors, so just drafted a minimal driver for my "scheduled" environment:

/*----------------------------------------------------------------------------*/
/* Global Variables (Translation Unit Scope)                                  */
/*----------------------------------------------------------------------------*/
static unsigned count = 0;             /* Number of steps in this move        */
static time_t   snext;                 /* Time of next step                   */
static unsigned char sbusy = 0;        /* Stepper busy indicator              */
/*----------------------------------------------------------------------------*/
/* stepper() - Cause stepper to move one step (Translation Unit Scope)        */
/*----------------------------------------------------------------------------*/
static void stepper(void)
{  if (count)                          /* Are there any steps left in move?   */
   {  digitalWrite(STP,HIGH);          /* If so, output a step control pulse  */
      digitalWrite(STP,LOW);           /* (Direction already set up)          */
      --count;                         /* Decrement steps remaining           */
      schd(snext+=STT,stepper);        /* Schedule next step                  */
   }                                   /*  end: if steps remain               */
   else sbusy = 0;                     /* Else Indicate stepper not busy      */
}                                      /*  end: stepper()                     */
/*----------------------------------------------------------------------------*/
/* step() - initiate a stepper motor move (Global Scope)                      */
/*----------------------------------------------------------------------------*/
void step(unsigned dir,unsigned steps)
{  while (sbusy) dispatch();           /* Until previous move completes       */
   if (count = steps)                  /* Is the caller's count non-zero?     */
   {  sbusy = ~0;                      /* Indicate stepper busy               */
      snext = mst();                   /* Initialize step base time           */
      digitalWrite(STD,dir & 1);       /* Set up the step direction           */
      stepper();                       /* Take the first step, schedule next  */
   }                                   /*  end: if there's work to do         */
}                                      /*  end: step()                        */

Once I have drivers for all of the devices, I can begin testing and fine-tuning the actual application program. One of the benefits is that all of the code (except probably the application code) will be reusable "as is" for other projects. [/quote]

I agree. I think a core philosophy of the original C language was that it was designed to be a very 'small' language that relied on external functions and libraries to give it it's great versatility, portablity, and power.

Lefty

Yup, not a 1. It's all inline. My stuff seems to have evolved into watching for a condition, then acting on it, setting a flag if I want something done, then going back to watching. Looking at it a new, setting the flag and then checking it & acting on it is basically a function call.

My big program, 7 tabs compiled to 13 Kbytes, was basically:

void loop(){

Is time running and did a 1/4 second pass (1:00, 3:00, 10:00 countdown)? update digits, set a flag to update the display.

Did a serial message come in? Flash the corresponding lights, stop time if it was running, sound the buzzer.

Did an RF command come in? if time is running, ignore it unless it's the Stop command.
If time is not running, do the command.
Set a flag to update the display if needed. (reset time, reset scores)

is the update display flag set? if yes, write out the new data to the MAX7221.

}

Since most of the time nothing is going on and the conditions are all No, the code is really responsive when something does happen.

@CrossRoads

Not disagreeing with your approach, and will suggest that different problems call for different solution strategies. Arduino’s single loop() works best for highly deterministic problems involving a high degree of synchronicity. My current project probably ranks “medium-low” on determinism, and “low” on synchronicity - and the process I’m controlling is (euphamistically) not well-understood. I’m aware that it has produced at least one explosion (and have read unofficial murmurings of another that resulted in a fatality). My goal is to introduce adaptive real-time computer control of the process to (a) moderate its behavior and (b) capture enough data to allow a better understanding of the process.

The Arduino resource cost of the strategy appears low - with temperature and radiation monitoring, data logging, and the upgrade to keeping time as 64-bit epochal time in msec (but without the Serial debug stuff), the binary sketch size was 1712 bytes. By the time I add the device drivers that’ll probably grow to about 2K - and I don’t yet have a handle on the overall application size, but would be surprised if the whole thing goes over 8K.

[ I was tickled to see that you’re a fencer - in younger days I was a foil enthusiast. :slight_smile: ]

Epee - street fighting at its best!