External Interrupt for MEGA 2560 with SQW from DS1307

Hello all,

I’m trying to control my Mega board 2560 with the SQW signal from an RTC DS1307 Shield.
I want to use this configuration to work with an interrupt (int.0 on pin 2) at 1hz. I made a first sketch but the result on the serial monitor is incomprehensible.
I just want to count the seconds… in this case it will be possible to make a measurement for each minutes and a recording for each hours.
You would find the sketch in the following, if somenone could help me to find and improve my understanding…

Thank you in advance

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

volatile int count;

void setup()
{
Wire.begin();
attachInterrupt(0, loop , RISING);
Serial.begin(9600);
}

void compteur()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07);
Wire.write(0x10);
count = count++;
Serial.println(count);
Wire.endTransmission();
}

void loop()
{
compteur();
}

The "#" CODE button is for posting code. CLICK the MODIFY button. Highlight the code, click the "#" CODE button to create a scroll window for scrolling through the code.

Hi KFMAKR,

First of all, always post your sketch using code tags. (Use the button on the New Topic screen with a # symbol)

Try this:

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

volatile int count;

void setup()
{
  Wire.begin();
  attachInterrupt(0, compteur , RISING);
  Serial.begin(9600);
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07);
  Wire.write(0x10);
  Wire.endTransmission();
}

void compteur()
{
  count = count++;
  Serial.println(count);
}

void loop()
{
}
#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

volatile int count;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07);
  Wire.write(0x10);
  Wire.endTransmission();
  attachInterrupt(0, compteur , RISING);
}

void compteur()
{
  count = count + 1;
}

void loop()
{
  int c = count;
  while (c == count);
  Serial.println(count);
}

Cheers!

 attachInterrupt(0, loop , RISING);

This wrong. ISR (compteur) should be in the above statement, not "loop".

 attachInterrupt(0, compteur , RISING);

I tested your corrections, but it's not very well...

At the SQW rising, compteur start, but there are 25 steps, then it freeze (I think during the low SQW level)
At the second rising, compteur start again and add 25 other steps...
In summary, for each SQW rising, compteur increase 25 times. (1s =1,2,3,...25 / 2s=25,26,27...50 / 3s=...75 / 4s=....100 ....)

I tried to play with the interrupt mode, but without success...

I'm upset...

KFMAKR:
I'm upset...

If you become upset so quickly then maybe electronics is not a good hobby for you!

Try attaching an led from Vcc to the SQW output of the RTC (with a series resistor). Does it flash with 1s interval?

What value do you have for the pull-up resistor on the SQW output? It is open-drain (see page 6 of data sheet). Or you could set the Arduino pin to INPUT_PULLUP. This 25 count each half second sounds like interference from electrical mains (which is 50Hz in Europe) picked up when the pin is floating. If the pullup resistor does not fix the problem, try a 10uF cap between Vcc & GND.

Also post your latest code (use tags this time).

Paul

"Upset" wouldn't be the correct term... I'm more puzzled ... It's my French touch

In fact I'm using the RTC shield from Sparkfun, and, after control, there is no pull-up resistor on the SQW output... firs of all.
In a second time, I'am able to see the step over the board TX led, and it's clearly 1Hz, but we see also a lot of short times in relation with the 25 steps.
Finally, I'm really agree with you about interferences... I initially hesitated to talk about it but I need to put my fingers over the board edge to start the normal running. Currently I'm working with the USB link from an iMAC computer... previously I worked with a classical PC and I never saw this kind of problems. Do you think a power supply would improve this behavior ?

About the sketch I'm using the correction from kowalski:

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

volatile int count;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07);
  Wire.write(0x10);
  Wire.endTransmission();
  attachInterrupt(0, compteur , RISING);
}

void compteur()
{
  count = count + 1;
}

void loop()
{
  int c = count;
  while (c == count);
  Serial.println(count);
}

Can somebody please give me a link to the definition of SQW so I can follow this ? (there seems to be more than one def)

You would find the datasheet of the DS1307 at this link:

The SQW is the square-wave signal which can be create by the DS1307, with the quartz component. It's possible to provide a square-wave signal at 1hz, 4096Hz, 8192Hz, or 32768Hz.

This is my first mistake. In the following there is the extract from the data sheet

SQW/OUT (Square Wave/Output Driver) – When enabled, the SQWE bit set to 1, the SQW/OUT pin outputs one of four square wave frequencies (1Hz, 4kHz, 8kHz, 32kHz). The SQW/OUT pin is open drain and requires an external pull-up resistor. SQW/OUT will operate with either Vcc or Vbat applied.

The pull-up resistor, it's true, I forgot it, and it's not present over the shield...

After you test it with the pullups, let us know if that fixed the problem that made you "upset" french style.. Then we can talk about
this:

I just want to count the seconds… in this case it will be possible to make a measurement for each minutes and a recording for each hours.

Did you get this working ?

It's RUNNING....Thanks Paul

