Use Real Time Clock to start routine

Hi

I am a new to Arduino and am looking implement a simple time based action.

Goal:
at 7am start the action below
at 8pm turn off the action below
Repeat

I assume it should use an if then statement of some sort like if time > 07:00:00 and < 20:00:00 run routine, else do not run.

I have a RTC ds3231 installed and working properly. ds 3231 master is installed in the Libraries folder. Time is in 24hr format so I would like it to start at 07:00:00 and end at 20:00:00 seconds resolution is not really needed for this application.

I am using the code below to control the stepper motor:

Can someone help me add the time constraint to the stepper motor routine below?

yes this is probably considered lazy but if someone could help out it would save me hour(s) of reading and trial and error...I do have a book on programming on the way.

Thanks

moderator added code tags

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 

// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Stepper test!");

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  myMotor->setSpeed(10);  // 10 rpm   
}

void loop()  {
 delay(2000);
  Serial.println("Single coil steps");
  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
 myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
 myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
   myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
  myMotor->step(400, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(400, BACKWARD, MICROSTEP); 
  myMotor->release();
  delay(3600000);
  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(2000);
}

I assume it should use an if then statement of some sort like if time > 07:00:00 and < 20:00:00 run routine, else do not run.

Of some sort, but not like that.

Can someone help me add the time constraint to the stepper motor routine below?

That code doesn't even read the RTC. That is the first step.

Supposed that the library has methods for getting hour(), minute(), and second(). You could then use:

if(hour() >= 7 && hour() <= 20)
{
   // do the monkey motion stuff
}

If you want to start at 7:30 and end at 8:42:34, then it's a bit more complicated, and using nested if statements is easier:

if(hour() >= 7 && minute() >= 30)
{
    // if it's before the end time...
}

I know that you did not ask about your main code but this

  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
 myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
 myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000); 
   myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000);

is crying out to be done in a for loop

for (int stepNum = 0; stepNum < 5; stepNum++)
{
  myMotor->step(1000, FORWARD, MICROSTEP);
  delay(1000); 
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  delay(1000);  
}

re the motor, yes that loop does look a lot simpler, thanks.

re the time check function, that is where I am having a hard time.
I don't know what code I need to use to tell the arduino to check the time then run if the current time is with in 07:00 and 20:00.

below is all I have done, basically look at the current time in the serial window. I got the arduino 2 weeks ago so this is all new to me. I can change behavior of example code but I dont really know the principals of efficient coding yet. thanks

#include <Wire.h>
#include "ds3231.h"
#include "rtc_ds3231.h"

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");
    
    //Serial.println ("Setting time");
    //parse_cmd ("T173413620122014",16);
    
   
}

void loop()
{
    char in;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
#endif

        Serial.println(buff);
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = inp2toi(cmd, 7);
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

UKHeliBob:
I know that you did not ask about your main code but this

  myMotor->step(1000, FORWARD, MICROSTEP);

delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000);
myMotor->step(1000, FORWARD, MICROSTEP);
delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000);
  myMotor->step(1000, FORWARD, MICROSTEP);
delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000);
myMotor->step(1000, FORWARD, MICROSTEP);
delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000);
  myMotor->step(1000, FORWARD, MICROSTEP);
delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000);



is crying out to be done in a for loop


for (int stepNum = 0; stepNum < 5; stepNum++)
{
  myMotor->step(1000, FORWARD, MICROSTEP);
  delay(1000);
  myMotor->step(1000, BACKWARD, MICROSTEP);
  delay(1000); 
}

I don't know what code I need to use to tell the arduino to check the time then run if the current time is with in 07:00 and 20:00.

Can you at least recognize where hours, minutes, and seconds are stored?

Did you read reply #1?

Hi,

Yes I read reply 1 and while it seems simple I have not seen a good example of a time based sketch using the ds3231. I added your if statement but it did not work. I dont think I have the get time command right. I have copied setup code from the get time test sketch for the ds3231 and added it to the stepper motor sketch I have, then added the if statement. that didnt seem to work.

At this point I am afraid all I am capable of is modifying an existing sketch.

The code is below, maybe there is something simple I missed.

Thanks for the help I appreciate it.

#include <config.h>
#include <ds3231.h>

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 

// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Stepper test!");

  AFMS.begin(1600);  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  myMotor->setSpeed(30);  // 10 rpm   
  int stepNum = 0; stepNum < 5; stepNum++;
  
   Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");
    
    //Serial.println ("Setting time");
    //parse_cmd ("T173413620122014",16); used to reset time sec,min,hrs,day of week1-7,day of month, month, year
    
}
 
void loop()  {
  if(hour() >= 7 && hour() <= 20)
{
    // Monkeystuff below
  
 delay(2000);
  Serial.println("Single coil steps");
  myMotor->step(1000, FORWARD, MICROSTEP);
 delay(1000); 
     
  myMotor->step(1000, BACKWARD, MICROSTEP); 
  release 
  delay(2520000);
}

The code is below, maybe there is something simple I missed.

Yes, there is. I said "suppose you have a function called hour() that...". You don't, so just blindly copying and pasting code is useless.

I'll ask again. Can you see where you get the time from the RTC? It's silly to put code that is concerned about the time BEFORE code that gets the time.

AFTER you get the time,

   if(t.hour > 7 && t.hour < 20)
   {

Paul,

I am posting this request for help in the gigs section. Thanks for the help. at this point I don't feel I know enough to answer even basic questions and don't want to waste members time.