interfacing a DS1307 with a 17 Nema motor

hi, I’m building a time controlled automatic feeder for my cats, using Arduino Uno+motor shield V1+17 Nema step motor+Ds1307
I stacked the motor shield on top of the Uno, connected the DS1307 and set up the time( so happy to see that it works :slight_smile: , and connected the stepper motor to M3 and M4. I tested the motor with an easy program and it does what it’s supposed to do…now, the hard part is mixing the time notion with it…
here is my sketch, largely inspired by two project I found online, but i tried to make it simpler:
I defined C1, C2, C3, for each meal, but not sure it’s the best and easy way to proceed.
I got an error message :"a function-definition is not allowed here before ", and I don’t understand why…

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>


RTC_DS1307 rtc;

AF_Stepper motor (200,2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;

int fh1=6;  // 6
int fm1=00;  // 00

int fh2=13;  // 13
int fm2=00;   //00

int fh3=21;   //21
int fm3=00;    //00

int c1;
int c2;
int c3;


void setup() { 
Serial.begin(57600);
 if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);

void loop() { 
  
    DateTime now = rtc.now(); /// it's reading the time
    
 
    //Serial.print(now.year(), DEC);
    //Serial.print('/');
    //Serial.print(now.month(), DEC);
    //Serial.print('/');
    //Serial.print(now.day(), DEC);
    //Serial.print(" (");
    //Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    //Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();  
}

 if (hr == fh1 && mi == fm1 )
  {
    c2=1;
    c3=1;
    
    if(c1== 1)  {
      c1=0;
      motor.step(800,BACKWARD, SINGLE);
      delay(1000);
      motor.step(200,FORWARD, SINGLE);
      delay(1000);
                }
  }
  else
  {
   if (hr == fh2 && mi == fm2 )
   {
     c1=1;
     c3=1;
     
     if(c2== 1)  {
      c2=0;
       motor.step(600,BACKWARD, SINGLE);
      delay(1000);
      motor.step(200,FORWARD, SINGLE);
      delay(1000);
                }
     
     
    }
    else
    {
      if (hr == fh3 && mi == fm3)
      {
        c1=1;
        c2=1;
        
        if (c3== 1) {
          c3=0;
           motor.step(10000,BACKWARD, SINGLE);
           delay(1000);
            motor.step(200,FORWARD, SINGLE);
            delay(1000);;
                }
        
      }
      else
        {

 c1=1;
 c2=1;
 c3=1;          
        }
      }
  
}

}

You have missing and misplaced curly brackets in your sketch. If you put every { and } on their own lines, consistently, and use the autoformat tool (ctrl-t or Tools, Auto Format) those types of errors will be more apparent.

See my comments, in your more properly formatted code, for the locations of the missing and misplaced { and }. The code now compiles. If it does not do what you want, please describe what it does and how that differs from what it should do.

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>

RTC_DS1307 rtc;

AF_Stepper motor (200, 2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;

int fh1 = 6; // 6
int fm1 = 00; // 00

int fh2 = 13; // 13
int fm2 = 00; //00

int fh3 = 21; //21
int fm3 = 00;  //00

int c1;
int c2;
int c3;


void setup() 
{
  Serial.begin(57600);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);
} // added a curly here to close the setup function

void loop()
{
  DateTime now = rtc.now(); /// it's reading the time
  //Serial.print(now.year(), DEC);
  //Serial.print('/');
  //Serial.print(now.month(), DEC);
  //Serial.print('/');
  //Serial.print(now.day(), DEC);
  //Serial.print(" (");
  //Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  //Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  //}  commented out misplaced curly that closed loop function early

  if (hr == fh1 && mi == fm1 )
  {
    c2 = 1;
    c3 = 1;

    if (c1 == 1)
    {
      c1 = 0;
      motor.step(800, BACKWARD, SINGLE);
      delay(1000);
      motor.step(200, FORWARD, SINGLE);
      delay(1000);
    }
  }
  else
  {
    if (hr == fh2 && mi == fm2 )
    {
      c1 = 1;
      c3 = 1;

      if (c2 == 1)  
      {
        c2 = 0;
        motor.step(600, BACKWARD, SINGLE);
        delay(1000);
        motor.step(200, FORWARD, SINGLE);
        delay(1000);
      }

    }
    else
    {
      if (hr == fh3 && mi == fm3)
      {
        c1 = 1;
        c2 = 1;

        if (c3 == 1) 
        {
          c3 = 0;
          motor.step(10000, BACKWARD, SINGLE);
          delay(1000);
          motor.step(200, FORWARD, SINGLE);
          delay(1000);;
        }
      }
      else
      {
        c1 = 1;
        c2 = 1;
        c3 = 1;
      }
    }
  }
}

Thank you! the code compile now, that’s the first step in the good direction. I will follow your advice for the bracket position tracking…the idea, RTC controls the time, and when time is there ( fh1 fm1 for example), the stepper motor should rotate as I directed…but the stepper does not rotate when it reaches the choosen time. I set up the first time at 10h30am, and I open the monitor control and see the time goes by …and nothing happened.
I tested the motor with another small sketch to check if it’s not the motor fault, and it works with some Simpletimer instruction like this one:

#include <SimpleTimer.h>

#include <AFMotor.h>

AF_Stepper motor (200,2);
SimpleTimer timer; // different time, but it's the same idea

void setup() {
  Serial.begin(9600);
  timer.setInterval(5000,repeatMe);//that's where I choose the time between and use repeatMe
  motor.setSpeed(50);// put your setup code here, to run once:

}
void repeatMe() {
  motor.step(600,FORWARD, SINGLE);
delay(1000);
  motor.step(200,BACKWARD, SINGLE);
motor.release();
delay(2000);
}

void loop() {
  timer.run(); //that's the loop using by Simpletimer
  

}

Then I decided to remoce the C1 C2 C3 and simplify with just only one time , I did this sketch:

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>

RTC_DS1307 rtc;

AF_Stepper motor (200, 2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;

int fh1 = 10; // 10
int fm1 = 41; // 00

void setup() {
 Serial.begin(57600);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);
}

void loop() 
{
  DateTime now = rtc.now();
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println();

  if (hr == fh1 && mi == fm1 )
  {motor.step(800, BACKWARD, SINGLE);
      delay(1000);
      motor.step(200, FORWARD, SINGLE);
      delay(1000);
  }
}

and it compiles, but it still does not work…I do not connect the time provided by RTC and the function compared to simpletimer…Should I define something like the RepeatMe which works fine with Simpletimer? Thanks Groundfungus for your help!

 if (hr == fh1 && mi == fm1 )

hr and mi are initialized to 0. Where do they ever get any different values?

The time values from the rtc are given by now.hour() and now.minute().

Once you get this sorted out, you will find that the motor goes back and forth for the full minute. Is that what you want?

I got it, I forgot to connect hr and RTC, and also I realized that the motor will be rotating during a full minute, so I just added a second, so when it reaches for example 11h20min01sec, it does what I ask , and stop right after.
here is the final code with just one time selected, and it works! :slight_smile:

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>

RTC_DS1307 rtc;

AF_Stepper motor (200, 2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;
int sec;

int fh1 = 11; // 10
int fm1 = 20; // 00
int sec1 =01; 
void setup() {
 Serial.begin(57600);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);
}

void loop() 
{
  DateTime now = rtc.now();
  hr=now.hour();
  mi=now.minute();
  sec=now.second();
delay(500);
  
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.print(':');
  
  Serial.println();

  if (hr == fh1 && mi == fm1 && sec ==sec1)
  {motor.step(800, BACKWARD, SINGLE);
      delay(1000);
      motor.step(200, FORWARD, SINGLE);
      delay(1000);
  }
}

Now, I have to define the 3 times, and the stepper motor will activate at 3 specific times I choose and do as many steps as I command ( I have to calibrate now for a number of steps/qqt of food delivered)…When it works, it’s such a small joy! I should have put a video of me jumping…it’s my first project…

if (hr == fh1 && mi == fm1 && sec ==sec1)

With these time matching functions, it is not good practice to rely on an exact match to a specific second. With delay() and other code timing, you might miss the exact match, or with some code, execute multiple times within the second.

One way around this is to match on the minute like you were doing, is to use a boolean "flag" variable like runMotor. Set it = true in the conditional statement. Then trigger the motor operation from if(runMotor). Set runMotor false when you are done with the motor move.

if (hr == fh1 && mi == fm1 && runMotor == false)
 {
   runMotor = true)
 }