The pull-up resistor was the solution.
I added a resistor at 2kOhm, I found some written which advice an Rp resistor between 1,5 and 3 kOhm, it's a classical value for i2c communication for a standard mode.

Just an additional precision: the DS1307 data sheet from DALLAS semiconductor is more detailed than Maxim Integrated especially about the need of pull-up resistor.

I'll begin my sketch for measurement and recording and I'll share about it we you.

Thanks all.

I added a resistor at 2kOhm, I found some written which advice an Rp resistor between 1,5 and 3 kOhm, it's a classical value for i2c communication for a standard mode.

Not really, the "classical" (read CLASSIC) value (the one in all the tutorials and documentation) is 4.7k ohm. Actually 10k would work but they prefer 4.7 k to be sure. 2 k is really overkill.

You are probably right.

I withdrew my 2kOhm for a 10 and finally a 4,7 and it's running correctly.
In the following you would find the link where I found this levels of resistors, but it's also talking about pull up for SDA and SCL, it's probably not the same for a SQW signal...??

Could you give me more details about the level of resistor pull-up? If we are agree about the level used for SDA & SCL, what is the risk for the SQW with a using of a weak level of pull up??

Thank you in advance

I believe it is across the board to include any serial interface but not SPI , I don't know why . It does include ONEWIRE devices.
Those and I2C are the only ones I have used it for but there may be others.

An i2c bus can be several hundred millimeters long and have quite a few devices attached to it, so a lower/stronger pullup value is appropriate. In your case only two pins are connected over a short distance, so 10K or Arduino's internal pullup would be suficient.

A lower pullup has two disadvantages. More power is wasted. The device might not be able to pull it down hard enough to make ita low signal.

A higher pullup also has disadvantages. The devices connected to the line might pull the level down so that it "floats" even when none of the devices are actually trying to pull it low (because of small leakage currents). Also, the inherant capacitance of the signal line and the devices on it would prevent high speed changes because of slow rise and fall times, so only lower i2c bus speeds would work.

Paul

Thanks so much.

I'm going to test my sketch to control measurement and recording, I'll come back probably to share about it with you perhaps to try to simplify it.

.

Hello all, I'm back.

This is in the following my sketch which is managing the measurements steps.
If someone have some time to take a look and help me to improve it...
I'm not a programmer, and I think some improvements are possible...

The idea is to build a weather station. I know it's a frequent subject, but I don't want a simple data logger, because a significant period of recording is one hour, but during this delay, some parameters like wind, or sun, can change a lot...
So, In this sketch, I'm just manage a writing event for each minute with a calculation of average value, minimum & maximum.
The measurement is just a CTN sensor put on the Analog pin A0, without translation.

For exemple, I'm using volatile value, is it necessary?
I'm wondering if it's not possible to create a sub function to calculate Average/Min/Max...??

Best regards

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68
#define THERM_PIN   0  

volatile int count;
volatile int therm;
volatile int MN_therm;
volatile int MX_therm;
volatile int INT_therm;
volatile int AV_therm;

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

// Gets the date and time from the ds1307 
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 if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void setup() //-------------------------------------------------------------------------------------------------------
{
  Wire.begin();
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0x07);
  Wire.write(0x10);
  Wire.endTransmission();
  attachInterrupt(0, compteur , RISING);
  Serial.begin(9600);
  Serial.print("Ana  Max  Min  Moy  __:__:__  __/__/__");
}

void compteur() //----------------------------------------------------------------------------------------------------
{
  count = count + 1; 
  if (count == 60)
  {
  count = 0;  
  }
}

void loop() //--------------------------------------------------------------------------------------------------------
{
  int c = count;
  
  while (c == count);
  
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  therm = analogRead(THERM_PIN);
  INT_therm = INT_therm + therm;
  AV_therm = INT_therm / 60;
    
      if (therm > MX_therm)
      {
      MX_therm = therm;
      } 
      else if (therm < MN_therm)
      {
      MN_therm = therm;
      } 
      else
      {
      therm = therm;
      } 
  
  if (second == 0)
    {
    Serial.print(therm);
    Serial.print("  ");
    Serial.print(MX_therm);  
    Serial.print("  ");
    Serial.print(MN_therm);
    Serial.print("  ");
    Serial.print(AV_therm);
    Serial.print("  ");
    Serial.print(hour);
    Serial.print(":");
    Serial.print(minute);
    Serial.print(":");
    Serial.print(second);
    Serial.print("  ");
    Serial.print(month);
    Serial.print("/");
    Serial.print(dayOfMonth);
    Serial.print("/");
    Serial.println(year);
    INT_therm = therm;
    AV_therm = therm;
    MN_therm = therm;
    MX_therm = therm; 
    } 

}

Hi kfmakr,

Only "count" needs to be volatile. It is the only one used in the interrupt code.

have a look at sprintf command. It is not mentioned in the reference section, you will have to google. It could make some parts of your sketch much shorter.

Paul