Arduino Nixie Clock > Pics & Source Code

Hey Guys,

I’ve been working on a Nixie Clock for the last couple of months after snapping up a couple of Nixie Tubes on Ebay Russia for cheap. I have now got it to the stage where is is up and running. I haven’t settled on a final housing yet so just knocked up a quick and dirty housing to keep the high voltage circuitry away from being touched while I burn it in. I have written the sketch so that between Minutes it will change numbers randomly, a random number of times and display for a random amount of time. This looks quite speccy and helps the tubes from getting Cathode Poising. I’m seeing if i’ll get sick of it happening every minute and might just re-code it so it happen at random intervals throughout the day.

Components ==>

1 x Arduino Nano Microcontroller

2 x INS-1 Nixie Lamp for Colon

4 x IN-12 Russian Nixie Tubes

4 x 74141 BCD to decimal decoder and Nixie driver IC

2 x 74HC595N 8 Bit Shift Registers IC

1 x DS1307 Real Time Clock

Lots and lots of wires and heatshrink.

Source Code ==>

// ROB NIXIE CLOCK
// 5/10/2012 v0.1
// Compiled on Arduino 1.0.1 using adafruitRTClib & ogi lumen Nixie Driver Libraries

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
// On most Arduino boards, SDA (data line) is on analog input pin 4, and SCL (clock line) is on analog input pin 5.

#include <NixieBeta4.h>
#include <Wire.h>
#include “RTClib.h”

// note the digital pins of the arduino that are connected to the nixie driver
#define dataPin 2 // data line or SER
#define clockPin 3 // clock pin or SCK
#define latchPin 4 // latch pin or RCK

// note the number of digits (nixie tubes) you have (buy more, you need more)
#define numDigits 4

// Create the Nixie object
// pass in the pin numbers in the correct order
Nixie nixie(dataPin, clockPin, latchPin);

RTC_DS1307 RTC;

int previoushour;
int previousminute;
int currenthour;
int currentminute;
int nixiedisplay;

int randNumber;
int randTime;
int randTimeCount = 0;

void setup () {
Serial.begin(57600);
Wire.begin();
RTC.begin();

// Clear the display if you wish
nixie.clear(numDigits);

// following line sets the RTC to the date & time this sketch was compiled
// RTC.adjust(DateTime(DATE, TIME));
}

void clock()
{
if (currenthour > 12) //Added for 12 Hour time instead of 24 hour
{
currenthour = currenthour - 12;
}

nixiedisplay = ((currenthour*100)+currentminute);

Serial.print(nixiedisplay);
Serial.println();

nixie.writeNumZero(nixiedisplay, numDigits);
}

void loop ()
{ //Display Initial Time once and then go into loop.
DateTime now = RTC.now();
previoushour = now.hour();
previousminute = now.minute();
currenthour = now.hour();
currentminute = now.minute();

clock();

while (1) //infinite loop
{
now = RTC.now();
currenthour = now.hour();
currentminute = now.minute();

if ((currenthour!=previoushour) | (currentminute!=previousminute)) // if either doesnt equal previous value display new values
{
// gemerate random numbers for a random period of time
randTime = random(15,30); // Change Values between 15 and 30 times before displaying Actual Time
while (randTimeCount != randTime)
{
randNumber = random(0,9999); //Display Random Number between 0 and 9999
Serial.println(randNumber);
nixie.writeNumZero(randNumber, numDigits);
delay(random(50,250)); //Delay for a random period of time between 50ms and 250ms
randTimeCount++;
}
randTimeCount = 0;
//
previoushour = now.hour();
previousminute = now.minute();

clock();

}
else //Do Nothing
{
// Serial.print(“Doing nothing”);
// Serial.println();
// delay(3000);
}
}
}

Nice work - lots of wires!

Good job. Got a schematic as well?

What are you using as the Nixie power source? I just built something similar, spending more on parts but saving on headaches and wires using this guys parts:

http://www.tayloredge.com

He has an especially slick high voltage DC-DC converter:

http://www.tayloredge.com/storefront/SmartNixie/PSU/index.html

Hey JoeN,

Awesome, I'd love to see some pics of your progress/work.

I saw those taylor edge ones and you can't complain about the price!
but what really sold me was the Kosbo.com ones also had a 5v power out so you can power the Arduino and Nixie tubes of one wall plug.

Mine is still going strong and I have added a Dallas D18B20 Temperature Sensor so it's displaying the temperature as well which is pretty cool.
One little glitch i've seen while bedding mine in is every now and then it doesn't fire a number and is just blank not to sure why.

Rob.

Hey florinc,

Sorry I missed this before, I don't have a proper schematic yet. I'm still working on the PCB's to get fabbed but
I have knocked up a quick wiring pic that I used here ==>

