RTC to BCD to Multiplexing for Nixie Clock

Hello,

I'm new to the adruino programming and the whole programming thing in general. I do have experience with solidering/building electronic circuits. Anyways, i've built several clocks using nixie tubes. Here's a wikipedia link in case you haven't heard of nixie tubes Nixie tube - Wikipedia . I've built 3 clocks using only 4017 ic counters and the 60hz from the ac line to time the clock. Everything works well but now i'd like to digitize everything. This would allow me to add certain features to the clock ex: real time clock, date, temp, alarm, etc... and reduce the part # count. I have a RTC ds1307 but is being used in another clock for the 1hz pulse only. I recently discovered how to use it and i'd like to incorporate one in my nixie clock (using a ds1337). My clock that I'm building will use a atmega168 (also have a adruino diecimila). The clock will be multiplexed, only 2 tubes lit at once, using only 2 bcd to dec converter chips. These are special ic's since they work with high voltage. I quickly wrote up a schematic to illustrate how the circuit works. I have a general idea on how the clock is going to run (software wise) but I need help with the code. The code I attached has the code from running the rtc Hobby Robotics » An I2C Bus Example Using the DS1307 Real-Time Clock . So, basically the clock is going to work like this: read time from rtc (outputs in bcd), read correct time depending on which tubes are being displayed (multiplexed; but will look always on to the eye), send bcd code to bcd to dec converter chips, chips will connect the correct cathode to ground to light up the number in the nixie tube. I do want to end up adding a way to display the date and temp and be able to change the rtc time without using a comp but for now I just want the clock to display the time from the rtc. This clock isn't built yet (waiting on bcd chips) but I want to start on the code early. Some of the code I added is pseudo code because I want to get the basic point across and I don't know the actual real functions. Please refer to the comments in the code to see what I want to do. Oh yeah, this will be a 12 hr clock. Feel free to add/edit my code. Any suggestions or pointers will be greatly appreciated and I'll include updates on the progress. Thanks.

If you'd like to see my other nixie clocks i've built (except the tiny clock) visit my photobucket album: Photobucket | Make your memories fun!

The code:

//
// Nixie clock code including RTC by Tai Oliphant (code for rtc is by Maurice Ribble)

// Maurice Ribble
// 4-17-2008
// http://www.glacialwanderer.com/hobbyrobotics
 
// This code tests the DS1307 Real Time clock on the Arduino board.
// The ds1307 works in binary coded decimal or BCD.  You can look up
// bcd in google if you aren't familior with it.  There can output
// a square wave, but I don't expose that in this code.  See the
// ds1307 for it's full capabilities.
 
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
 
int anode1 = 2;                      // this pin controls the tens hr and min tubes
int anode2 = 3;                      // this pin controls the hrs and tens sec tubes
int anode3 = 4;                      // this pin controls the tens min and sec tubes

int bcd1a = 9;                        // this chip connects to the tens hrs, hrs, and tens min tubes
int bcd1b = 10;
int bcd1c = 11;
int bcd1d = 12;

int bcd2a = 5;                       // this chip connects to the mins, tens sec, and sec tubes
int bcd2b = 6;
int bcd2c = 7;
int bcd2d = 8;

int val;
 
// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(0x80);
  Wire.endTransmission();
}*/
 
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(second);    // 0 to bit 7 starts the clock
   Wire.send(minute);
   Wire.send(hour);      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(dayOfWeek);
   Wire.send(dayOfMonth);
   Wire.send(month);
   Wire.send(year);
   Wire.endTransmission();
}
 
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 
  // A few of these need masks because certain bits are control bits
  *second     = Wire.receive() & 0x7f;
  *minute     = Wire.receive();
  *hour       = Wire.receive() & 0x6f;  // Need to change this if 12 hour am/pm
  *dayOfWeek  = Wire.receive();
  *dayOfMonth = Wire.receive();
  *month      = Wire.receive();
  *year       = Wire.receive();
}
 
void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
 
 
  // Change these values to what you want to set your clock to.
  // You probably only want to set your clock once and then remove
  // the setDateDs1307 call.
  second = 45;
  minute = 3;
  hour = 7;
  dayOfWeek = 5;
  dayOfMonth = 17;
  month = 4;
  year = 8;
  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  
   pinMode(anode1, OUTPUT);    //sets anode pins as output
   pinMode(anode2, OUTPUT);
   pinMode(anode3, OUTPUT);
  
  pinMode(bcd1a, OUTPUT);     //sets bcd pins as output
  pinMode(bcd1b, OUTPUT);
  pinMode(bcd1c, OUTPUT);
  pinMode(bcd1d, OUTPUT);
  
  pinMode(bcd2a, OUTPUT);
  pinMode(bcd2b, OUTPUT);
  pinMode(bcd2c, OUTPUT);
  pinMode(bcd2d, OUTPUT);
}
 
void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.print(second);
  Serial.print("  ");
  Serial.print(month);
  Serial.print("/");
  Serial.print(dayOfMonth);
  Serial.print("/");
  Serial.print(year);
  Serial.print("  Day_of_week:");
  Serial.println(dayOfWeek);
 
  delay(1000);

The rest of it:

              //This is where I started to add my own code.
  
  
  
  digitalWrite(anode1, HIGH);               // this will display (turn on) the tens hours tube and minutes tube
  digitalWrite(anode2, LOW);                // all other tubes have to have the anodes grounded to prevent ghosting
  digitalWrite(anode3, LOW);
  

  
     tens hrs == val;     //read tens hrs code from rtc
                                 // send the correct matching code to bcd chip #1
  
  if(val == 0000){                   //#0
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, LOW);
  }
  
   if(val == 0001){                  //#1
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, HIGH);
  }
  
   if(val == 0010){                  //#2
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, HIGH);
    digitalWrite(bcd1d, LOW);
  }
  
   if(val == 0011){                  //#3
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, HIGH);
    digitalWrite(bcd1d, HIGH);
  }
  
  if(val == 0100){                   //#4
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, HIGH);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, LOW);
  }
  
  if(val == 0101){                   //#5
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, HIGH);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, HIGH);
  }
  
  if(val == 0110){                   //#6
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, HIGH);
    digitalWrite(bcd1c, HIGH);
    digitalWrite(bcd1d, LOW);
  }
  
  if(val == 0111){                   //#7
    digitalWrite(bcd1a, LOW);
    digitalWrite(bcd1b, HIGH);
    digitalWrite(bcd1c, HIGH);
    digitalWrite(bcd1d, HIGH);
  }
  
  if(val == 1000){                   //#8
    digitalWrite(bcd1a, HIGH);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, LOW);
  }
  
  if(val == 1001){                   //#9
    digitalWrite(bcd1a, HIGH);
    digitalWrite(bcd1b, LOW);
    digitalWrite(bcd1c, LOW);
    digitalWrite(bcd1d, HIGH);
  }
  
  mins == val;                     //read min code from rtc
  // send the correct matching code to bcd chip #2
  
  if(val == 0000){                   //#0
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, LOW);
  }
  
   if(val == 0001){                  //#1
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, HIGH);
  }
  
   if(val == 0010){                  //#2
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, HIGH);
    digitalWrite(bcd2d, LOW);
  }
  
   if(val == 0011){                  //#3
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, HIGH);
    digitalWrite(bcd2d, HIGH);
  }
  
  if(val == 0100){                   //#4
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, HIGH);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, LOW);
  }
  
  if(val == 0101){                   //#5
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, HIGH);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, HIGH);
  }
  
  if(val == 0110){                   //#6
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, HIGH);
    digitalWrite(bcd2c, HIGH);
    digitalWrite(bcd2d, LOW);
  }
  
  if(val == 0111){                   //#7
    digitalWrite(bcd2a, LOW);
    digitalWrite(bcd2b, HIGH);
    digitalWrite(bcd2c, HIGH);
    digitalWrite(bcd2d, HIGH);
  }
  
  if(val == 1000){                   //#8
    digitalWrite(bcd2a, HIGH);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, LOW);
  }
  
  if(val == 1001){                   //#9
    digitalWrite(bcd2a, HIGH);
    digitalWrite(bcd2b, LOW);
    digitalWrite(bcd2c, LOW);
    digitalWrite(bcd2d, HIGH);
  }
                                        //Then repeated for the 4 other tubes
                                         
                                         
                                         
   digitalWrite(anode1, LOW);               
  digitalWrite(anode2, HIGH);                        // this will display (turn on) hours tube and tens seconds tube
  digitalWrite(anode3, LOW);
  
 
                                           //read hrs code from rtc
                                           //read tens secs code from rtc
                                           //send bcd code to bcd chip #1
                                           //send bcd code to bcd chip #2
                                         
                                         
  digitalWrite(anode1, LOW);               
  digitalWrite(anode2, LOW);                       
  digitalWrite(anode3, HIGH);                            // this will display (turn on) tens mins tube and seconds tube
  

                                            //read tens mins code from rtc
                                            //read secs code from rtc
                                           //send bcd code to bcd chip #1 
                                           //send bcd code to bcd chip #2

}

