MCP79400 RTC get time

Good day, I am new working with real time clocks and arduino in general. Recently I've managed to get the MCP7940M working but using the same code doesn't work for the MCP79400 RTC. I can't find a library to work with it and I am unsure how to go about using the registers to get the date-time information. Help would be greatly appreciated!

A quick glance at the 7940 and 79400 datasheets leads me to believe they're pretty similar on the RTC software side. The RTC registers look the same, even the I2C address is the same. What exactly happened when you tried the MCP7940 library that leads you to believe that it doesn't work?

So the code I am running looks as follows:

#include <Wire.h>
#include <MCP7940.h>  // Include the MCP7940 RTC library
/***************************************************************************************************
** Declare all program constants                                                                  **
***************************************************************************************************/
const uint32_t SERIAL_SPEED{115200};     // Set the baud rate for Serial I/O
const uint8_t  LED_PIN{13};              // Arduino built-in LED pin number
const uint8_t  SPRINTF_BUFFER_SIZE{32};  // Buffer size for sprintf()
/***************************************************************************************************
** Declare global variables and instantiate classes                                               **
***************************************************************************************************/
MCP7940_Class MCP7940;                           // Create an instance of the MCP7940
char          inputBuffer[SPRINTF_BUFFER_SIZE];  // Buffer for sprintf()/sscanf()
#define I2C_SLAVE_ADDR 0x08 // 7-bit I2C address of the PIC16F1829


void readCommand() {
  static uint8_t inputBytes = 0;              // Variable for buffer position
  while (Serial.available()) {                // Loop while incoming serial data
    inputBuffer[inputBytes] = Serial.read();  // Get the next byte of data
    if (inputBuffer[inputBytes] != '\n' &&
        inputBytes < SPRINTF_BUFFER_SIZE)  // keep on reading until a newline
      inputBytes++;                        // shows up or the buffer is full
    else {
      inputBuffer[inputBytes] = 0;                 // Add the termination character
      for (uint8_t i = 0; i < inputBytes; i++)     // Convert the whole input buffer
        inputBuffer[i] = toupper(inputBuffer[i]);  // to uppercase characters
      Serial.print(F("\nCommand \""));
      Serial.write(inputBuffer);
      Serial.print(F("\" received.\n"));
      /**********************************************************************************************
      ** Parse the single-line command and perform the appropriate action. The current list of **
      ** commands understood are as follows: **
      ** **
      ** SETDATE      - Set the device time **
      ** CALDATE      - Calibrate device time **
      ** **
      **********************************************************************************************/
      enum commands { SetDate, CalDate, Unknown_Command };  // of commands enumerated type
      commands command;                                     // declare enumerated type
      char     workBuffer[10];                              // Buffer to hold string compare
      sscanf(inputBuffer, "%s %*s", workBuffer);            // Parse the string for first word
      if (!strcmp(workBuffer, "SETDATE"))
        command = SetDate;  // Set command number when found
      else if (!strcmp(workBuffer, "CALDATE"))
        command = CalDate;  // Set command number when found
      else
        command = Unknown_Command;                              // Otherwise set to not found
      uint16_t tokens, year, month, day, hour, minute, second;  // Variables to hold parsed dt/tm
      switch (command) {                                        // Action depending upon command
        /*******************************************************************************************
        ** Set the device time and date                                                           **
        *******************************************************************************************/
        case SetDate:  // Set the RTC date/time
          tokens = sscanf(inputBuffer, "%*s %hu-%hu-%hu %hu:%hu:%hu;", &year, &month, &day, &hour,
                          &minute, &second);
          if (tokens != 6)  // Check to see if it was parsed
            Serial.print(F("Unable to parse date/time\n"));
          else {
            MCP7940.adjust(
                DateTime(year, month, day, hour, minute, second));  // Adjust the RTC date/time
            Serial.print(F("Date has been set."));
          }       // of if-then-else the date could be parsed
          break;  //
        /*******************************************************************************************
        ** Calibrate the RTC and reset the time                                                   **
        *******************************************************************************************/
        case CalDate:  // Calibrate the RTC
          tokens = sscanf(inputBuffer,
                          "%*s %hu-%hu-%hu %hu:%hu:%hu;",  // Use sscanf() to parse the date/
                          &year, &month, &day, &hour, &minute, &second);  // time into variables
          if (tokens != 6)  // Check to see if it was parsed
            Serial.print(F("Unable to parse date/time\n"));
          else {
            int8_t trim =
                MCP7940.calibrate(DateTime(year, month, day,  // Calibrate the crystal and return
                                           hour, minute, second));  // the new trim offset value
            Serial.print(F("Trim value set to "));
            Serial.print(trim * 2);  // Each trim tick is 2 cycles
            Serial.println(F(" clock cycles every minute"));
          }  // of if-then-else the date could be parsed
          break;
        /*******************************************************************************************
        ** Unknown command                                                                        **
        *******************************************************************************************/
        case Unknown_Command:  // Show options on bad command
        default:
          Serial.println(F("Unknown command. Valid commands are:"));
          Serial.println(F("SETDATE yyyy-mm-dd hh:mm:ss"));
          Serial.println(F("CALDATE yyyy-mm-dd hh:mm:ss"));
      }                // of switch statement to execute commands
      inputBytes = 0;  // reset the counter
    }                  // of if-then-else we've received full command
  }                    // of if-then there is something in our input buffer
}  // of method readCommand









void setup() {
  Serial.begin(115200);
  
#ifdef __AVR_ATmega32U4__      // If this is a 32U4 processor, then
  delay(3000);                 // wait 3 seconds for the serial
#endif                         // interface to initialize
  Serial.print(F("\nStarting SetAndCalibrate program\n"));
  Serial.print(F("- Compiled with c++ version "));
  Serial.print(F(__VERSION__));  // Show compiler information
  Serial.print(F("\n- On "));
  Serial.print(F(__DATE__));
  Serial.print(F(" at "));
  Serial.print(F(__TIME__));
  Serial.print(F("\n"));
  while (!MCP7940.begin()) {  // Initialize RTC communications
    Serial.println(F("Unable to find MCP7940M. Checking again in 3s."));  // Show error text
    delay(3000);                                                          // wait a second
  }  // of loop until device is located
  Serial.println(F("MCP7940 initialized."));
  while (!MCP7940.deviceStatus()) {  // Turn oscillator on if necessary
    Serial.println(F("Oscillator is off, turning it on."));
    bool deviceStatus = MCP7940.deviceStart();  // Start oscillator and return state
    if (!deviceStatus) {                        // If it didn't start
      Serial.println(F("Oscillator did not start, trying again."));  // Show error and
      delay(1000);                                                   // wait for a second
    }                // of if-then oscillator didn't start
  }                  // of while the oscillator is off
  MCP7940.adjust();  // Set to library compile Date/Time
  Serial.println(F("Enter the following serial commands:"));
  Serial.println(F("SETDATE yyyy-mm-dd hh:mm:ss"));
  Serial.println(F("CALDATE yyyy-mm-dd hh:mm:ss"));
  pinMode(LED_PIN, OUTPUT);  // Declare built-in LED as output
  Wire.begin();
}

void loop() {
  // From my understanding, the Arduino Wire library handles all Ack and Nack bits
  Wire.requestFrom(I2C_SLAVE_ADDR, 1); // Requests data from slave
  byte data = Wire.read(); // NACK sent by slave once read
  byte data2 = Wire.read(); // NACK sent by slave once read
  

  if (data != 0  || data!= 255) { // Read data followed by the ACK received
  if(data==5)
  {
    Serial.println("Correct Token Received: 01x02x03x05");
                                // See if serial port had incoming
  }
   if(data==6)
  {
    Serial.println("Correct Token Received: 01x02x03x06");
      static uint8_t secs;                 // store the seconds value
  DateTime       now = MCP7940.now();  // get the current time
  if (secs != now.second()) {          // Output if seconds have changed
    sprintf(inputBuffer, "%04d-%02d-%02d %02d:%02d:%02d",
            now.year(),  // Use sprintf() to pretty print
            now.month(), now.day(), now.hour(), now.minute(),
            now.second());                         // date/time with leading zeros
    Serial.println(inputBuffer);                   // Display the current date/time
    secs = now.second();                           // Set the counter variable
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));  // Toggle the LED
  }                                                // of if the seconds have changed
  readCommand();                                   // See if serial port had incoming
  }
  }


  delay(50);
}


Which was made for the MCP79400 as well I think. The output it gives is that the MCP7940 is not detected. I tried the other I2C address as well by changing it in the header file but no luck.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.