Cheers Rob.

Just shot a quick video of it.

randyrob:
Awesome, I'd love to see some pics of your progress/work.

This is it the night before on the exhibition page:

Right now it has the buttons implemented, another LED, and a peizo. You can set the date, time, alarm time, and it works as an alarm clock and stores alarm settings in EPROM. I will update the pic this weekend on the exhibition page.

Hi randyrob,

Can you explain how cathode poisoning prevention works?
Thanks.

Daniel

Hello Daniel,

It just cycles thru each number, I do it between each minute for effect but you could do it less without an issue.

I've added a temperature sensor (DS18B20) that displays for 2 seconds after random cycle the and the Colon's now flash every second.

Very happy with how stable it is and how it is performing, still have to get a PCB fabbed and final housing.

Circuitry for Colons ==>

Current Source Code ==>

// ROB NIXIE CLOCK
// 27/10/2012 v0.4
// Compiled on Arduino 1.0.1 using adafruitRTClib, OneWire v2.1 & ogi lumen Nixie Driver Libraries

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
// On most Arduino boards, SDA (data line) is on analog input pin 4, and SCL (clock line) is on analog input pin 5. 

#include <OneWire.h>
#include <NixieBeta4.h>
#include <Wire.h>
#include "RTClib.h"

// note the digital pins of the arduino that are connected to the nixie driver
#define dataPin 2  // data line or SER
#define clockPin 3 // clock pin or SCK
#define latchPin 4 // latch pin or RCK

// note the number of digits (nixie tubes) you have (buy more, you need more)
#define numDigits 4

// Create the Nixie object
// pass in the pin numbers in the correct order
Nixie nixie(dataPin, clockPin, latchPin);


//Temperature Read Stuff
const byte PinTemp = 5;               // Dallas Ds1820 Temperature Sensors 
byte sensor1[8] = {0x28, 0x67, 0xFF, 0xC4, 0x03, 0x00, 0x00, 0x42};   // User Defined Temperature Sensor Address 1
//28 67 FF C4 3 0 0 42
int currenttemp1 = 0;     // curent temperature (1/16th degrees) sensor1
int SignBit, Whole, Fract, Tc_100; 
OneWire ds(PinTemp); 

//Colon Stuff
int colon = 6; //Nixie colons on digital pin 6
int colonState = LOW;             // ledState used to set the LED

RTC_DS1307 RTC;

int previoushour;
int previousminute;
int previoussecond; //TODO
int currenthour;
int currentminute;
int currentsecond; //TODO
int nixiedisplay;

int randNumber;
int randTime;
int randTimeCount = 0;

void setup () {
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();
    
      // Clear the display if you wish
     nixie.clear(numDigits);
    
    pinMode(PinTemp, INPUT);          // sets the digital pin as input
    pinMode(colon, OUTPUT);           // set the nixie colons as output

 // following line sets the RTC to the date & time this sketch was compiled
//    RTC.adjust(DateTime(__DATE__, __TIME__));
}

int tempread(byte sensoraddr[])
// error codes:
// -1 no sensors found
// -2 invalid CRC
// -3 not a DS1820
{
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  //int HighByte, LowByte, TReading, SignBit, Tc_100, Tf_100, Whole, Fract;
  int Temp;

  if ( !ds.search(addr)) {
    ds.reset_search();
    return -1; 
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
    return -2;
  }

  if ( addr[0] != 0x28) {
    return -3;
  }

  for ( i = 0; i < 8; i++) {
    addr[i]=sensoraddr[i];
  }
  ds.reset(); // pulse the pins and wait for a response to reset the DS1820
  ds.select(addr); // 0x55 (MATCH_ROM) followed by the address of the 1820 to talk to.
//  ds.write(0x44,1);	   // start conversion, with parasite power on at the end

  ds.write(0x44,0);  //PARASITE POWER OFF
  //delay(800);     

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);	   // Read Scratchpad

  for ( i = 0; i < 9; i++) {	     // we need 9 bytes
    data[i] = ds.read();
    
  }
  Temp=(data[1]<<8)+data[0]; //take the two bytes from the response relating to temperature
  
  SignBit = Temp & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    Temp = (Temp ^ 0xffff) + 1; // 2's comp
  }
  
  return Temp;
}

void clock()
{
      if (currenthour > 12) //Added for 12 Hour time instead of 24 hour
      {
      currenthour = currenthour - 12;
      }

      nixiedisplay = ((currenthour*100)+currentminute);

      Serial.print(nixiedisplay);
      Serial.println();
      
     nixie.writeNumZero(nixiedisplay, numDigits); 
}