I updated the code above. I just thought up more ideas for the code. When you get the seconds from the rtc, it'll spit out bcd ex. 0001 0010 . So, let's just say that the 0001 = 1 in dec and 0010 = 2. Since only 2 tubes are lit at once but in a different category(say tens min and seconds), I only need one of those bcd codes. Ex. rtc spits out 0001 0010 which equals 12 seconds but at the moment, I only need the sec, so I need only the 2nd set of bcd numbers (0010). Then the 0010 needs to be sent to the bcd converter chip. Ex. 0 (low) to pin5, 0 (low) to pin6, 1 (high) to pin 7, and 0 (low) to pin 8. If I knew this it would help out alot.

EDIT: I think I figured out how to send the code to the BCD chips (the long way). It's in the code above. I'm sure there is a shorter and easier way to do it but I don't know how to. Anyways, check it out and let me know.

For multiple nixie tube digit hardware, you can also try http://www.ogilumen.com

They've got these cool nixie tube modules that plug together. It makes the interface for Arduino coding pretty easy.

Here are some code ideas. It's a combination of pseudocode and some completely untested functions that I hope will get you going in the right direction .

Have fun

#define NBR_ANODE_PINS 3
#define NBR_DECADE_PINS 4

int anodePins[NBR_ANODE_PINS] = {2,3,4};
int bigDecadePins[NBR_DECADE_PINS] = {12,11,10,9}; //LSB first
int smallDecadePins[NBR_DECADE_PINS] = {5,6,7,8}; //LSB first

int bigTime[NBR_ANODE_PINS]; // hrs and tens of minutes from RTC
int smallTime[NBR_ANODE_PINS]; // minutes and seconds from RTC

void setup(){
    for(int i=0; i < NBR_ANODE_PINS; i++)
       pinMode( anodePins[i],OUTPUT);    
    for(int i=0; i < NBR_DECADE_PINS; i++){
       pinMode( bigDecadePins[i],OUTPUT);  
       pinMode( smallDecadePins[i],OUTPUT); 
    }
     // init RTC ....
}

void writeAnode(int tube){  
// turn the given tube on, all others off  
    for(int i=0; i < NBR_ANODE_PINS; i++)
       digitalWrite(anodePins[i],LOW); // turn off all pins
   digitalWrite(tube,HIGH);  // turn on given tube      
}

void writeDecade(boolean bigDecade, int value){  
// set pins to reflect the given decade value, write to the big Decade if first argument is true or small Decade if false

unsigned int bit;
unsigned int pos = 1;

    for(int i=0; i < 4; i++){
      bit = value & pos;
      if(bigDecade)
         digitalWrite(bigDecadePins[i],bit); 
      else   
         digitalWrite(smallDecadePins[i],bit); 
      pos = pos << 1;
    }     
}

void loop(){
    // read time into bigTime and smallTime arrays
    // loop for each of the 3 anode pins
    // - call the writeAnode function with the anode number
    // - call the writeDecade functions for the big and little decades with the values in the time arrays     
}