RTC module question

greetings.

I've recently purchased a RTC to implement clock system for my growbox.

However im not sure if im programming it right.

The goal is to turn on light at 5am, turn it off 7pm. while pump runs 15mins, off 45mins, concurrently.

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

////Convert normal decimal numbers to binary coded decimal.
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

////Convert binary coded decimal to normal decimal numbers.
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

////Stops the clock, but it has the side effect of setting seconds to 0.
/*void stopDs1307()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.writeWire.writeWire.write(0x80);
Wire.endTransmission();
}*/

////1) Sets date and time on the clock.
////2) Starts the clock.
////3) Sets hour mode to 24 hours.
void setDateDs1307(
byte second, ////0-59
byte minute, ////0-59
byte hour, ////1-23
byte dayOfWeek, ////1-7
byte dayOfMonth, ////1-28/29/30/31
byte month, ////1-12
byte year) ////0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); ////0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour)); ////If you want 12 hours (am/pm) you need to set
////bit 6 (also need to change getDateDs1307)
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}

////Reads date and time from the clock,
void getDateDs1307(
byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{

////Reset the register pointer.
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

////A few of these need masks because certain bits are control bits.
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); ////Need to change this for 12 hours (am/pm)
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

////Define light and pump pin outs.
int light1 = 8; //light relay
int light2 = 9;
int pump1 = 5; //waterpump relay
int pump2 = 6;

void setup() ////One time run at each execution.
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
pinMode(light1, OUTPUT);
pinMode(light2, OUTPUT);
pinMode(pump1, OUTPUT);
pinMode(pump2, OUTPUT);
Wire.begin();
Serial.begin(9600);

////Set date and time on the clock.
////You only need to run this the first time you setup your RTC.
////Set the correct value below and un comment it to run it.
/*
second = 01;
minute = 32;
hour = 21;
dayOfWeek = 3;
dayOfMonth = 19;
month = 3;
year = 14;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
*/

}

////Main programm loop.
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

////Serial Monitor Output.
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
Serial.print("Date: ");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.println(" ");
Serial.print("Day of week: ");
Serial.print(dayOfWeek, DEC);
Serial.println(" ");
Serial.print("Time: ");
Serial.print(hour, DEC);
Serial.print(":");
Serial.print(minute, DEC);
Serial.print(":");
Serial.print(second, DEC);
Serial.println(" ");

delay(500);


//Turn On light at 5am and Off at 7pm daily.
if((dayOfWeek == 1) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}

else { if((dayOfWeek == 1) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 2) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}
else { if((dayOfWeek == 2) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 3) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}
else { if((dayOfWeek == 3) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 4) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}

else { if((dayOfWeek == 4) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 5) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}

else { if((dayOfWeek == 5) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 6) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}

else { if((dayOfWeek == 6) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}

if((dayOfWeek == 7) && (hour == 05) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}

else { if((dayOfWeek == 7) && (hour == 19) && (minute ==00) && (second == 00))
{
  digitalWrite(light1,LOW);
  digitalWrite(light2,LOW);
}
}
for(int j=0;j<100;j++){
      digitalWrite(pump1,HIGH);
      digitalWrite(pump2,HIGH);
      delay(9000);
    }
    for(int k=0;k<100;k++){
      digitalWrite(pump1,LOW);
      digitalWrite(pump2,LOW);
      delay(27000);
    }
delay(1000);

}

please enlighten me where im wrong. many thanks in advance.

Hi, welcome to the forum.

We can't answer that question, since that could be random code you found somewhere on the internet. I have no idea if that code is any good. Where did you get the code from ?

Hi thanks for the reply.

I used this code and modified the output part.

http://fishtankprojects.com/diy-aquarium-projects/arduino-controlled-dosing-pumps.html

#include “Wire.h”
#define DS1307_I2C_ADDRESS 0x68

////Convert normal decimal numbers to binary coded decimal.
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

////Convert binary coded decimal to normal decimal numbers.
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

////Stops the clock, but it has the side effect of setting seconds to 0.
/*void stopDs1307()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.writeWire.writeWire.write(0x80);
Wire.endTransmission();
}*/

////1) Sets date and time on the clock.
////2) Starts the clock.
////3) Sets hour mode to 24 hours.
void setDateDs1307(
byte second, ////0-59
byte minute, ////0-59
byte hour, ////1-23
byte dayOfWeek, ////1-7
byte dayOfMonth, ////1-28/29/30/31
byte month, ////1-12
byte year) ////0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); ////0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour)); ////If you want 12 hours (am/pm) you need to set
////bit 6 (also need to change getDateDs1307)
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}

////Reads date and time from the clock,
void getDateDs1307(
byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{

////Reset the register pointer.
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

////A few of these need masks because certain bits are control bits.
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); ////Need to change this for 12 hours (am/pm)
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

////Define pump pin outs.
int motorPin1 = 10; //Pump 1 – Flourish Excel
int motorPin2 = 11; //Pump 2 – Flourish Iron
int motorPin3 = 9; //Pump 3 – Flourish
int actled = 13; //Status Led

void setup() ////One time run at each execution.
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(actled, OUTPUT);
Wire.begin();
Serial.begin(9600);

////Set date and time on the clock.
////You only need to run this the first time you setup your RTC.
////Set the correct value below and un comment it to run it.
/*
second = 01;
minute = 32;
hour = 21;
dayOfWeek = 3;
dayOfMonth = 19;
month = 3;
year = 14;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
*/

}

////Main programm loop.
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

////Serial Monitor Output.
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
Serial.print(“Date: “);
Serial.print(dayOfMonth, DEC);
Serial.print(“/”);
Serial.print(month, DEC);
Serial.print(“/”);
Serial.print(year, DEC);
Serial.println(” “);
Serial.print(“Day of week: “);
Serial.print(dayOfWeek, DEC);
Serial.println(” “);
Serial.print(“Time: “);
Serial.print(hour, DEC);
Serial.print(“:”);
Serial.print(minute, DEC);
Serial.print(“:”);
Serial.print(second, DEC);
Serial.println(” “);

delay(500);
analogWrite(actled, 255);
delay(500);

////Pump Operation
////Everyday: Flourish Excel
if((dayOfWeek != 7)&&(hour == 10)&&(minute == 00)&&(second == 10)){

////Start Flourish Iron pump 1,5ml
Serial.print(” Flourish Iron Pump 1,5ml”);
Serial.println(” “);
Serial.println(” On”);
analogWrite(motorPin2, 255);
delay(1500); // 1000 = aprox 1 ml
analogWrite(motorPin2, 0);
Serial.println(” “);
Serial.println(” Off”);

////Monday: Flourish Excel Pump 7,5ml + Flourish 1,5ml
if(dayOfWeek == 1){

////Start Flourish Excel pump 7,5ml
Serial.print(” Flourish Excel Pump 7,5ml”);
Serial.println(” “);
Serial.println(” On”);
analogWrite(motorPin1, 255);
delay(7500); // 1000 = aprox 1 ml
analogWrite(motorPin1, 0);
Serial.println(” “);
Serial.println(” Off”);

////Start Flourish pump 1,5ml
Serial.print(” Flourish Pump 1,5ml”);
Serial.println(” “);
Serial.println(” On”);
analogWrite(motorPin3, 255);
delay(1500); // 1000 = aprox 1 ml
analogWrite(motorPin3, 0);
Serial.println(” “);
Serial.println(” Off”);

}

else{

////Start Flourish Excel pump 1,5ml
Serial.print(” Flourish Excel Pump 1,5ml”);
Serial.println(” “);
Serial.println(” On”);
analogWrite(motorPin1, 255);
delay(1500); // 1000 = aprox 1 ml
analogWrite(motorPin1, 0);
Serial.println(” “);
Serial.println(” Off”);

}

////Saturday: Flourish 1,5ml
if(dayOfWeek == 6){

////Start Flourish pump
Serial.print(” Flourish Pump 1,5ml”);
Serial.println(” “);
Serial.println(” On”);
analogWrite(motorPin3, 255);
delay(1500); // 1000 = aprox 1 ml
analogWrite(motorPin3, 0);
Serial.println(” “);
Serial.println(” Off”);

}
}

else{
Serial.println(“Pump Status: Off”);

////Backup Close Pump
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(actled, 0);

}

// delay(1000);

}

:frowning:

There is a library for that.
This is the start page for the time : Arduino Playground - HomePage
That page points towards the pjrc website for the newest versions.
This is the newest time library : Time Library, Timekeeping and Time/Date Manipulation on Teensy
This is the library to use alarms with it : TimeAlarms Library, Run Functions At Specific Times
Keep that in mind as a good option.

In your sketch, the time is printed to the serial monitor. Is that okay ? So the sketch and DS1307 are working ?
The problem is that you could miss a second or do something many times a second. I see a delay of 27 seconds, that means you can not check the time for a specific (accurate to the second) time. You have to prevent that by remembering the 'state'.

There are many ways to use a 'state', so what I write here is just one of the many ways to do this.
Let's make two variables, one is the state of the light, the other is the state of the pump. I make them boolean, true is on and false is off.
Let's check only the hour for the lights, and only the minute (or a few minutes) for the pump.

boolean stateLight = false;
boolean statePump = false;
...
if ( hour == 5 && !stateLight )
{
  // the hour is 5, and the light was off.
  stateLight = true;

  digitalWrite(light1,HIGH);
  digitalWrite(light2,HIGH);
}
else if ( hour == 19 && stateLight )
{
  stateLight = false;
  ...

The same for the pump. However, I don't want to check for just one minute. Let's expand the window to 5 minutes.
For example turn the pump on at 00 minutes, and turn them off at 45 minutes ? I'm not sure that is what you want to do.

if ( minute >= 0 && minute < 5 && !statePump)          // 5 minute window
{
  statePump = true;

  digitalWrite(pump1,HIGH);
  digitalWrite(pump2,HIGH);
}
else if ( minute >= 45 && minute < 50 && statePump )  // 5 minute window
{
  statePump = false;
  ...

I hope it makes sense. Could you write a sketch with it ?
Please use the auto-format tool, that formats the layout of the text to make it easier to read. It is in the menu somewhere.

There is a library for that.
This is the start page for the time : http://playground.arduino.cc/code/time
That page points towards the pjrc website for the newest versions.
This is the newest time library : http://www.pjrc.com/teensy/td_libs_Time.html
This is the library to use alarms with it : http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
Keep that in mind as a good option.


In your sketch, the time is printed to the serial monitor. Is that okay ? So the sketch and DS1307 are working ?

Yes as of now it's fine if it's printed to the serial monitor. Im getting a LCD display for arduino soon.

and yes the DS1307 module works.

I hope it makes sense. Could you write a sketch with it ? 
Please use the auto-format tool, that formats the layout of the text to make it easier to read. It is in the menu somewhere.

it does make sense. thanks for explaning.

i'll try to make a sketch of it. Kindly correct me if Im wrong. :slight_smile:

So i sketch it like this;

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

//light and pump relays
int light1 = 8; //light relay
int light2 = 9;
int pump1 = 5; //pump relay
int pump2 = 6;

boolean stateLight = false;
boolean statePump = false;

void setup()
{

  Wire.begin();
  Serial.begin(9600);
  byte second, minute, hour;
  pinMode(light1, OUTPUT);
  pinMode(light2, OUTPUT);
  pinMode(pump1, OUTPUT);
  pinMode(pump2, OUTPUT);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  //setDS3231time(30, 34, 23, 5, 7, 5, 15);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
                   dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
                    byte *minute,
                    byte *hour,
                    byte *dayOfWeek,
                    byte *dayOfMonth,
                    byte *month,
                    byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
                 &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute < 10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second < 10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch (dayOfWeek) {
    case 1:
      Serial.println("Sunday");
      break;
    case 2:
      Serial.println("Monday");
      break;
    case 3:
      Serial.println("Tuesday");
      break;
    case 4:
      Serial.println("Wednesday");
      break;
    case 5:
      Serial.println("Thursday");
      break;
    case 6:
      Serial.println("Friday");
      break;
    case 7:
      Serial.println("Saturday");
      break;
  }
}
void loop()
{
  byte second, minute, hour;
  displayTime(); // display the real-time clock data on the Serial Monitor,
  delay(1000); // every second

  if ( hour == 5 && !stateLight )
  {
    // the hour is 5am, and the light was off.
    stateLight = true;

    digitalWrite(light1, HIGH);
    digitalWrite(light2, HIGH);
  }
  else if ( hour == 19 && stateLight )
  {
    stateLight = false;

    digitalWrite(light1, LOW);
    digitalWrite(light2, LOW);
  }

  if ( minute >= 0 && minute < 15 && !statePump)          // 15 minute window
  {
    statePump = true;

    digitalWrite(pump1, HIGH);
    digitalWrite(pump2, HIGH);
  }
  else if ( minute >= 45 && minute < 50 && statePump )  // 45 minute window
  {
    statePump = false;

    digitalWrite(pump1, LOW);
    digitalWrite(pump2, LOW);
  }
}

however it's odd that only the pump turns on..

at first i thought it's because of my time zone hence i reverse the stateLight status. However it's still the same.

In the loop() you declare 'second', 'minute' and 'hour', but they are never filled with the time. They are used as they are. I think you need to call readDS3231time().

holymarder:
So i sketch it like this;

If you'd like to test a different sketch, here is a "RTC timer switch" I posted in the German forum. Comments in the code are English, the sketch is attached as a ZIP file to this posting
http://forum.arduino.cc/index.php?topic=313047.msg2193148#msg2193148

That example needs no library installation or third party libraries
Just unpack the folder from the ZIP file to your Arduino sketch folder.
Supports: DS1307 or DS3231 RTC.

The main reason for writing that was to have a timer switch that automatically adjusts daylight saving time during summer months. Rules for daylight saving time are currently available for Europe (all countries) and for East Australia. If you live in a country without DST, just use the "zoneTime" functions instead of the "localTime" functions.

A one-channel timer switch using as many switching times per day as you like is included in the example sketch. This could switch the light for you.

Then your pump switching in an concurrently task running 15mins/ON and 45mins/OFF could easily be added as an extra task to the loop function.

Please let me know if you need additional assistance or different DST rules for automatic DST time switching.