Pages: [1]   Go Down
Author Topic: DS1307 as an alarm.  (Read 754 times)
0 Members and 1 Guest are viewing this topic.
Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Guys, im trying to build an alarm based on the DS1307 RTC.

My plan is this, to have an alarm that would alarm at specific times as i have inputted them already.

I ordered the module, and im excited to use it, but i wanted to get a jump start from you guys.

My plan to create this project is to read the time from the RTC, such as:

Code:
int hour = now.hour()
int minute = now.minute()

correct?

then, run it through an if statement, like say, i wanted it to ring the alarm at say, 0830, the could would be like:

Code:
if hour == 8 && minute == 30
{
digitalWrite(alarmPin, HIGH);
delay(1000);
digitalWrite(alarmPin, LOW;
}

correct?

smiley
Logged

--Gin319

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you taken into account that the test "hour == 8 && minute == 30" is true for whole a minute (= 60 seconds)? So your alarm pin may be high for more than 1 second (or better 60 times high for one second with only a very short interruption).
Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You've got a point there... Hmmm... Here's my solution:

Since the pin would be 60 times as high as you mentioned, and I wanted a 1 second interruption, ill just make the pin HIGH for 16 mS. So that 60*16 = 960mS, around 1 second. smiley-grin

as for the other codes, would that be a valid code sequence? Like for example, I wanted for different times, i just keep adding "if" statements?
Logged

--Gin319

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Since the pin would be 60 times as high as you mentioned, and I wanted a 1 second interruption, ill just make the pin HIGH for 16 mS. So that 60*16 = 960mS, around 1 second.

You didn't get the point. It's high for one minute, the 60 times comes from the fact that a minute has 60 seconds. If you shorten the pulse to 16ms you just get about 4000 pulses but it's still one minute.

Quote
as for the other codes, would that be a valid code sequence? Like for example, I wanted for different times, i just keep adding "if" statements?

I would not do it that way. Think about storing your alarm times in EEPROM? That way you can change the alarm times without uploading new sketches.
Logged

Sweden
Offline Offline
Full Member
***
Karma: 1
Posts: 161
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi!

You can add a counter. That will solve your problem.

Code:
if ((bAlarmHours==hours) && (bAlarmMinutes==minutes))
{
  if ((nowMillis - ulAlarmDelay) > 60000)
  {
      digitalWrite(alarmPin, HIGH);
      ulAlarmDelay=nowMillis;
  }
  if ((nowMillis - ulAlarmDelay) > 1000)
  {
     digitalWrite(alarmPin, LOW);
  }
}

nowMillis = millis();
The alarm will not trigger again until 1 minute has passed. You will also get 1 sec HIGH/LOW period.

Either store the alarm settings in EEPROM or use the DS1307 RAM (battery powered).

Code:
void set_alarm(byte ah,byte am)
{
  write_byte(1, ah);
  write_byte(2, am);
}
void get_alarm()
{
  bAlarmHours=read_byte(1);
  bAlarmMinutes=read_byte(2);
}
byte read_byte(byte bAdress)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  
  Wire.write(0x08+bAdress);                   // Set the register pointer to (0x08) to read first memory byte
  Wire.endTransmission();                      
  Wire.requestFrom(DS1307_I2C_ADDRESS, 1);     // In this case only read one byte
  byte bRetVal = Wire.read();  
  return bRetVal;
}

void write_byte(byte bAdress,byte bValue)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  
  Wire.write(0x08+bAdress);                             // Set the register pointer to (0xf3) to write the 11th memory byte
  Wire.write(bValue);                             // Write the desired byte value
  Wire.endTransmission();
}


« Last Edit: February 06, 2013, 01:04:02 pm by olof_n » Logged

Philippines
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey olof_n!

Thanks for the reply and help!

I was looking at the code, where you have to store it in either the EEPROM or RAM of the DS1307, considering that I have multiple times that require an alarm, what would be the best way to approach this?

Looking at the code, please do guide me, since I'm still a newbie in programming. i out some comments on each line where I get confused.

