chronodot v2.1 sqm

For RTC breakouts, etc., use the Other Products from Adafruit forum

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
momber
 
Posts: 3
Joined: Sat Dec 27, 2014 5:30 pm

chronodot v2.1 sqm

Post by momber »

Hi,

I've been trying to get an alarm once per minute (0 seconds of every minute) working but can't seem to figure out how to do it.
My setup is an Arduino mega 2560 r3 + ethernet shield r3 and chronodot.
The sqm pin is connected to pin2 (interrupt 0) on the arduino and has a 10k pullup resistor.
Instead of connecting to pin2 I also tried it connected to a led but ... nothing, I could however get the 1hz signal working to blink the led.

I've been thru several webpages and few posts here about chronodot alarm but hasn't helped yet, but I think I'm close :s

//set alarm 1
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x07);
Wire.write(0x0);
Wire.write(0x80);
Wire.write(0x80);
Wire.write(0x80);
Wire.endTransmission();

//set alarm 2
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write (0x0B);
Wire.write (0x80);
Wire.write (0x80);
Wire.write (0x80);
Wire.endTransmission();

Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0F); //select status registers,
Wire.write(0x0);//reset alarm
Wire.endTransmission();

Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(0x0E);
Wire.write(0x06);
Wire.endTransmission();


output:

Code: Select all

Initializing ethernet ... success
* Ip address: 192.168.124.223
Initializing SD card ... success
* Card type: SDHC
* Volume type is FAT; 32
* Volume size (bytes): 4062707712
* Volume size (Kbytes): 3967488
* Volume size (Mbytes): 3874
Requesting time from time.nist.gov ... success
* Unix time: 1419717063
* UTC Date/time: 2014-12-27 21:51:3
Chronodot registers: 
0	11
1	1010001
2	100001
3	0
4	100111
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	0
2014-12-27 21:51:3
2014-12-27 21:51:4
2014-12-27 21:51:5
2014-12-27 21:51:6
2014-12-27 21:51:7
2014-12-27 21:51:8
2014-12-27 21:51:9
2014-12-27 21:51:10
my sketch:

Code: Select all

#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SD.h>
#include <RTClib.h>

#define DEBUG_ETH true
#define DEBUG_SD true
#define DEBUG_CLOCK true

#define PIN_ETHLED 48
#define PIN_SDLED 47
#define PIN_CLOCKLED 49

#define PIN_INTERRUPTPIN2 0

#define PIN_ALARMINTERRUPT PIN_INTERRUPTPIN2

#define CLOCK_ADDRESS 0x68

bool isEthAvailable = false;
bool isSdAvailable = false;
bool isClockAvailable = false;

byte mac[] = { 0xDE, 0xAD, 0xAC, 0xDE, 0xFE, 0xED };

unsigned int udpLocalPort = 55425;
const char *timeServer = "time.nist.gov";

const int NTP_PACKET_SIZE= 48;
byte ntpPacketBuffer[ NTP_PACKET_SIZE];

EthernetUDP Udp;
Sd2Card card;
SdVolume volume;

RTC_DS1307 rtc;

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }
 
  Wire.begin();
  
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0E);
  Wire.write(0x4);
  Wire.endTransmission();
    
  pinMode(PIN_ETHLED, OUTPUT);
  digitalWrite(PIN_ETHLED, LOW);
  
  pinMode(PIN_SDLED, OUTPUT);
  digitalWrite(PIN_SDLED, LOW);
  
  pinMode(PIN_CLOCKLED, OUTPUT);
  digitalWrite(PIN_CLOCKLED, LOW); 
  
  
  pinMode(53, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWrite(4,HIGH);
  
  pinMode(PIN_ALARMINTERRUPT, INPUT);
  
  
  if (!isEthAvailable) {
    initializeEth();
    if (!isEthAvailable)
      return;
    else
      Udp.begin(udpLocalPort);
  }
  if (!isSdAvailable)
    initializeSd();
  if (isEthAvailable && !isClockAvailable)
    SetClock();
}

void loop() {
  DateTime dt = rtc.now();
  Serial.print(dt.year());
  Serial.print(F("-"));
  Serial.print(dt.month());
  Serial.print(F("-"));
  Serial.print(dt.day());
  Serial.print(F(" "));
  Serial.print(dt.hour());
  Serial.print(F(":"));
  Serial.print(dt.minute());
  Serial.print(F(":"));
  Serial.println(dt.second());
  delay(1000);
}

void OnAlarm() {
  Serial.println("On alarm");
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x0);//reset alarm
  Wire.endTransmission();
}

