Pages: [1] 2   Go Down
Author Topic: real time clock ds 1307  (Read 6836 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
shrz
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

im trying to use the ds 1307 realtimeclock
(datasheet:http://www.reichelt.de/?SID=208PfrUqwQARQAAH6JtH4852ebc6602248fba4d6fe06e77038d10;ACTION=7;LA=6;OPEN=1;INDEX=0;FILENAME=A200%252FDS_1307.pdf),
connected via i2c two wire bus
im able to set the the time (it seems like it works) , but if i try to read from the ds 1307 i get always the time and date i set up in 1307 memory. There is no increasement of time.
I use a 32.768 kHz quartz crystal connected to he x1/x2 pins of the RTC, if I remove it there is the same behaviour, nothing changes.

Here is the code I use:


Code:

#include <Wire.h>

byte _sec =4;
byte _min=8;
byte _hour=3;
byte _day =5;
byte _date=2;
byte _month=6;
byte _year =7;

boolean state;

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  Wire.beginTransmission(104); // transmit to device #104, the ds 1307

    // **********setting time**************
 // Wire.send(sendung, 8); //sec
  Wire.send(_sec); //sec
  Wire.send(_min); //min
  Wire.send(_hour);  //hour
  Wire.send(_day);  //day
  Wire.send(_date); //date
  Wire.send(_month);  //month
 // Wire.send(_year);  //year
  

      
                  
  Wire.endTransmission();    // stop transmitting
}

void loop()
{

 delay(100);

  Wire.requestFrom(104, 6);    // request 6 bytes from slave ds1307
  while(Wire.available())    // slave may send less than requested
  {
    digitalWrite(13,state); //LED on pin 13 to see if there is activity
    state=!state;
    int c = Wire.receive();
    Serial.println(c);  

  }

delay (100);
}


thanks for help


woo
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

hi

check page 7 4 of the datasheet:

"Please note that the initial power on state of all registers is not defined.  Therefore it is important to
enable the oscillator (CH bit=0) during initial configuration. "

You could also check this page on using the Dallas DS1306.
D
« Last Edit: June 03, 2007, 05:50:03 pm by Daniel » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
shrz
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the fast reply,

I read that, bit 7 of register 00.
But isnt it the same as the "seconds" Register? So it will be set with the _sec value, which is set to 4 (binary 00000010) at the moment?
How to Adress the different registers, just by executing eg 3 times a Wire.send() line to acces the 3rd register?


best
woo
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

hi

not sure.. for inspiration, i would have a look at the  DS1306 tutorial.

D
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Many 32 kHz crystals are not designed to operate at the 6 (or 12) pFd input C of the DS1307.

You might add a 20 pFd cap from each side of the crystal to GRD.

Your CH is being set to 0 which is correct.

pha(at)phanderson.com
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
shrz
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I checked the Crystal it has a capacity of 12 pf - should work. But I tried as well with 22pF caps. Still the same.
In some other forums about microkontrollers they write abut that you have to send a 'TWI write' first, then 'repeated (TWI) start' then you can Read the register.  
I guess i need to set the pointer without writing directly to the register.

any ideas?

best
woo
Logged

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

I just got my 1307 working with the arduino.  I assume you have the resistors tying your SDA and SDL lines to 5V?  This is critical.  Otherwise you won't get reliable reads.

Also, the bigger problem is in your code.  I followed your code at first and got the same result but wondered how the DS1307 knew what address I wanted to read.  That's the problem.  Before you read you want to do at least one write to send in an address which will set the register pointer on the DS1307.  Page 8 of the datasheet glosses over this so quickly that it's easy to miss.  So in your setup function, first do a Wire.send(0x00) to set the register address to 0, then set the time.  At the beginning of your loop function, do a beginTransmission, send another 0x00, then an endTransmission.  Then requestFrom, etc, etc. and the while loop.  You should then be able to see the clock ticking.  Remember though that you're reading out a byte at a time in BCD format, so if you just print the byte the seconds will count to 89 and skip numbers in between.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
shrz
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This sounds great!
Thanks a lot I'll try it soon. I was wondering as well about setting the register pointer, but i didn't get a clue how to do... but this looks good.

thanks again!

woo
Logged

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

This code is pretty functionally solid so I figured I'd post it.  This will read the date and time and print it out on the serial port.  Even before you set the time you should be able to load this and see it tick.

#include <Wire.h>

int hour;
int minute;
int second;
int month;
int day_of_week;
int day;
int year;

char* dow[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup()
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  // Below required to reset the register address to 0.
  Wire.beginTransmission(104); // transmit to device #104, the ds 1307
  Wire.send(0x00);
  Wire.endTransmission();    // stop transmitting
 
  Wire.requestFrom(104, 7);    // request 7 bytes from slave ds1307, we'll assume it'll send them all even though it doesn't have to
  second = Wire.receive();
  minute = Wire.receive();
  hour = Wire.receive();
  day_of_week=Wire.receive();
  day = Wire.receive();
  month = Wire.receive();
  year = Wire.receive();

  // Convert all the BCD values that might have "tens" to decimal.  Most arduino folks do this w/shifts but this just looks easier to me.
  hour=hour/16 * 10 + hour % 16;
  minute=minute/16 * 10 + minute % 16;
  second=second/16 * 10 + second % 16;
  day=day/16 * 10 + day % 16;
  month=month/16 * 10 + month % 16;
  year=2000 + year/16 * 10 + year % 16;
  
  Serial.print(hour);
  Serial.print(":");
  if (minute < 10) { Serial.print("0"); }
  Serial.print(minute);
  Serial.print(":");
  if (second < 10) { Serial.print("0"); }
  Serial.print(second);
  Serial.print(" ");
  Serial.print(dow[day_of_week-1]);  // array is 0-6, but the dow register holds 1-7, so subtract 1.
  Serial.print(", ");
  Serial.print(month);
  Serial.print("/");
  Serial.print(day);
  Serial.print("/");
  Serial.print(year);
  Serial.print("\n");
  delay(1000);
}
Logged

new york
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So you guys are saying you should have a resistor on your Analog 4 and 5 pins (which connect to the SCL and SDA) ?
I am not using any resistors, but using this same exact code and I get no response from the RTC module.

I bought the module from sparkfun all wired up so I don't think it's because of an incorrect oscillator or anything.

Thanks,
Lucas
Logged

new york
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just caught you guys are probably talking about a pullup resistor!
Logged

Millicent, South Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Apologies for reviving an old thread, but it's the closest topic I could find to my problem, and I'm using essentially the code above to talk to my DS1307 mini board.

I have a sketch which (among other things) monitors & calculates the maximum & minimum daily temperatures, then writes the date (dd/mm/yy), MaxTemp & MinTemp to the Arduino's onboard EEPROM memory. This is working fine, but I thought I'd try to add the ability to display the recordings when I connect the USB cable and press 'd' (for 'dump data').

Currently I have to upload a small sketch to display the data, then re-load the original sketch. For simplicity I'd much rather just press 'd' & cut and paste the resulting data, without having to 'stop' the original program. Unfortunately, it seems that trying to monitor the serial port via Serial.read() somehow messes with the SDA/SCL lines. The standard output from my sketch looks like this:
Code:
15:05:37 on Monday, 8/12/2008 - Current temperature is: 24.7; Max - 23.0, Min - 22.0
15:05:38 on Monday, 8/12/2008 - Current temperature is: 25.7; Max - 24.0, Min - 22.0
15:05:39 on Monday, 8/12/2008 - Current temperature is: 26.4; Max - 25.0, Min - 22.0
15:05:40 on Monday, 8/12/2008 - Current temperature is: 26.9; Max - 26.0, Min - 22.0
15:05:41 on Monday, 8/12/2008 - Current temperature is: 26.8; Max - 26.0, Min - 22.0
15:05:42 on Monday, 8/12/2008 - Current temperature is: 26.6; Max - 26.0, Min - 22.0
When I add in the code to monitor for serial input, the clock output becomes something nonsensical, like this:
Code:
8:00:00 on I, 8/3/2000 - Current temperature is: 23.5; Max - 0.0, Min - 22.0
8:00:00 on I, 8/3/2000 - Current temperature is: 24.6; Max - 0.0, Min - 22.0
8:00:00 on I, 8/3/2000 - Current temperature is: 25.3; Max - 0.0, Min - 22.0
8:00:00 on I, 8/3/2000 - Current temperature is: 25.9; Max - 0.0, Min - 22.0
8:00:00 on I, 8/3/2000 - Current temperature is: 26.4; Max - 0.0, Min - 22.0
8:00:00 on I, 8/3/2000 - Current temperature is: 26.8; Max - 0.0, Min - 22.0
The data dump does work when I press 'd', but obviously it's pretty much useless if it messes with the clock. As a newbie I'm chuffed to have achieved this functionality, and won't be too fussed if there's no way around this, but you guys seem to be able to solve just about everything else that comes up!! smiley

Thanks for reading!

JB

PS - I haven't posted the code because it's pretty long, so let me know if you need it...
« Last Edit: December 07, 2008, 11:53:01 pm by jbennett » Logged

JB

Austin, TX USA
Offline Offline
God Member
*****
Karma: 5
Posts: 998
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It appears not to be just messing with the clock.  Note that the min temperature is also "messed with".  Is it the new sketch still storing the data in the eeprom?  If so, does the original "dump" sketch display the correct values, or is the eeprom corrupted also?

You say the code is pretty big.  Is it too big?  You sometimes see weirdness like this when you unexpectedly run out of memory.  You may have to post the code after all.

Regards,

Mikal
« Last Edit: December 08, 2008, 01:02:08 am by mikalhart » Logged

Millicent, South Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Mikal,

The min temp is actually OK - the grabs I've shown are when the program is displaying output every second, and the Min Temp is calculated over the past 60 seconds.

Well, in the hope that it helps, here's the code...

#include <EEPROM.h>
#include <Wire.h>
#include <math.h>
#include <DateTime.h>

int potPin = 0;                                 // input read pin for LM35 is Analog Pin 0
float temperature = 0;                             // variable which will be calculated in process
long val=0;                                 // variable to store the value coming from the sensor
#define TRIGGER_INACTIVE 0xffffffff              // a special value that indicates that no trigger is active.
unsigned long  endTrigger = TRIGGER_INACTIVE;
#define ThermistorPIN 0                          // Analog Pin 0
double temp;

int MinTemp = 40;       // setting a high initial value makes for easy comparison in the loop,
int MaxTemp = 0;        // and vice versa for a low initial MaxTemp.
int WriteAddress = 0;   // initial address for EEPROM writes.
int ReadAddress = 0;
byte value;             // will be used
int incomingByte = 0;      // for incoming serial data

int hour;
int minute;
int second;
int month;
int day_of_week;
int day;
int year;

char* dow[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

double Thermistor(int RawADC) {
 //    Inputs ADC Value from Thermistor and outputs Temperature in Celsius
 //    requires: include <math.h>
 //    Utilizes the Steinhart-Hart Thermistor Equation:
 //    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3}
 //    where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08
 long Resistance;  double Temp;  // Dual-Purpose variable to save space.
 Resistance=((10240000/RawADC) - 10000);  // Assuming a 10k Thermistor.  Calculation is actually: Resistance = (1024/ADC)
 Temp = log(Resistance); // Saving the Log(resistance) so not to calculate it 4 times later. // "Temp" means "Temporary" on this line.
 Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));   // Now it means both "Temporary" and "Temperature"
 Temp = Temp - 273.15;  // Convert Kelvin to Celsius                                         // Now it only means "Temperature"
 return Temp;  // Return the Temperature
}