Code:
void set_alarm(byte ah,byte am)
{
  write_byte(1, ah);         //ah is the hour?
  write_byte(2, am);        //am is the minute?
}
void get_alarm()
{
  bAlarmHours=read_byte(1);        //So this part reads the data from the EEPROM?
  bAlarmMinutes=read_byte(2);
}

//Is this a new code? like as you said in your statement above, I can either use the EEPROM, or the DS1307 RAM.

byte read_byte(byte bAdress)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS); 
  Wire.write(0x08+bAdress);                   // Set the register pointer to (0x08) to read first memory byte
  Wire.endTransmission();                     
  Wire.requestFrom(DS1307_I2C_ADDRESS, 1);     // In this case only read one byte
  byte bRetVal = Wire.read(); 
  return bRetVal;
}

void write_byte(byte bAdress,byte bValue)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS); 
  Wire.write(0x08+bAdress);                             // Set the register pointer to (0xf3) to write the 11th memory byte
  Wire.write(bValue);                             // Write the desired byte value
  Wire.endTransmission();
}


With regards to writing new values to the EEPROM without uploading new sketches, how is that done?

if I proceeded with the IF else statements, would it still be possible? Like if I add a "second" reading, and add it to the test, such as, "hour == 8 && minute == 30 && second == 01"? And just upload a new sketch every time i wanted to change the alarm times?
Logged

--Gin319

Offline Offline
Edison Member
*
Karma: 56
Posts: 2144
The last thing you did is where you should start looking.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you haven't already seen the Time library and the included TimeAlarms libraries you may benefit by looking at them:
http://playground.arduino.cc/Code/time
http://answers.oreilly.com/topic/2704-how-to-create-an-arduino-alarm-that-calls-a-function/
Logged

Sweden
Offline Offline
Full Member
***
Karma: 1
Posts: 161
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi!

The code stores the alarm in DS1307 RAM (not EEPROM).
You could use arrays to store multiple alarms.

Here is an example.

Code:
byte bAlarmHours[3];  //Declare an array of bytes
byte bAlarmMinutes[3]; //Declare an array of bytes

bAlarmHours[0] = 10; //Set first alarmhour
bAlarmHours[1] = 11; //Set next alarmhour
bAlarmHours[2] = 12;

//Check all alarms
for (byte bNumOfAlarms=0;bNumOfAlarms<=2;bNumOfAlarms++)
{
         if ((bAlarmHours[bNumOfAlarms]==hours) && (bAlarmMinutes[bNumOfAlarms]==minutes))
         ........
}

Code:
void set_alarm(byte ah,byte am)
{
  write_byte(1, ah);         //ah is the hour?  Correct
  write_byte(2, am);        //am is the minute? Yes you can change the variable names to something better.
}
void get_alarm()
{
  bAlarmHours=read_byte(1);        //So this part reads the data from the EEPROM?
  bAlarmMinutes=read_byte(2);     //It reads from DS1307 RAM.
                                               //If you use an array of alarms add an for loop
}

//Is this a new code? like as you said in your statement above, I can either use the EEPROM, or the DS1307 RAM.

//Below is a funtion that read from the DS1307 RAM. bAdress = which byte you want to read.
//Function get_alarm calls read_byte
byte read_byte(byte bAdress)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  
  Wire.write(0x08+bAdress);                   // Set the register pointer to (0x08) to read first memory byte
  Wire.endTransmission();                      
  Wire.requestFrom(DS1307_I2C_ADDRESS, 1);     // In this case only read one byte
  byte bRetVal = Wire.read();  
  return bRetVal;
}

//Writes to RAM.
//bAdress = The address in memory
//bValue = byte you want to store
//Function set_alarm calls write_byte
void write_byte(byte bAdress,byte bValue)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);  
  Wire.write(0x08+bAdress);                             // Set the register pointer to (0xf3) to write the 11th memory byte
  Wire.write(bValue);                             // Write the desired byte value
  Wire.endTransmission();
}

Hope this make sense. I am from Sweden so my English is not the best.

/Olof
Logged

Pages: [1]   Go Up
Jump to: