WiFly Shield - Real Time Clock RTC Grabber

Your source for all things Atmel.

Moderator: phalanx

Post Reply
Shouden
Posts: 1
Joined: Sun Mar 11, 2012 12:17 am

WiFly Shield - Real Time Clock RTC Grabber

Post by Shouden » Sun Mar 11, 2012 1:20 am

After installing my WiFly shield on top of my Uno, I configured the WiFly through the Terminal sketch. Through this process, I learned that the WiFly has a built-in Ream Time Clock. I configured it to automatically utilize NTP to synchronize when the device establishes a WiFi connection to the Internet.

When I got to pulling the time from the sketch, it appears that the system clock is tracked separately from the real time clock on the WiFly chip. So I set to pulling down or grabbing the time from WiFly's RTC. Unfortunately, it appears there is no built-in command to do this. So I was forced to write my own code to perform this. It took me the better part of 6 hours to figured this out, so hopefully this helps someone else accomplish this in less time. Provided that your WiFly is using the newest firmware (2.32 for me), your RTC outputs the time as a UNIX timestamp. This is easily usable to setTime() so that your system clock matches your RTC.

Code: Select all

/*
  WiFly_pullTime - tool to synchronize the system clock to the WiFly RTC
  
  Loosely based on:
    SpiUartTerminal - tool to help troubleshoot problems with WiFly shield
    Copyright (c) 2010 SparkFun Electronics. http://sparkfun.com LGPL 3.0
  
  Copyright (c) 2012 Maxwell Rathbone
  
  It is imperative that you upgrade the firmware on your WiFly card to ensure that your RTC chip 
  returns a UNIX timestamp. To upgrade your firmware, simply type 'ftp u' from the WiFly 
  SpiUartTerminal  

  You will need to ensure that NTP is set up on your WiFly card manually. Ensure that it is set to
  synchronized automatically. This script does not handle NTP synchronization as the module handles
  it internally and automatically.
*/

#include "Time.h";
#include "WiFly.h" // We use this for the preinstantiated SpiSerial object.

void setup() {
  Serial.begin(9600); // Establish Serial connection for output
}

void loop() {
 setTime(grabTime()); // Set the system clock to match the WiFly RTC
 adjustTime(-14400); // Adjust the time for Eastern Time Zone (GMT-4 as of 3/11)
 digitalClockDisplay(); // Display the system clock time to the Serial monitor
 delay(1300); // Delay 2 seconds before continuing
}

long grabTime(void)
{
 SpiSerial.begin(); 
 delay(250); // The delay buffer before and after were pulled from the WiFly library itself
 SpiSerial.print("$$$");
 delay(250); // The delay buffer before and after were pulled from the WiFly library itself
 SpiSerial.println("\n"); // The WiFly library also recommended two carraige returns to clear things up
 Flush_RX(); // I added this last bit to clear out the receive buffer in preparation for pulling the time
 // Without this Flush_RX() here, potentially the first couple results returned would not be accurate

 SpiSerial.println("show t t"); // Request the current RTC value from the WiFly card
 int linesSoFar=0; // Variable to track the line number in the output we receive
 int afterEquals=0; // Flag to trigger after equals sign -- when the RTC value begins
 char timestr[12]=""; // Variable to store the UNIX timestamp from the RTC clock
 int charNumber=0; // Counter to store the position number inside the UNIX timestamp char above

 // This for loop runs with a total delay of 100ms to ensure that the results of the command have been received
 // before allowing the program to loop and accept more input. Without this forced acceptance of incoming data,
 // unexpected results can be seen.
 for(int z=0;z<=100;z++) 
   {     
    // Loop while there is incoming data from the WiFly module(in response to our show t t command above)
    while(SpiSerial.available() > 0) 
      {
       char c = SpiSerial.read(); // Read in one character
       if(c=='\n') linesSoFar++; // If the character read in is a line feed, then add one to the counter for number of lines

       // Potential lines might look like: RTC=1331449728
       if(linesSoFar==3) // The third line in the results contains the RTC value
         {
          if(afterEquals==1) // Only perform the code below if our character position on the RTC line is after the =
            { timestr[charNumber] = (char)c; charNumber++; } // Store the character into our character array
          if(c=='=') afterEquals=1; // If the current character is an equals, the next character begins our RTC value -- throw flag
         }
      }
    delay(1); // Delay for 1ms
   }
   long returnL = strToLong(timestr); // Convert our character aray into a long
   return(returnL);
}

// I found this command to be needed so that the receive buffers are flushed
// This helps normalize output so that the time grabbing works consistently
void Flush_RX()
{
 for(int z=0;z<=100;z++) 
   {     
    // Loop while there is incoming data from the WiFly module(in response to our show t t command above)
    while(SpiSerial.available() > 0) 
       char c = SpiSerial.read(); // Read in one character
    delay(1);
   }
 return;
}

// Pulled from: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286545227
long strToLong(String s) { char arr[12]; s.toCharArray(arr, sizeof(arr)); return atol(arr); }

// Part of the standard Time library examples
void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

// Part of the standard Time library examples
void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits);
}

Post Reply