void printDouble(double val, byte precision) {
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimal places
  // example: printDouble(3.1415, 2); // prints 3.14 (two decimal places)
  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac, mult = 1;
    byte padding = precision -1;
    while(precision--) mult *=10;
    if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult;
    unsigned long frac1 = frac;
    while(frac1 /= 10) padding--;
    while(padding--) Serial.print("0");
    Serial.print(frac,DEC) ;
  }
}

void TakePhoto() {
  int FanStatus = digitalRead(3);
  digitalWrite(3,LOW); // first, switch off the fans
  Serial.print(" Fans switched off - status stored as ");
  if (FanStatus == 0) Serial.println("OFF");
  else Serial.println("ON");
  digitalWrite(9,HIGH); // then send power to the camera
  Serial.println("  Power to Camera");
//  delay(500); // time for current to get to camera - not sure if this is needed...
  digitalWrite(6,HIGH); // trigger the solenoid for 100 msec
  Serial.println("   Solenoid triggered");
  delay(100);
  digitalWrite(6,LOW);
  delay(15000); // wait 15 seconds for the camera to take a photo then shutdown
  digitalWrite(9,LOW);
  Serial.println("    Camera power switched off");
  digitalWrite(3,FanStatus); // return fans to initial status
  Serial.print(" Fans returned to ");
  if (FanStatus == 0) Serial.print("OFF");
  else Serial.print("ON");
  Serial.println(" status");
}

void setup()
{
 pinMode(3,OUTPUT); // FANS control - YELLOW
 digitalWrite(3,LOW);
 pinMode(6,OUTPUT); // SOLENOID power control - WHITE
 digitalWrite(6,LOW);
 pinMode(9,OUTPUT); // CAMERA control - BLUE
 digitalWrite(9,HIGH);
 pinMode(13,OUTPUT);
 Serial.begin(115200);
 Wire.begin();
}

void loop() {

 // Below required to reset the register address to 0.
 Wire.beginTransmission(104); // transmit to device #104, the ds 1307
 Wire.send(0x00);
 Wire.endTransmission();    // stop transmitting

 Wire.requestFrom(104, 7);    // request 7 bytes from slave ds1307, we'll assume it'll send them all even though it doesn't have to
 second = Wire.receive();
 minute = Wire.receive();
 hour = Wire.receive();
 day_of_week=Wire.receive();
 day = Wire.receive();
 month = Wire.receive();
 year = Wire.receive();

 // Convert all the BCD values that might have "tens" to decimal.
 hour=hour/16 * 10 + hour % 16;
 minute=minute/16 * 10 + minute % 16;
 second=second/16 * 10 + second % 16;
 day=day/16 * 10 + day % 16;
 month=month/16 * 10 + month % 16;
 
 year=2000 + year/16 * 10 + year % 16;
 
// Change times below to desired photo times. Copy & paste to add more photos per day.
// NOTE: for some reason, 8's & 9's cause an error, so don't use them on their own below;
// 18 & 19 work fine, but 08 & 09 do not.
 if (hour == 9) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 10) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 11) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 12) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 13) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 14) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 15) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 16) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 17) { if (minute == 00) { if (second == 00) { TakePhoto();}}}
 if (hour == 18) { if (minute == 00) { if (second == 00) { TakePhoto();}}}

 Serial.print(hour);
 Serial.print(":");
 if (minute < 10) { Serial.print("0"); }
 Serial.print(minute);
 Serial.print(":");
 if (second < 10) { Serial.print("0"); }
 Serial.print(second);
 Serial.print(" on ");
 Serial.print(dow[day_of_week]);
 Serial.print(", ");
 Serial.print(day);
 Serial.print("/");
 Serial.print(month);
 Serial.print("/");
 Serial.print(year);

  int span = 20;  int aRead = 0;
  for (int i = 0; i < span; i++) {        //loop to get average of 20 readings
    aRead = aRead + analogRead(ThermistorPIN);
}
  aRead = aRead / span;
  temperature = Thermistor(aRead);
 Serial.print(" - Current temperature is: "); printDouble(temperature,1);     // display Celsius

 Serial.print("; Max - "); printDouble(MaxTemp,1);     // display current MaxTemp
 Serial.print(", Min - "); printDouble(MinTemp,1);     // display current MinTemp
 Serial.println("");

  if( temperature > 35 ){  // is the Temp above 35 degrees Celcius?
      if( endTrigger == TRIGGER_INACTIVE){  // only proceed if no trigger is active.  
        // trigger the fans and store the time to turn off the LED
         digitalWrite(3, HIGH);
    Serial.println("              Threshold Temperature EXCEEDED, switching fans on.");
         endTrigger = DateTime.now() + (1 * 60); // set trigger for 1 minute(s) from now
              // note that DateTime.now() returns seconds since Arduino started
    }
  }
    if( DateTime.now() >= endTrigger ){ // only process this if endTrigger has been set
      if( temperature > 33 ){  // if temp has dropped below 33 degrees Celcius, turn fans off
        Serial.println("   Temperature still above threshold, fans remaining on.");
      endTrigger = DateTime.now() + (1 * 60);
      }      // or, if temp is still above threshold, leave fans on for another minute
      else if( temperature <= 33 ) {Serial.println("   Temperature has dropped below threshold, fans switched OFF.");
      digitalWrite(3,LOW);
      endTrigger = TRIGGER_INACTIVE;
      }
    }

// Now need a loop to read the temperature in the box, work out a daily MinTemp & MaxTemp, and record to EEPROM memory.
// This needs to repeat every day.

  if( temperature > MaxTemp) {MaxTemp = temperature;}
  if( temperature < MinTemp) {MinTemp = temperature;}

// if (second == 0){
// if (hour == 23) { if (minute == 59) { if (second == 50) {}} // just before midnight to avoid possible date confusion
 if (minute == 0){ if (second == 0){

    EEPROM.write(WriteAddress,(day));
    ++WriteAddress;
    EEPROM.write(WriteAddress,month);
    ++WriteAddress;
    EEPROM.write(WriteAddress,(year-2000));
    ++WriteAddress;    
    EEPROM.write(WriteAddress,MaxTemp);
    ++WriteAddress;
    Serial.println("                              MaxTemp recorded");
    MaxTemp = 0;
  }
}


... code continued next post ...
Logged

JB

Millicent, South Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... The section after "MinTemp = 40" below seems to be causing the problems. If I comment this lot out down to the delay my program behaves just fine.

// if (second == 30){
// if (hour == 12) { if (minute == 00) { if (second == 00) {}}
 if (minute == 30){ if (second == 0){
    EEPROM.write(WriteAddress,MinTemp);
    ++WriteAddress;
    Serial.println("                              MinTemp recorded");
    MinTemp = 40;
    }
  }
  // DATA-DUMP: check for any incoming serial input, then proceed only if 'd' is pressed
      if (Serial.available() > 0) {
      incomingByte = Serial.read();      
          if (incomingByte == 100) {
          Serial.println("          Data dump initiated:");
            Serial.print("\t");
            Serial.print("   Date");
            Serial.print("\t");
            Serial.print("MaxTemp");
            Serial.print("\t");
            Serial.println("MinTemp");

            value = EEPROM.read(ReadAddress);
            while (ReadAddress < 511) {
//              Serial.print(ReadAddress);
//              Serial.print("\t");
              Serial.print(value, DEC);
              ReadAddress = ReadAddress + 1;
              value = EEPROM.read(ReadAddress);
              Serial.print("/"); Serial.print(value, DEC);
              ReadAddress = ReadAddress + 1;
              value = EEPROM.read(ReadAddress);
              if(value < 10) {
                Serial.print("/200");}
                else {Serial.print("/20");}
              Serial.print(value, DEC);
              ReadAddress = ReadAddress + 1;
              value = EEPROM.read(ReadAddress);
              Serial.print("\t"); Serial.print("   "); Serial.print(value, DEC);
              ReadAddress = ReadAddress + 1;
              value = EEPROM.read(ReadAddress);
              Serial.print("\t"); Serial.print("   "); Serial.print(value, DEC);
              ReadAddress = ReadAddress + 1;
              Serial.println();
              }
          ReadAddress = 0;
      }
      }
 delay(1000);
}


Just for a quick run-down, the program is designed to take a photo at the pre-programmed times each day. The camera system will be remotely deployed & run off a solar panel & 12V battery. The program monitors temperatures & will switch on fans to cool down the box if the temp goes over 35 degrees Celcius. We're recording the temperatures to see what extremes the camera is being exposed to, as it's just a consumer-grade Canon PowerShot A720IS.

As I mentioned, the program WITHOUT the data dump feature works fine so there's no problems there. Just not sure why the data dump section is corrupting the clock's data!! smiley-sad

Sorry for the lengthy posts and thanks for any ideas!!

JB

PS - by the way, thanks to those of you who recognise the bits of code above that they've contributed to this project!  ;D
« Last Edit: December 08, 2008, 06:33:00 am by jbennett » Logged

JB

Pages: [1] 2   Go Up
Jump to: