Mirko Pavleski
Published © GPL3+

DIY Arduino IN-1 (ИН-1) Nixie Tube Clock

This is another one of the many unusual clocks you can see in some of my previous projects. IN-1 nixie tubes are relatively cheap.

IntermediateFull instructions provided4,445
DIY Arduino IN-1 (ИН-1) Nixie Tube Clock

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
IN-1 Nixie Tube
×6
SN74141 or KD155 IC
×6
74LS595 Shift register IC
×3
DS3231M - ±5ppm, I2C Real-Time Clock
Maxim Integrated DS3231M - ±5ppm, I2C Real-Time Clock
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×2
220v/6v small Trafo
×1
DS18B20 Programmable Resolution 1-Wire Digital Thermometer
Maxim Integrated DS18B20 Programmable Resolution 1-Wire Digital Thermometer
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Circuit diagram

Code

Arduino Code

C/C++
// Nixie-Bot
// Created 2013
// Scott-Bot.com

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

const int button1Pin = 11;
const int button2Pin = 10;

int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 2
int TempReading;
int TempDigit1;
int TempDigit2;
RTC_DS1307 RTC;
DateTime now;

//Pin connected to ST_CP of 74HC595
int latchPin = 6;
//Pin connected to SH_CP of 74HC595
int clockPin = 7;
////Pin connected to DS of 74HC595
int dataPin = 5;

int testpattern = 0;

int button1State = 0;
int button2State = 0;

unsigned long SecondCount = 0; // Second counter
unsigned long MinuteCount = 0; // Second counter
int randint;

byte DataOut1 = B11111111;
byte DataOut2 = B11111111;
byte DataOut3 = B11111111;

void setup () {
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);       
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  Serial.begin(57600);
  Wire.begin();
  RTC.begin();
  
  
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
    
  //Wait for power supply to power up
  delay(1000);
  getTemp();

}

void loop () {

  // Every minute display a test pattern
  if (millis()-MinuteCount > 60000) {
    MinuteCount = millis();
    if (testpattern == 0) {
      DispTemp();
      testpattern = 1;
    } else if (testpattern == 1) {
      ScrollPattern();
      testpattern = 0;
    }
  } else if (millis()-SecondCount > 1000) {
    SecondCount = millis();
    GetTime();
    DispTime();
  }
  
  button1State = digitalRead(button1Pin);
  button2State = digitalRead(button2Pin);
  if (button1State == HIGH) {   
    // Display the temperature pattern
    DispTemp();
    MinuteCount = millis();
  } 
  if (button2State == HIGH) {   
    // Display the scrolling pattern
    ScrollPattern();
    MinuteCount = millis();
  } 
  
}

// Scroll the temperature across the display
void DispTemp() {
  
  for(int j=1; j<=3; j++) {
    TempReading = getTemp();
    TempDigit1 = TempReading/10;
    TempDigit2 = TempReading%10;
    SetDigit(1, 10);
    SetDigit(2, 10);
    SetDigit(3, 10);
    SetDigit(4, 10);
    SetDigit(5, 10);
    SetDigit(6, 10);
    for (int i = -1; i<=7; i++) {
      SetDigit(i-1, 10);
      SetDigit(i, TempDigit1);
      SetDigit(i+1, TempDigit2);
      shiftOut();
      delay(333);
    }
  }
}

// Displays the time
void DispTime() {
  int hourdigit1 =(now.hour())/10;
  int hourdigit2 =(now.hour())%10;
  int mindigit1 =(now.minute())/10;
  int mindigit2 =(now.minute())%10;
  int secdigit1 =(now.second())/10;
  int secdigit2 =(now.second())%10;
  SetDigit(1, hourdigit1);
  SetDigit(2, hourdigit2);
  SetDigit(3, mindigit1);
  SetDigit(4, mindigit2);
  SetDigit(5, secdigit1);
  SetDigit(6, secdigit2);
  shiftOut();
}

void ScrollPattern() {
  // Blank the digits
  SetDigit(1, 10);
  SetDigit(2, 10);
  SetDigit(3, 10);
  SetDigit(4, 10);
  SetDigit(5, 10);
  SetDigit(6, 10);
  delay(250);
  //Scroll Loop
  for (int i = 1; i<=6; i++) {
    SetDigit(1, i);
    SetDigit(2, i-1);
    SetDigit(3, i-2);
    SetDigit(4, i-3);
    SetDigit(5, i-4);
    SetDigit(6, i-5);
    shiftOut();
    delay(200);
  }
  for (int i = 7; i<=39; i++) {
    SetDigit(1, (i)%10);
    SetDigit(2, (i-1)%10);
    SetDigit(3, (i-2)%10);
    SetDigit(4, (i-3)%10);
    SetDigit(5, (i-4)%10);
    SetDigit(6, (i-5)%10);
    shiftOut();
    delay(200);
  }
  for (int i = 10; i<=16; i++) {
    SetDigit(1, i);
    SetDigit(2, i-1);
    SetDigit(3, i-2);
    SetDigit(4, i-3);
    SetDigit(5, i-4);
    SetDigit(6, i-5);
    shiftOut();
    delay(200);
  }
}

// Sets a digit of the display
void SetDigit(int Digit, int Number) {
  
  byte BinNum;
  
  if ( Number == 0) {	
    BinNum= B0000;
  }
  else if ( Number == 1) {	
    BinNum= B1001;
  }
  else if ( Number == 2) {	
    BinNum= B1000;
  }
  else if ( Number == 3) {	
    BinNum= B0111;
  }
  else if ( Number == 4) {	
    BinNum= B0110;
  }
  else if ( Number == 5) {	
    BinNum= B0101;
  }
  else if ( Number == 6) {	
    BinNum= B0100;
  }
  else if ( Number == 7) {	
    BinNum= B0011;
  }
  else if ( Number == 8) {	
    BinNum= B0010;
  }
  else if ( Number == 9) {	
    BinNum= B0001;
  }
  else {
    BinNum= B1010;
  }
  
  if ( Digit == 1) {	
    DataOut1 &= B00001111;
    DataOut1 |= (BinNum << 4);
  }
  else if ( Digit == 2) {	
    DataOut1 &= B11110000;
    DataOut1 |= BinNum;
  }
  else if ( Digit == 3) {	
    DataOut2 &= B00001111;
    DataOut2 |= (BinNum << 4);
  }
  else if ( Digit == 4) {	
    DataOut2 &= B11110000;
    DataOut2 |= BinNum;
  }
  else if ( Digit == 5) {	
    DataOut3 &= B00001111;
    DataOut3 |= (BinNum << 4);
  }
  else if ( Digit == 6) {	
    DataOut3 &= B11110000;
    DataOut3 |= BinNum;
  }
  
}  

// Shifts out the data to the shift registers
void shiftOut() {
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;

  //clear everything out just in case to
  //prepare shift register for bit shifting
  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, 0);
  digitalWrite(dataPin, 0);
  digitalWrite(clockPin, 0);

  //for each bit in the byte myDataOutďż˝
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=7; i>=0; i--)  {
    digitalWrite(clockPin, 0);

    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( DataOut1 & (1<<i) ) {
      pinState= 1;
    }
    else {	
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(clockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(dataPin, 0);
  }
  
  //stop shifting
  digitalWrite(clockPin, 0);
  
  // Shift the second word
  for (i=7; i>=0; i--)  {
    digitalWrite(clockPin, 0);

    if ( DataOut2 & (1<<i) ) {
      pinState= 1;
    }
    else {	
      pinState= 0;
    }
    
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
    digitalWrite(dataPin, 0);
  }

  digitalWrite(clockPin, 0);
  
  // Shift the third word
  for (i=7; i>=0; i--)  {
    digitalWrite(clockPin, 0);

    if ( DataOut3 & (1<<i) ) {
      pinState= 1;
    }
    else {	
      pinState= 0;
    }

    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
    digitalWrite(dataPin, 0);
  }

  digitalWrite(clockPin, 0);
  
  digitalWrite(latchPin, 1);
}

// Read from the real time clock
void GetTime () {
  now = RTC.now();
}

float getTemp(){
 //returns the temperature from one DS18S20 in DEG Celsius

 byte data[12];
 byte addr[8];

 if ( !ds.search(addr)) {
   //no more sensors on chain, reset search
   ds.reset_search();
   return -1000;
 }

 if ( OneWire::crc8( addr, 7) != addr[7]) {
   Serial.println("CRC is not valid!");
   return -1000;
 }

 if ( addr[0] != 0x10 && addr[0] != 0x28) {
   Serial.print("Device is not recognized");
   return -1000;
 }

 ds.reset();
 ds.select(addr);
 ds.write(0x44,1); // start conversion, with parasite power on at the end

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

 
 for (int i = 0; i < 9; i++) { // we need 9 bytes
  data[i] = ds.read();
 }
 
 ds.reset_search();
 
 byte MSB = data[1];
 byte LSB = data[0];

 float tempRead = ((MSB << 8) | LSB); //using two's compliment
 float TemperatureSum = tempRead / 16;
 TemperatureSum = (TemperatureSum * 9.0)/ 5.0 + 32.0;
 return TemperatureSum;
 
}

Credits

Mirko Pavleski

Mirko Pavleski

116 projects • 1163 followers

Comments