Pages: [1]
Author Topic: Why is my clock fast despite RTC?  (Read 4573 times)
Serow
Newbie
*
Posts: 6


View Profile Email
« on: September 13, 2013, 11:56:01 PM »

I started with the 4 nixie plus colon code on the downloads page. I altered the code to read an RTC to get the time. When I run the code it gets the time and displays it correctly on the Nixie tubes. Unfortunately it immediately starts running almost 2x too fast. The way I understand the code it should be continuously reading the RTC and shouldn't get off. Could someone tell me what is wrong with my code. Thanks in advance!

Code:
// SN74141 : True Table
//D C B A #
//L,L,L,L 0
//L,L,L,H 1
//L,L,H,L 2
//L,L,H,H 3
//L,H,L,L 4
//L,H,L,H 5
//L,H,H,L 6
//L,H,H,H 7
//H,L,L,L 8
//H,L,L,H 9

#include <Wire.h>
#include "RTClib.h" // a basic DS1307 library that returns time as a time_t
RTC_DS1307 RTC;

// SN74141 (1)
int ledPin_0_a = 2;                
int ledPin_0_b = 3;
int ledPin_0_c = 4;
int ledPin_0_d = 5;
// SN74141 (2)
int ledPin_1_a = 6;                
int ledPin_1_b = 7;
int ledPin_1_c = 8;
int ledPin_1_d = 9;

// anod pins
int ledPin_a_1 = 10;
int ledPin_a_2 = 11;
int ledPin_a_3 = 12;

void setup()
{
  
    //Start I2C and RTC
  Wire.begin();
  RTC.begin();
  
  pinMode(ledPin_0_a, OUTPUT);      
  pinMode(ledPin_0_b, OUTPUT);      
  pinMode(ledPin_0_c, OUTPUT);      
  pinMode(ledPin_0_d, OUTPUT);    
  
  pinMode(ledPin_1_a, OUTPUT);      
  pinMode(ledPin_1_b, OUTPUT);      
  pinMode(ledPin_1_c, OUTPUT);      
  pinMode(ledPin_1_d, OUTPUT);      
  
  pinMode(ledPin_a_1, OUTPUT);      
  pinMode(ledPin_a_2, OUTPUT);      
  pinMode(ledPin_a_3, OUTPUT);      
  
  // NOTE:
  // You can add a input here to for setting the time
}

////////////////////////////////////////////////////////////////////////
//
// DisplayNumberSet
// Use: Passing anod number, and number for bulb 1 and bulb 2, this function
//      looks up the truth table and opens the correct outs from the arduino
//      to light the numbers given to this funciton (num1,num2).
//      On a 6 nixie bulb setup.
//
////////////////////////////////////////////////////////////////////////
void DisplayNumberSet( int anod, int num1, int num2 )
{
  int anodPin;
  int a,b,c,d;
  
  // set defaults.
  a=0;b=0;c=0;d=0; // will display a zero.
  anodPin =  ledPin_a_1;     // default on first anod.
  
  // Select what anod to fire.
  switch( anod )
  {
    case 0:    anodPin =  ledPin_a_1;    break;
    case 1:    anodPin =  ledPin_a_2;    break;
    case 2:    anodPin =  ledPin_a_3;    break;
  }  
  
  // Load the a,b,c,d.. to send to the SN74141 IC (1)
  // 1=H, 0=L.  Truth Table
  switch( num1 )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=1;b=0;c=0;d=0;break;
    case 2: a=0;b=1;c=0;d=0;break;
    case 3: a=1;b=1;c=0;d=0;break;
    case 4: a=0;b=0;c=1;d=0;break;
    case 5: a=1;b=0;c=1;d=0;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=1;b=1;c=1;d=0;break;
    case 8: a=0;b=0;c=0;d=1;break;
    case 9: a=1;b=0;c=0;d=1;break;
  }  
  
  // Write to output pins.
  digitalWrite(ledPin_0_d, d);
  digitalWrite(ledPin_0_c, c);
  digitalWrite(ledPin_0_b, b);
  digitalWrite(ledPin_0_a, a);

  // Load the a,b,c,d.. to send to the SN74141 IC (2)
  switch( num2 )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=1;b=0;c=0;d=0;break;
    case 2: a=0;b=1;c=0;d=0;break;
    case 3: a=1;b=1;c=0;d=0;break;
    case 4: a=0;b=0;c=1;d=0;break;
    case 5: a=1;b=0;c=1;d=0;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=1;b=1;c=1;d=0;break;
    case 8: a=0;b=0;c=0;d=1;break;
    case 9: a=1;b=0;c=0;d=1;break;
  }
  
  // Write to output pins
  digitalWrite(ledPin_1_d, d);
  digitalWrite(ledPin_1_c, c);
  digitalWrite(ledPin_1_b, b);
  digitalWrite(ledPin_1_a, a);

  // Turn on this anod.
  digitalWrite(anodPin, HIGH);  

  // Delay
  // NOTE: With the differnce in Nixie bulbs you may have to change
  //       this delay to set the update speed of the bulbs. If you
  //       dont wait long enough the bulb will be dim or not light at all
  //       you want to set this delay just right so that you have
  //       nice bright output yet quick enough so that you can multiplex with
  //       more bulbs.
  delay(3);
  
  // Shut off this anod.
  digitalWrite(anodPin, LOW);
}

