rtc ppm calibration?

Hi im trying to calibarate an rtc(mcp79410) and it allows for +/- 125ppm adjustment idk how much that means in time but with 0 it runs about 4 seconds slow in a day and with -1 it runs about 4 seconds fast How should I handle this to actually get it accuract?

sync it with an NTP server every 6 hours. Check - http://arduino.cc/playground/Main/DS1307OfTheLogshieldByMeansOfNTP -

There are 24*60*60 seconds per day, so one part per million is .0864 seconds per day. The device allows you to adjust up to +/- 125 which is +/-10.8 seconds per day. Four seconds would be an adjustment of 125*4/10.8 = 46. So set it to 46 and see how much that corrects it. I don't know whether you have to set it to +46 or -46 to correct it but give + a shot. If that doesn't work try -46. BTW. If it is 4 seconds slow with an adjustment of zero, it's extremely unlikely that it could be 4 seconds fast with an adjustment of -1. Are you sure you sure you didn't set it to its maximum negative value when you tried -1? Post your code.

Pete

its for a mobile project so the ethernet is not a possibility : / heres the code that sets the calibration,

    if(_command[0] == '~'){
      int temp;
      temp = _command[2] - 48;
      temp = temp * 10;
      temp = temp + (_command[3] - 48);
      if(_command[1] == 'S') MCP.setSeconds(temp);
      if(_command[1] == 'M') MCP.setMinutes(temp);
      if(_command[1] == 'H') MCP.setHours(temp);
      if(_command[1] == 'D') MCP.setDay(temp);
      if(_command[1] == 'd') MCP.setDate(temp);
      if(_command[1] == 'm') MCP.setMonth(temp);
      if(_command[1] == 'Y') MCP.setYear(temp);
      if(_command[1] == 'C') MCP.calibrate(temp);
      if(_command[1] == 'c') MCP.calibrate(-(temp));


    }

which refers to this library i made

void MCP::calibrate(int calibration){
MCPwrite(0x08, calibration);

void MCP::MCPwrite(int address, int value){
 Wire.beginTransmission(RTCC);
 Wire.write(address);
 Wire.write(value);
 Wire.endTransmission(); 
}

}

heres the reference for calibration

4.2.3 CALIBRATION
The MCP7941X utilizes digital calibration to correct for
inaccuracies of the input clock source (either external
or crystal). Calibration is enabled by setting the value
of the Calibration register at address 08H. Calibration
is achieved by adding or subtracting a number of input
clock cycles per minute in order to achieve ppm level
adjustments in the internal timing function of the
MCP7941X.
The MSB of the Calibration register is the sign bit, with
a ‘1’ indicating subtraction and a ‘0’ indicating addition.
The remaining seven bits in the register indicate the
number of input clock cycles (multiplied by two) that
are subtracted or added per minute to the internal
timing function.
The internal timing function can be monitored using
the MFP open-drain output pin by setting bit [6]
(SQWE) and bits [2:0] (RS2, RS1, RS0) of the control
register at address 07H. Note that the MFP output
waveform is disabled when the MCP7941X is running
in VBAT mode. With the SQWE bit set to ‘1’, there are
two methods that can be used to observe the internal
timing function of the MCP7941X:
With bits RS1 and RS0 set to ‘00’, the calibration
function can be expressed as:
Since the calibration is done once per minute (i.e.,
when the internal minute counter is incremented), only
one cycle in sixty of the MFP output waveform is
affected by the calibration setting. Also note that the
duty cycle of the MFP output waveform will not
necessarily be at 50% when the calibration setting is
applied.
With bits RS1 and RS0 set to ‘01’ or ‘10’, the
calibration function can not be expressed in terms of
the input clock period. In the case where the MSB of
the Calibration register is set to ‘0’, the waveform
appearing at the MFP output pin will be “delayed”,
once per minute, by twice the number of input clock
cycles defined in the Calibration register.
B.RS2 BIT SET TO ‘1’
With the RS2 bit set to ‘1’, the following internal timing
signal is output on the MFP pin:
The frequency listed in the table presumes an input
clock source of exactly 32.768 kHz. In terms of the
equivalent number of input clock cycles, the table
becomes:
Unlike the method previously described, the
calibration setting is continuously applied and affects
every cycle of the output waveform. This results in the
modulation of the frequency of the output waveform
based upon the setting of the Calibration register.
Using this setting, the calibration function can be
Toutput = (2 * (256 +/- (2 * CALREG))) Tinput
where:
Toutput = clock period of MFP output signal
Tinput = clock period of input signal
CALREG = decimal value of the Calibration
register setting, and the sign is
determined by the MSB of the
Calibration register.

The MSB of the Calibration register is the sign bit, with
a ‘1’ indicating subtraction and a ‘0’ indicating addition.
The remaining seven bits in the register indicate the
number of input clock cycles (multiplied by two) that
are subtracted or added per minute to the internal
timing function.

I think you’ll find that this is the critical bit of info you need to understand in order to set the calibration value correctly.
The Arduino uses twos complement notation to represent integers. But the RTC uses what is called signed magnitude. In the Arduino the value -1 in a 16-bit integer is represented by the value 0xFFFF in which every bit is set to one. If you try to set the adjustment in the RTC to -1, your routine will set every bit in the adjustment to 1. But this will set the sign bit to a 1 and all the magnitude bits to 1. Since the sign bit is a one, the RTC subtracts the magnitude which, being all ones, is 127 which means it actually interprets it as -127.
What you have to do inside your adjustment routine is set the sign and magnitude bits correctly. You need to change the code to something like this:

void MCP::calibrate(int calibration) {
  unsigned char sign_mag = 0;
  int cal = calibration;

  // If the adjustment is negative, set the sign bit and make cal positive
  if(cal < 0) {
    sign_mag |= 0x80;
    cal = -cal;
  }
  // Now set the magnitude
  sign_mag |= (cal & 0x7F);
  MCPwrite(0x08, sign_mag);

thank you! that makes complete sense, i forgot about the twos complement math, it was driving me crazy for a few days

its for a mobile project so the ethernet is not a possibility

You can try GPS then.

Is there any gps module you recommend? The best would be one in the <25$ range
and I just fixed that code, hopefully when I check it later it’ll be more accurate

It is hard (impossible?) to find GPS modules for less than $25. I myself used one from seeedstudio ($45), but others sell similar modules too (e.g. https://www.adafruit.com/products/272, for $40). Here is a post I wrote on using it: http://timewitharduino.blogspot.com/2012/01/wise-clock-4-time-synchronization-with.html

Yeah unfortunetly that's why I've not bought one randomly off ebay yet : / Are gps modules 3v3 devices or 5v? It'd be alot more convienient if atleast the inputs were 5v tolerant

What do you think the feasibility of an automatic calibration program? I don't have the ability to monitor the output to make sure its exact, so im trying to make a program on processing where basically it will monitor the drift and every hour/day(not sure which is best) make a correction im about halfway done and can monitor the difference in milliseconds( which I find can vary as much as 30 each reading due to transmission I guess) my plan is that the first minute it averages the difference in seconds as a starting point, then during the course of the hour it will average the difference every second( so 60*60 reading to get a steady difference) with that average it will compare to the last hour and see if its higher/lower and raise/lower the calibration register im hoping that during the course of a day or two the difference will be the same and the program would finish, having done its job successfully

Am I overlooking something as to where this wont work? Or will this take days? Or does it sound legit?

Am I overlooking something as to where this wont work

One important factor that needs to be considered is temperature. Take a look at DS3231: "extremely accurate, temperature compensated"

So if I calibrate it a certain temperature, it may not be calibrated for other temperatures? That kinda stinks

So if I calibrate it a certain temperature, it may not be calibrated for other temperatures?

The weak link in your case is the crystal, whose frequency really varies with temperature. Is it worth implementing logic (in software) for temperature compensation, when other chips already have it in hardware?

Yeah I guess it may be best to get the better hardware, but it'd be nice to make what I have work, atleast to justify the time already given lol

As long as you aren't going to subject the RTC and crystal to wide temperature swings you don't really need to worry about its variation with temperature. What you have to decide is how accurate you think you need this clock to be. If your RTC is currently about 4 seconds slow per day, you can correct this to within about .086 seconds per day which amounts to the clock being out by no more than about 2.6 seconds per month or about 32 seconds per year. Once you've determined the adjustment value for the clock, after that you only need a program which sets the clock to the current time (right down to the second) and run it once a month or so.

Pete