5

I'm able to set a time and to read it back without any problems but it doesn’t tick up. It stays the same. Even if I restart the serial monitor and thereby resets the buffer(?). So it seems to me that I'm able to set the registers but somehow the oscillator isn't working, do I have to tell it to use the external oscillator? Datasheet. Using Uno Rev3.

I've connected it like this:Schematic

Never mind the BAT54 diode and the "RTC+MCU_VCC" node, its all just backup power from a capacitor. The supply voltage is alright.

The code I've been using is a modified version of this.

// SDA analog pin 4
// SCL analog pin 5

#include <Wire.h>
const int MCP7940 = 0x6F; // Address of MCP7940 see data sheets
const char* days[] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const char* months[] =
{"January", "February", "March", "April", "May", "June", "July", "August","September", "October", "November", "December"};

// Initializes all values: 
byte second = 0;
byte minute = 0;
byte hour = 0;
byte weekday = 0;
byte monthday = 0;
byte month = 0;
byte year = 0;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  delay(2000); // This delay allows the MCU to read the current date and time.

  Serial.print("The current date and time is: ");
  printTime();
  Serial.println("Please change to newline ending the settings on the lower right of the Serial Monitor");
  Serial.println("Would you like to set the date and time now? Y/N");

  while (!Serial.available()) delay(10);
  if (Serial.read() == 'y' || Serial.read() == 'Y')

  // This set of functions allows the user to change the date and time
  {
    Serial.read();
    setTime();
    Serial.print("The current date and time is now: ");
    printTime();
  }


  Serial.println("Thank you.");
}

// Continuous function for converting bytes to decimals and vice versa
void loop() {
}
byte decToBcd(byte val) {
  return ((val/10*16) + (val%10));
}
byte bcdToDec(byte val) {
  return ((val/16*10) + (val%16));
}


// This set of codes is allows input of data
void setTime() {
  Serial.print("Please enter the current year, 00-99. - ");
  year = readByte();
  Serial.println(year);
  Serial.print("Please enter the current month, 1-12. - ");
  month = readByte();
  Serial.println(months[month-1]);
  Serial.print("Please enter the current day of the month, 1-31. - ");
  monthday = readByte();
  Serial.println(monthday);
  Serial.println("Please enter the current day of the week, 1-7.");
  Serial.print("1 Sun | 2 Mon | 3 Tues | 4 Weds | 5 Thu | 6 Fri | 7 Sat - ");
  weekday = readByte();
  Serial.println(days[weekday-1]);
  Serial.print("Please enter the current hour in 24hr format, 0-23. - ");
  hour = readByte();
  Serial.println(hour);
  Serial.print("Please enter the current minute, 0-59. - ");
  minute = readByte();
  Serial.println(minute);
  second = 0;
  Serial.println("The data has been entered.");

  // The following codes transmits the data to the RTC
  Wire.beginTransmission(MCP7940);
  Wire.write(byte(0));
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekday));
  Wire.write(decToBcd(monthday));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.write(byte(0));
  Wire.endTransmission();
  // Ends transmission of data
}


byte readByte() {
  while (!Serial.available()) delay(10);
  byte reading = 0;
  byte incomingByte = Serial.read();
  while (incomingByte != '\n') {
    if (incomingByte >= '0' && incomingByte <= '9')
      reading = reading * 10 + (incomingByte - '0');
    else;
    incomingByte = Serial.read();
  }
  Serial.flush();
  return reading;
}


void printTime() {
  char buffer[3];
  const char* AMPM = 0;
  readTime();
  Serial.print(days[weekday-1]);
  Serial.print(" ");
  Serial.print(months[month-1]);
  Serial.print(" ");
  Serial.print(monthday);
  Serial.print(", 20");
  Serial.print(year);
  Serial.print(" ");

  Serial.print(hour);
  Serial.print(":");

 Serial.print(minute);
 Serial.println();
}


void readTime() {
  Wire.beginTransmission(MCP7940);
  Wire.write(byte(0));
  Wire.endTransmission();
  Wire.requestFrom(MCP7940, 7);
  second = bcdToDec(Wire.read());
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read());
  weekday = bcdToDec(Wire.read());
  monthday = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = bcdToDec(Wire.read());
}

2 Answers2

6

Okey, I've been very tired when doing this but I think the problem was with bit 7 at adress 00h. The "seconds byte". That bit is called ST and turns on or off the oscillator. Doing a bitwise OR like this: Wire.write(decToBcd(second) | 128); sets it to "1" (128 = B10000000) and it's running now.

0

you have a small flaw in your readTime function. If you don't want very strange seconds from the device you should combine the two nibbles packed into the seconds byte. Like this:

void readTime() {
  Wire.beginTransmission(MCP7940);
  Wire.write(byte(0));
  Wire.endTransmission();
  Wire.requestFrom(MCP7940, 7);

  int rawsecond = Wire.read();
  second = bcdToDec( rawsecond & 112) + bcdToDec(rawsecond & 15);
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read());
  weekday = bcdToDec(Wire.read());
  monthday = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = bcdToDec(Wire.read());
}

Thanks for the sample - helped me quite a bit.

  • found another one. When accessing the weekday you also need to cut the correct bits out of the byte like this: weekday = bcdToDec(Wire.read() & 7); – Andreas Mar 26 '15 at 21:35