if(runMotor) 
{
   motor.step(800, BACKWARD, SINGLE);
   delay(1000);
   motor.step(200, FORWARD, SINGLE);
   delay(1000);
   runMotor = false;
  
}

it's a great idea, I did the time sec by default, but directing the motor to be off is much better...Anyway, I change the sketch and copy your part, but it does not want to compile, I got error message : runMotor was not declared in this scope.... and I realized that the stepper turns only in one direction despite the fact I instruct it FORWARD and BACKWARD???? :confused:

runMotor was not declared in this scope....

Yes, you need to declare all variables. I would make runMotor global. That is declared before setup()

boolean runMotor = false;

I unfortunately provided you with a "snippet" of code which you needed to work properly in to your code.

and I realized that the stepper turns only in one direction despite the fact I instruct it FORWARD and BACKWARD???? :confused:

When you were running the simple timer version of the program, was the motor going forward and backward?

I just tested it, it starts exactly at the time, but does not stop after the first run as commanded!
I added
boolean runMotor =false; just before Void setup (){
and added the code you proposed…but it’s like the motor does not stop until the minute is over.

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>

RTC_DS1307 rtc;

AF_Stepper motor (200, 2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;


int fh1 = 13; // 10
int fm1 = 43; // 00


int fh2 =12;
int fm2 =48;


int fh3=12;
int fm3=07;
int sec3=01;

boolean runMotor =false;
void setup() {
 Serial.begin(57600);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);
}

void loop() 
{
  DateTime now = rtc.now();
  hr=now.hour();
  mi=now.minute();
 
  
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');

  
  Serial.println();

  if (hr == fh1 && mi == fm1 && runMotor ==false)
  { runMotor =true;
  }
  if (runMotor)
  {motor.step(800, BACKWARD, SINGLE);
      delay(1000);
      motor.step(200, FORWARD, SINGLE);
      delay(1000);
      runMotor= false;
     
  }
}

and I realized that the stepper is doing weird stuff also with the simpler sketch too, sometimes it does rotates exactly , but kind of forgot what is forward or backward after. I wonder if my wiring is good: I attached in order yellow, red, green, gray to M3 and M4 of the motor shield board…that’s really weird

and added the code you proposed…but it’s like the motor does not stop until the minute is over.

Yes, I misunderstood the speed and the number of steps you are running. The complete cycle for running of the motor takes less than the minute, and when you reset motorRun= false, it re-enables the sequence to run again during the matched minute.

Here’s a revision which corrects that problem by enabling/disabling the alarm based on time instead of the motor cycle.

#include <Wire.h>
#include "RTClib.h"
#include <AFMotor.h>

RTC_DS1307 rtc;

AF_Stepper motor (200, 2); // it's a stepper motor 1.8deg, 200 steps for 360degrees and is connected to M3 and M4

int hr;
int mi;

int fh1 = 13; // 10
int fm1 = 43; // 00

int fh2 = 12;
int fm2 = 48;

int fh3 = 12;
int fm3 = 07;
int sec3 = 01;

boolean alarm1Enabled = true;

void setup() {
  Serial.begin(57600);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // ->//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // -> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  motor.setSpeed(50);
}

void loop()
{
  DateTime now = rtc.now();
  hr = now.hour();
  mi = now.minute();
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println();

  if (hr == fh1 && mi == fm1 && alarm1Enabled == true)
  {
    alarm1Enabled = false;
    motor.step(800, BACKWARD, SINGLE);
    delay(1000);
    motor.step(200, FORWARD, SINGLE);
    delay(1000);
  }
  
 // if (mi != fm1)
 //EDIT: The code can be made a little more efficient with an additional condition
  if(alarm1Enabled == false && mi != fm1)
  {
    alarm1Enabled = true;
  }
}

I realized that the stepper is doing weird stuff also with the simpler sketch too, sometimes it does rotates exactly , but kind of forgot what is forward or backward after. I wonder if my wiring is good: I attached in order yellow, red, green, gray to M3 and M4 of the motor shield board…that’s really weird

I strongly advise you to work through all the hardware/wiring issues with the motor and motor shield before moving away from the basic library sketches.

EDIT:
There is a useful thread on the same topic of single action time based alarms here https://forum.arduino.cc/index.php?topic=517011.msg3523117#msg3523117

thanks! I will try it as soon as I'm back to it...most likely friday morning! the stepper is doing weird stuff, like it forgot what is forward and do sometimes the full cycle FORWARD,and then doing it right just after.....thanks for you help,I'm getting close to get it done!

Hi. I implemented the corrected sketch, and it works great for ONE time only. When I add a second time, fm2, the loop makes the stepper doing what it's supposed to do for a full minute again!. I just copy/paste the second loop with fm2 mi2, and change in accordance the code...but now, it's back to full work for a minute...GRRRRR

I just copy/paste the second loop with fm2 mi2, and change in accordance the code...but now, it's back to full work for a minute...GRRRRR

You must have done something incorrectly. My crystal ball is not working this morning, so I can't help you.

https://www.youtube.com/watch?v=tdQL_7osGzc