void temperatureread()
{
 currenttemp1 = tempread(sensor1);
 if (currenttemp1>0)
    {
      Tc_100 = (6 * currenttemp1) + currenttemp1 / 4;    // multiply by (100 * 0.0625) or 6.25
      Whole = Tc_100 / 100;  // separate off the whole and fractional portions
      Fract = Tc_100 % 100;

      nixiedisplay = ((Whole*100)+Fract);

//      Serial.print(nixiedisplay);
//      Serial.println();
      
//     nixie.writeNumZero(nixiedisplay, numDigits); 
  }
}

void loop () 
{  //Display Initial Time once and then  go into loop.
    DateTime now = RTC.now();
    previoushour = now.hour();
    previousminute = now.minute();
    previoussecond = now.second();
    currenthour = now.hour();
    currentminute = now.minute();  
    currentsecond = now.second();
        
    clock();      
    
  while (1) //infinite loop
  {
  now = RTC.now();
  currenthour = now.hour();
  currentminute = now.minute();  
  currentsecond = now.second();
  
 if ((currenthour!=previoushour) | (currentminute!=previousminute))    // if either doesnt equal previous value display new values 
  {   
    // gemerate random numbers for a random period of time 
    randTime = random(15,30); // Change Values between 15 and 30 times before displaying Actual Time
    while (randTimeCount != randTime)
    {
     nixie.clear(numDigits); //TODO
  //   delay(50);  //TODO
     randNumber = random(0,9999); //Display Random Number between 0 and 9999
     Serial.println(randNumber); 
     nixie.writeNumZero(randNumber, numDigits); 
     delay(random(50,250));  //Delay for a random period of time between 50ms and 250ms
     //COLON STUFF TODO
     if (colonState == LOW)
    {
      colonState = HIGH;
    }
    else
    {
      colonState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(colon, colonState);
    randTimeCount++;
    }
    randTimeCount = 0;
    //
      previoushour = now.hour();
      previousminute = now.minute();
      previoussecond = now.second();
     
     nixie.clear(numDigits); 
     delay(50); 
     
     nixie.writeNumZero(nixiedisplay, numDigits);  //write temperature
     //temperatureread();
     delay(2000); //delay for 2 seconds 
     
     nixie.clear(numDigits); 
     delay(50); 
     
     clock(); //display clock
      
  }
  else //Do Nothing
  {
   //clock(); //added to fix bug where a blank number is sometimes shown 
   temperatureread(); //added to fix bug where when temperatre wasn't read    
   
   //COLON FLASHING STUFF 
    if (currentsecond!=previoussecond)    // if either doesnt equal previous value display new values 
  {  
       // if the COLON is off turn it on and vice-versa:
    if (colonState == LOW)
    {
      colonState = HIGH;
   }
   else
   {
      colonState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(colon, colonState); 
    previoussecond = now.second();    
  } 
}
}
}

Cheers Rob.

Thanks Rob.

I've seen this behaviour on some of the clocks but didn't know why it was done.
Until I found good article explaining cathode poisoning.

Cheers,
Daniel

How easy would it be to expand this to 6 digits, 2 more for the seconds? If I added another 595 and tied it to D3 and D4 of the Arduino, how would that 3rd 595 connect to the other shifts?

ryemac3:
How easy would it be to expand this to 6 digits, 2 more for the seconds? If I added another 595 and tied it to D3 and D4 of the Arduino, how would that 3rd 595 connect to the other shifts?

One 595 or 10 595s, the chain of 595s should always use exactly three or four arduino digital lines - clock, register clock, data, and optionally clear. The chips are daisy-chained, they are not wired individually. So adding extra 595s costs nothing in terms of pins. And they're cheap too - go nuts! Check this tutorial for a better explanation:

http://bildr.org/2011/02/74hc595/

When the last bit is being "lost" from the first chip, it gets transferred onto the second chip. Only the last bit on the last chip ever meets its fate and gets derezzed (poor bit!).

I suggest you buy a bunch XD:

Not to bring this back up but most of the nixie tubes I have seen require 200v...or atleast say they require 200v, but the kosbo one only ouputs 180v...will it still work at 180v or it just wont be as bright?

Rob, Willing to help me out regarding your coding for this clock. Trying to get the same setup working with no luck!

Thanks

Hello,

If you are having a problem getting this working it may because there is a error in the schematic provided. Pin 7 of the far right 595 should go to pin 4 of the far right 74141 and pin 6 of the far right 595 should go to pin 7 of the far right 74141. Hope that helps you.

I have developed a fully featured Arduino based Nixie Clock code, and have posted it up on GitHub:

I gathered a load of experience with this project so if anyone needs any help with Nixie topics, don't hesitate to get in contact with me.

Look at my version of Nixie Clock DIY Step By Step Nixie Clock Tube IN-18 Arduino Divergence Meter, GRA & AFCH, ATmega328 - YouTube