RTClib.h and DS3231

In the RTClib.h there is an example program for DS1307 square wave output generator. I have this converted for DS3231.

However, the serial monitor shows the wrong messages: instead of the sequence "OFF", "1Hz", '1.024kHz", "4.096kHz", "8.192kHz" the monitor puts out the following:
"1Hz", 1Hz", "1Hz", "4.096kHz", "4.096kHz"

The actual frequencies put out however are correct.

Following is the example program, underneath is the actual (converted) program:

// SQW/OUT pin mode using a DS1307 RTC connected via I2C.
//
// According to the data sheet (http://datasheets.maxim-ic.com/en/ds/DS1307.pdf), the
// DS1307's SQW/OUT pin can be set to low, high, 1Hz, 4.096kHz, 8.192kHz, or 32.768kHz.
//
// This sketch reads the state of the pin, then iterates through the possible values at
// 5 second intervals.
//

// NOTE:
// You must connect a pull up resistor (~10kohm) from the SQW pin up to VCC.  Without
// this pull up the wave output will not work!

#include <Wire.h>
#include "RTClib.h"

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

RTC_DS1307 rtc;

int mode_index = 0;

Ds1307SqwPinMode modes[] = {OFF, ON, SquareWave1HZ, SquareWave4kHz, SquareWave8kHz, SquareWave32kHz};


void print_mode() {
  Ds1307SqwPinMode mode = rtc.readSqwPinMode();
  
  Serial.print("Sqw Pin Mode: ");
  switch(mode) {
  case OFF:             Serial.println("OFF");       break;
  case ON:              Serial.println("ON");        break;
  case SquareWave1HZ:   Serial.println("1Hz");       break;
  case SquareWave4kHz:  Serial.println("4.096kHz");  break;
  case SquareWave8kHz:  Serial.println("8.192kHz");  break;
  case SquareWave32kHz: Serial.println("32.768kHz"); break;
  default:              Serial.println("UNKNOWN");   break;
  }
}