void initializeEth() {
  digitalWrite(PIN_ETHLED, LOW);
  isEthAvailable = false;
  if (DEBUG_ETH)
    Serial.print(F("Initializing ethernet ... "));
  if (Ethernet.begin(mac) == 0) {
    if (DEBUG_ETH)
      Serial.println(F("failed"));
      return;
  }
  if (DEBUG_ETH) {
    IPAddress ip = Ethernet.localIP();
    Serial.println(F("success"));
    Serial.print(F("* Ip address: "));
    for (byte thisByte = 0; thisByte < 4; thisByte++) {
      if (thisByte < 3) {
        Serial.print(ip[thisByte], DEC);
        Serial.print(".");
      }
      else
        Serial.println(ip[thisByte], DEC);
    }
  }
  digitalWrite(PIN_ETHLED, HIGH);
  isEthAvailable = true;
}

void initializeSd() {
  digitalWrite(PIN_SDLED, LOW);
  isSdAvailable = false;
  if (DEBUG_SD) 
    Serial.print(F("Initializing SD card ... "));
  if (!card.init(SPI_HALF_SPEED, 4)) {
    if (DEBUG_SD) {
      Serial.println(F("failed"));
      Serial.println(F("* is a card is inserted?"));
      Serial.println(F("* Is your wiring correct?"));
      Serial.println(F("* did you change the chipSelect pin to match your shield or module?"));
    }
    return;
  } else if (DEBUG_SD) {
    Serial.println(F("success"));
  }

  // print the type of card
  if (DEBUG_SD) {
    Serial.print(F("* Card type: "));
    switch (card.type()) {
      case SD_CARD_TYPE_SD1:
        Serial.println(F("SD1"));
        break;
      case SD_CARD_TYPE_SD2:
        Serial.println(F("SD2"));
        break;
      case SD_CARD_TYPE_SDHC:
        Serial.println(F("SDHC"));
        break;
      default:
        Serial.println(F("Unknown"));
    }
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    if (DEBUG_SD)
      Serial.println(F("* Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"));
    return;
  }
  if (DEBUG_SD) {
    // print the type and size of the first FAT-type volume
    uint32_t volumesize;
    Serial.print(F("* Volume type is FAT; "));
    Serial.println(volume.fatType(), DEC);
  
    volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
    volumesize *= volume.clusterCount();       // we'll have a lot of clusters
    volumesize *= 512;                            // SD card blocks are always 512 bytes
    Serial.print(F("* Volume size (bytes): "));
    Serial.println(volumesize);
    Serial.print(F("* Volume size (Kbytes): "));
    volumesize /= 1024;
    Serial.println(volumesize);
    Serial.print(F("* Volume size (Mbytes): "));
    volumesize /= 1024;
    Serial.println(volumesize);
  }
  digitalWrite(PIN_SDLED, HIGH);
  isSdAvailable = true;
}

void SetClock() {
  isClockAvailable = false;
  digitalWrite(PIN_CLOCKLED, LOW);
  if (DEBUG_CLOCK) {
    Serial.print(F("Requesting time from "));
    Serial.print(timeServer);
    Serial.print(" ... ");
  }
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);
  if (!Udp.parsePacket()) {
    if (DEBUG_CLOCK)
      Serial.println(F("failed"));
      return;
  }
  if (DEBUG_CLOCK)
    Serial.println(F("success"));
  Udp.read(ntpPacketBuffer, NTP_PACKET_SIZE);
  unsigned long highWord = word(ntpPacketBuffer[40], ntpPacketBuffer[41]);
  unsigned long lowWord = word(ntpPacketBuffer[42], ntpPacketBuffer[43]);
  // combine the four bytes (two words) into a long integer
  // this is NTP time (seconds since Jan 1 1900):
  unsigned long secsSince1900 = highWord << 16 | lowWord;
  const unsigned long seventyYears = 2208988800UL;
  unsigned long unixTime = secsSince1900 - seventyYears;
  if (DEBUG_CLOCK) {
    Serial.print(F("* Unix time: "));
    Serial.println(unixTime, DEC);
  }
    
  DateTime dt = DateTime(unixTime);
  if (DEBUG_CLOCK) {
    Serial.print(F("* UTC Date/time: "));
    Serial.print(dt.year());
    Serial.print(F("-"));
    Serial.print(dt.month());
    Serial.print(F("-"));
    Serial.print(dt.day());
    Serial.print(F(" "));
    Serial.print(dt.hour());
    Serial.print(F(":"));
    Serial.print(dt.minute());
    Serial.print(F(":"));
    Serial.println(dt.second());
  }
    
  rtc.adjust(dt);
  
  //set alarm 1
  Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write(0x07);
    Wire.write(0x0);  
    Wire.write(0x80);
    Wire.write(0x80);
    Wire.write(0x80);
  Wire.endTransmission();

  //set alarm 2
  Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write (0x0B);
    Wire.write (0x80);
    Wire.write (0x80);
    Wire.write (0x80);
  Wire.endTransmission();
  
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0F); //select status registers, 
  Wire.write(0x0);//reset alarm
  Wire.endTransmission();
  
  Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write(0x0E);        //control register 0E
    Wire.write(0x06); 
  Wire.endTransmission();
  
  
  printClockRegisters();
  
  
  attachInterrupt(PIN_ALARMINTERRUPT, OnAlarm, RISING);
  digitalWrite(PIN_CLOCKLED, HIGH);
  isClockAvailable = true;
}

unsigned long sendNTPpacket(const char* address) {
  // set all bytes in the buffer to 0
  memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  ntpPacketBuffer[0] = 0b11100011;   // LI, Version, Mode
  ntpPacketBuffer[1] = 0;     // Stratum, or type of clock
  ntpPacketBuffer[2] = 6;     // Polling Interval
  ntpPacketBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  ntpPacketBuffer[12]  = 49;
  ntpPacketBuffer[13]  = 0x4E;
  ntpPacketBuffer[14]  = 49;
  ntpPacketBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:         
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(ntpPacketBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

void printClockRegisters() {
  Serial.println("Chronodot registers: ");
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0);
  Wire.endTransmission();
  for (int reg = 0x0; reg <= 0x0F;reg++) {
    Wire.requestFrom(CLOCK_ADDRESS, 1);
    Serial.print(reg, HEX);
    Serial.print("\t");
    Serial.println(Wire.read(), BIN);
  }
}

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: chronodot v2.1 sqm

Post by adafruit_support_bill »

Code: Select all

void OnAlarm() {
  Serial.println("On alarm");
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0F);
  Wire.write(0x0);//reset alarm
  Wire.endTransmission();
}
You can't call into the wire library from an interrupt handler. Wire uses interrupts for communication, but interrupts are disabled on entry to the handler.

You can re-enable interrupts within the handler, but that is generally bad practice. Better to set a flag in the handler and handle the reset in your loop.

Also, it is not a good idea to do serial I/O from the handler either. Current versions of the Arduino serial library are asynchronous - but only to the point that the buffer fills up.

User avatar
momber
 
Posts: 3
Joined: Sat Dec 27, 2014 5:30 pm

Re: chronodot v2.1 sqm

Post by momber »

Hi, thanks for your reply.

I've changed the OnAlarm and loop now but still don't get the alarm triggered.

Code: Select all

volatile bool alarmTriggered = false;
void loop() {
  if (alarmTriggered) {
    alarmTriggered = false;
    Serial.println("On alarm");
    Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write(0x0F); //select status registers, 
    Wire.write(0b00000000);//reset alarm
    Wire.endTransmission();
  }
  DateTime dt = rtc.now();
  Serial.print(dt.year());
  Serial.print(F("-"));
  Serial.print(dt.month());
  Serial.print(F("-"));
  Serial.print(dt.day());
  Serial.print(F(" "));
  Serial.print(dt.hour());
  Serial.print(F(":"));
  Serial.print(dt.minute());
  Serial.print(F(":"));
  Serial.println(dt.second());
  delay(500);
}

void OnAlarm() {
  alarmTriggered = true;
}
Also removed the "pinMode(PIN_ALARMINTERRUPT, INPUT);" since I don't think its needed.

User avatar
momber
 
Posts: 3
Joined: Sat Dec 27, 2014 5:30 pm

Re: chronodot v2.1 sqm

Post by momber »

Excellent, I finally have it working by moving the attachInterrupt up and change it to falling:

Code: Select all

  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(0x0F); //select status registers, 
  Wire.write(0x0);//reset alarm
  Wire.endTransmission();
  
  attachInterrupt(PIN_ALARMINTERRUPT, OnAlarm, FALLING);
  
  Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write(0x0E);        //control register 0E
    Wire.write(0x06); 
  Wire.endTransmission();
output alarm working:

Code: Select all

2014-12-28 13:56:58
Chronodot registers: 
0	1011000
1	1010110
2	10011
3	0
4	101000
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	0
On alarm
2014-12-28 13:57:0
Chronodot registers: 
0	0
1	1010111
2	10011
3	0
4	101000
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	0
I noticed while printing the clock registers every second that the 3th bit in the status register sometimes gets high (0x0F -> 100) and the next loop it's low again.
What causes this?

3th bit high at 21sec:

Code: Select all

2014-12-28 14:1:20
Chronodot registers: 
0	100000
1	1
2	10100
3	0
4	101000
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	0
2014-12-28 14:1:21
Chronodot registers: 
0	100001
1	1
2	10100
3	0
4	101000
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	100
2014-12-28 14:1:22
Chronodot registers: 
0	100010
1	1
2	10100
3	0
4	101000
5	10010
6	10100
7	0
8	10000000
9	10000000
A	10000000
B	10000000
C	10000000
D	10000000
E	110
F	0

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: chronodot v2.1 sqm

Post by adafruit_support_bill »

I noticed while printing the clock registers every second that the 3th bit in the status register sometimes gets high (0x0F -> 100) and the next loop it's low again.
bit 2 of the status register is the busy bit.
http://datasheets.maximintegrated.com/en/ds/DS3231.pdf

Locked
Please be positive and constructive with your questions and comments.

Return to “Clock Kits (discontinued)”