Making Servo run at a certain time using an DS3231 RTC clock

Hey guys I have a school project that involves an arduino Leonardo, servo motor and a DS3231 RTC....
What I need for the servo to do is for it to move once and strike a metal tube at a certain times of the day.

What I need help with is how to write the code including the RTC and Servo, I've programmed before and its been a real long time since I've programmed last.

Ive searched all over the internet for help and can't find the right type of help....

Any help would be greatly appreciated

When working with servos, the best thing to do is load up the servo sweep tutorial and try it out.
This confirms that you can load a sketch and that you have the servo wired up properly.

Adafruit has arduino examples for the DS3231 RTC. Go try those out.
This will confirm that you have the RTC wired correctly.

Now you have examples of how to use the RTC and examples of how to more a servo. Put them together!
If you have difficulties with this, come back here and we will help you with the issues you are having with your code.

I have used a couple of sources to come up with some code.... The problem that I have run into is that the code wont compile. The error message I keep getting is....
Arduino: 1.8.2 (Windows 8.1), Board: "Arduino Leonardo"

Build options changed, rebuilding all
Servo_and_RTC_code:3: error: no matching function for call to 'DS3231::DS3231(const uint8_t&, const uint8_t&)'

DS3231 rtc(SDA, SCL);

^

C:\Users\Ed\Documents\Servo_and_RTC_code\Servo_and_RTC_code.ino:3:20: note: candidates are:

In file included from C:\Users\Ed\Documents\Servo_and_RTC_code\Servo_and_RTC_code.ino:1:0:

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:64:3: note: DS3231::DS3231()

DS3231();

^

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:64:3: note: candidate expects 0 arguments, 2 provided

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:60:7: note: constexpr DS3231::DS3231(const DS3231&)

class DS3231 {

^

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:60:7: note: candidate expects 1 argument, 2 provided

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:60:7: note: constexpr DS3231::DS3231(DS3231&&)

C:\Users\Ed\Documents\Arduino\libraries\DS3231/DS3231.h:60:7: note: candidate expects 1 argument, 2 provided

Servo_and_RTC_code:4: error: 'Time' does not name a type

Time t; //define a name for the time function

^

C:\Users\Ed\Documents\Servo_and_RTC_code\Servo_and_RTC_code.ino: In function 'void setup()':

Servo_and_RTC_code:15: error: 'class DS3231' has no member named 'begin'

rtc.begin();

^

C:\Users\Ed\Documents\Servo_and_RTC_code\Servo_and_RTC_code.ino: In function 'void loop()':

Servo_and_RTC_code:21: error: 't' was not declared in this scope

t = rtc.getTime();

^

Servo_and_RTC_code:21: error: 'class DS3231' has no member named 'getTime'

t = rtc.getTime();

^

Servo_and_RTC_code:29: error: 'OnHOur' was not declared in this scope

if (t.hour == OnHOur && t.min == OnMin {

^

Servo_and_RTC_code:29: error: expected ')' before '{' token

if (t.hour == OnHOur && t.min == OnMin {

^

Servo_and_RTC_code:43: error: expected primary-expression before '}' token

}

^

exit status 1
no matching function for call to 'DS3231::DS3231(const uint8_t&, const uint8_t&)'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

This is the code I have so far

#include <DS3231.h>
#include <Servo.h>
DS3231 rtc(SDA, SCL);
Time t; //define a name for the time function
//The start and end times of the desired operation
const int OnHour = 12;
const int OnMin = 24;
const int OffHour = 12;
const int OffMin = 25;
Servo myservo; //create servo object to control a servo..... a maximum of 8 servos can be created
int pos = 0; //variable to store the servo position
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
rtc.begin();
myservo.attach(9); //attaches the servo on pin 9 to the servo object
}

void loop() {
// put your main code here, to run repeatedly:
t = rtc.getTime();
Serial.print(t.hour);
Serial.print (" hour(s),");
Serial.print (t.min);
Serial.print (" minute(s)");
Serial.println(" ");
delay (1000);

if (t.hour == OnHOur && t.min == OnMin {
for (pos = 0; pos < 180; pos += 1) //goes from 0 degrees to 180 degrees
{
myservo.write(pos); //tell servo to go to position in variable 'pos'
delay(3); // wait 3ms for the servo to reach the position
}
{
for (pos = 180; pos >= 1; pos -= 1)
{
myservo.write(pos); //tell servo to go to position in variable pos
delay(3); //wait 3ms for the servo to reach the position
}
}
}
}

There are several libraries called DS3231.h and they each have different syntax. It appears that the syntax of your sketch and that of your library do not match.

My recommendation is to use a library by Jack Christensen called DS3232RTC.h. It works with the DS3231 and is a available through the library manager. It is designed to integrate with the Time library which can help with scheduling events at specified times.

Okay guys,
This is where im stuck, I have code that will run 6 servos and strike the tubular bells....
But I need to now program the servos to strike in a tune... such as dum.. dum... dum. dum.
They all need to strike once.
Can anyone tell me how to achieve this using this code?

#include <DS3231.h>
#include <Servo.h>
DS3231 rtc (SDA, SCL);
Time t;
const int OnHour = 0; //we'll set hour and minute to a specific time later
const int OnMin = 1; //we'll set hour and minute to a specific time later
int pos = 0;
Servo myservo1; // Note D
Servo myservo2; // Note E
Servo myservo3; // Note F#
Servo myservo4; // Note G
Servo myservo5; // Note A
Servo myservo6; // Note B
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
rtc.begin();
myservo1.attach(13); //attaches Note D to pin 9
myservo2.attach(12);
myservo3.attach(11);
myservo4.attach(10);
myservo5.attach(9);
myservo6.attach(8);
}

void loop() {
// put your main code here, to run repeatedly:
t = rtc.getTime();
Serial.print(t.hour);
Serial.print (" hour(s),");
Serial.print (t.min);
Serial.print (" minute(s)");
Serial.println(" ");
delay (1000);

if (t.hour == OnHour && t.min == OnMin)
{
for (pos = 0; pos <= 0; pos += 5)
myservo1.write(pos);
delay(6000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo1.write(pos);
delay(60);
}
{
for (pos = 0; pos <= 0; pos += 5)
myservo2.write(pos);
delay(5000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo2.write(pos);
delay(60);
}
{
for (pos = 0; pos <= 0; pos += 5)
myservo3.write(pos);
delay(4000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo3.write(pos);
delay(20);
}
{
for (pos = 0; pos <= 0; pos += 5)
myservo4.write(pos);
delay(3000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo4.write(pos);
delay(20);
}
{
for (pos = 0; pos <= 0; pos += 5)
myservo5.write(pos);
delay(2000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo5.write(pos);
delay(20);
}
{
for (pos = 0; pos <= 0; pos += 5)
myservo6.write(pos);
delay(2000);
}
for (pos = 180; pos >= 0; pos -= 5) {
myservo6.write(pos);
delay(20);
}
}

Before you start solving new problems can you please explain the purpose of the many for loops in your program that look like this

    for (pos = 0; pos <= 0; pos += 5)
      myservo1.write(pos);

Those are to move all my servos fast and strong enough to strike the tubular bells and make a loud enough sound. It makes the servo go from starting position to 180 degrees and then comes back.
Since theres 6 servos and I need them to go back into position I need that many loops.
I have very little experience coding so I don't know if I can do this differently.

Those are to move all my servos fast and strong enough to strike the tubular bells and make a loud enough sound

If you want the servo to move as fast as possible to a given position you do not need a for loop. Simply write() the target position to the servo. In any case the for loops are written in such a way as to write to the servos only once anyway.

I don't really understand. Can you please give me a an example of what you mean by using a write() command?

If you want a servo to go from where it is now to position 120 as fast as possible just say servo.write(120). No need for anything more.

Steve

1 Like

succ17:
I don't really understand. Can you please give me a an example of what you mean by using a write() command?

slipstick has given you the answer, but let me expand on it

Try this

void setup()
{
  Serial.begin(115200);
  int pos;
  for (pos = 0; pos <= 0; pos += 5)
    Serial.println(pos);
}

void loop()
{
}

Before you run it, try and predict how many times it will print the value of pos and its value(s) and hence how many times it would write the value of pos to the servo if the println() was replaced by writing to the servo.

Do you need the for loop ?

It looks like you took the Sweep example as your model when writing your program but Sweep has a very different purpose, one of which is moving the servo slowly, which is exactly the opposite of what you want