void setup () {

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(57600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  print_mode();
}

void loop () {
  rtc.writeSqwPinMode(modes[mode_index++]);
  print_mode();

  if (mode_index > 5) {
    mode_index = 0;
  }

  delay(5000);
}

Here is the converted program working with a DS3231 (included and enumerated in the RTClib.h library):

// https://github.com/adafruit/RTClib/blob/master/examples/ds1307SqwPin/ds1307SqwPin.ino
// Aangepast voor DS3231

// SQW/OUT pin mode using a DS3231 RTC connected via I2C.
//
// According to the data sheet (http://datasheets.maxim-ic.com/en/ds/DS1307.pdf), the
// DS1307's SQW/OUT pin can be set to low, 1Hz, 1.024kHz, 4.096kHz, 8.192kHz.
//
// This sketch reads the state of the pin, then iterates through the possible values at
// 5 second intervals.
//

#include <Wire.h>
#include "RTClib.h"

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endif

RTC_DS3231 rtc;
int mode_index = 0;
Ds3231SqwPinMode modes[] = {DS3231_OFF, DS3231_SquareWave1Hz, DS3231_SquareWave1kHz, DS3231_SquareWave4kHz, DS3231_SquareWave8kHz};
const byte rtcTimerIntPin = 2;
volatile byte flag = false;

void setup () {

  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (rtcTimerIntPin, INPUT_PULLUP);
  attachInterrupt (digitalPinToInterrupt (rtcTimerIntPin), rtc_interrupt, CHANGE);

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(57600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

}

void rtc_interrupt ()
{
  flag = true;
}  // end of rtc_interrupt


void print_mode() {
  Ds3231SqwPinMode mode = rtc.readSqwPinMode();

  Serial.print("Sqw Pin Mode: ");
  switch (mode) {
    case DS3231_OFF:             Serial.println("OFF");       break;
    case DS3231_SquareWave1Hz:   Serial.println("1Hz");       break;
    case DS3231_SquareWave1kHz:  Serial.println("1.024kHz");  break;
    case DS3231_SquareWave4kHz:  Serial.println("4.096kHz");  break;
    case DS3231_SquareWave8kHz: Serial.println("8.192kHz"); break;
    default:              Serial.println("UNKNOWN");   break;
  }
}

void loop () {
  rtc.writeSqwPinMode(modes[mode_index++]);
  print_mode();

  if (mode_index > 4) {
    mode_index = 0;
  }

  delay(5000);
}

There is a bug in the readSqwPinMode() function in the DS3231 portion of the library. It is incorrectly using the read mask from the DS1307 readSqwPinMode() function. If you modify the .cpp code in the library as below, the print out is correct. Look at the writeSwqPinMode() function to help explain the revised mask and treatment of mode ==0x04.
It will be helpful for you to have the data sheets for the DS1307 and DS3231 available.

Ds3231SqwPinMode RTC_DS3231::readSqwPinMode() {
  int mode;

  Wire.beginTransmission(DS3231_ADDRESS);
  Wire._I2C_WRITE(DS3231_CONTROL);
  Wire.endTransmission();
  
  Wire.requestFrom((uint8_t)DS3231_ADDRESS, (uint8_t)1);
  mode = Wire._I2C_READ();

  //mode &= 0x93;//bug due to using ds1307 read mask
  mode &= 0x1C;
  if(mode == 0x04)
	  mode = DS3231_OFF;
  return static_cast<Ds3231SqwPinMode>(mode);
}
Sqw Pin Mode: OFF
Sqw Pin Mode: 1Hz
Sqw Pin Mode: 1.024kHz
Sqw Pin Mode: 4.096kHz
Sqw Pin Mode: 8.192kHz

cattledog:
There is a bug in the readSqwPinMode() function in the DS3231 portion of the library. It is incorrectly using the read mask from the DS1307 readSqwPinMode() function. If you modify the .cpp code in the library as below, the print out is correct. Look at the writeSwqPinMode() function to help explain the revised mask and treatment of mode ==0x04.
It will be helpful for you to have the data sheets for the DS1307 and DS3231 available.

(...)

OMG!! Is there something you do not know? Thank you very much, I stand in admiration.
+1

It would be great if one of you would take a few minutes to submit a pull request to the GitHub repository for the library to fix this bug:

I did a quick search through the issues and pull requests and didn't find anything about this.

Done. Issue #81

cattledog:
Done. Issue #81

I am glad you did it, I would not have known (yet) how to do that. I see it is not a "Pull Request" but an "Issue": what is the difference,?

brice3010:
what is the difference,?

Issues are used to report bugs.

Pull requests are used to submit proposals to change the content of a repository. For example, you could submit a pull request that proposes to change line 487 of RTClib.cpp from:

 mode &= 0x93;

to:

 mode &= 0x1C;

They are both valuable ways to contribute to an open source repository.

I use issues when I have identified a bug but I don't know the solution to the bug. It's still very helpful to report bugs but it puts more of the burden of work on others, and thus may cause more delay before the bug is fixed. In a situation like this where I have identified an issue and also know how to fix it a pull request is a better option because it makes it very easy to see what changes are proposed. Once the maintainer of the repository has reviewed the proposal they can simply click the "Merge" button and the changes are automatically made.

pert:
Issues are used to report bugs.

Pull requests are used to submit proposals to change the content of a repository. For example, you could submit a pull request that proposes to change line 487 of RTClib.cpp from:

 mode &= 0x93;

to:

 mode &= 0x1C;

They are both valuable ways to contribute to an open source repository.

I use issues when I have identified a bug but I don't know the solution to the bug. It's still very helpful to report bugs but it puts more of the burden of work on others, and thus may cause more delay before the bug is fixed. In a situation like this where I have identified an issue and also know how to fix it a pull request is a better option because it makes it very easy to see what changes are proposed. Once the maintainer of the repository has reviewed the proposal they can simply click the "Merge" button and the changes are automatically made.

You have the gift of the explanation. Thank you.