////////////////////////////////////////////////////////////////////////
//
// DisplayNumberString
// Use: passing an array that is 8 elements long will display numbers
//      on a 6 nixie bulb setup.
//
////////////////////////////////////////////////////////////////////////
void DisplayNumberString( int* array )
{
  // bank 1 (bulb 0,3)
  DisplayNumberSet(0,array[0],array[3]);  
  // bank 2 (bulb 1,4)
  DisplayNumberSet(1,array[1],array[4]);  
  // bank 3 (bulb 2,5)
  DisplayNumberSet(2,array[2],array[5]);  
}

// Defines
long MINS = 60;         // 60 Seconds in a Min.
long HOURS = 60 * MINS; // 60 Mins in an hour.
long DAYS = 24 * HOURS; // 24 Hours in a day. > Note: change the 24 to a 12 for non millitary time.
long runTime = 0;   // Time from when we started.

//************************************
long previous = 0;
long interval = 1000;
int colon = 1;

//************************************


// default time sets. clock will start at 12:59:00
// NOTE: We start seconds at 0 so we dont need a clock set
//       The values you see here would be what you change
//       if you added a set clock inputs to the board.
long clockHourSet;
long clockMinSet;

////////////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////
void loop()    
{
  Serial.begin(9600);
      //pull the time from the RTC
  DateTime now = RTC.now();
    //pull out the hours, mins from now
  long clockHourSet = now.hour();
  long clockMinSet = now.minute();

  
  // Get milliseconds.
  runTime = millis();
  
  Serial.println (runTime);

  // Get time in seconds.
  long time = (runTime) / 1000;
  
  // Set time based on offset..
  long hbump = 60*60*clockHourSet;
  long mbump = 60*clockMinSet;
  time += mbump + hbump;

  // Convert time to days,hours,mins,seconds
  long days  = time / DAYS;    time -= days  * DAYS;
  long hours = time / HOURS;   time -= hours * HOURS;
  long minutes  = time / MINS;    time -= minutes  * MINS;
  long seconds  = time;
  
  //*****************************
  unsigned long current = millis();
  if( (current - previous) > interval)
  {
    previous = current;
    if (colon == 0)
      {
        colon = 1;
      }
      
    else
      {
        colon = 0;
      }
  }
  //*****************************
    
  
  // Get the high and low order values for hours,min,seconds.
  int lowerHours = hours % 10;
  int upperHours = hours - lowerHours;
  int lowerMins = minutes % 10;
  int upperMins = minutes - lowerMins;
  int lowerSeconds = seconds % 10;
  int upperSeconds = seconds - lowerSeconds;
  if( upperSeconds >= 10 )   upperSeconds = upperSeconds / 10;
  if( upperMins >= 10 )      upperMins = upperMins / 10;
  if( upperHours >= 10 )     upperHours = upperHours / 10;
  
  // Fill in the Number array used to display on the tubes.
  int NumberArray[6]={0,0,0,0,0,0};
  NumberArray[0] = upperHours;     //
  NumberArray[4] = lowerHours;     //
  NumberArray[2] = upperMins;      //
  NumberArray[3] = lowerMins;      //
  NumberArray[1] = colon;          //Digit 4, wire 0
    

  // Display.
  DisplayNumberString( NumberArray );
}

Edit: After looking at the behavior more closely, it appears that it stays accurate for the first few minutes and then starts behaving more erratically but always too fast. Could this be a hardware problem?

edit 2: I just let it run for 5 hours. It appears to be running 2x too fast.

edit 3: I watched the values through the serial monitor. It correctly advances the minutes when the seconds turn over from 60 to 0. For some reason it also advances the minute somewhere between 16 and 17 seconds. I still have no idea why.

edit 4: Okay now it's advancing about at 60 to 0 and about again about 8 seconds later. My head is going to explode.
« Last Edit: September 14, 2013, 04:28:18 PM by Serow » Logged

Serow
Newbie
*
Posts: 6


View Profile Email
« Reply #1 on: September 17, 2013, 04:14:27 PM »

Okay, I realized what was wrong. I put the starting time in the loop function so it constantly updates along with the offset. When I try to move it out of the loop function, only zeroes are displayed on the Nixie tubes. What would be the easiest way to do this?
Logged

Risen
Newbie
*
Posts: 18


View Profile Email
« Reply #2 on: October 09, 2013, 09:08:07 AM »

I think your problem lies here:

Code:
  // Get milliseconds.
  runTime = millis();
 
  Serial.println (runTime);

  // Get time in seconds.
  long time = (runTime) / 1000;
 
  // Set time based on offset..
  long hbump = 60*60*clockHourSet;
  long mbump = 60*clockMinSet;
  time += mbump + hbump;
 
 
You are keeping track of time twice, once with the RTC and once with the Arduino.

 
At startup, all seems fine:

RTC time = now
runTime = millis --> 0
time +=  mbump + hbump --> 0 + (now)
Result: time = now


But here's what the code is doing 10m in:

RTC time = now
runTime = millis --> 10m
time +=  mbump + hbump --> 10m + (now) ... see how it's adding the time twice?
Result: time = now + 10m

Get the time from the RTC, then try something like this instead, deleting the other lines noted above.

  // Set time based on RTC
  long hbump = 60*60*clockHourSet;
  long mbump = 60*clockMinSet;
  long time += mbump + hbump;
Logged

Pages: [1]
Print
Jump to: