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.