Tuesday, February 19, 2013

Laser cut Nixie Tube clock powered by Arduino





http://www.thingiverse.com/thing:52252



I bought all the goodies to make a nice Nixie clock from Taylor Electronics, but I didn't have a nice case for it. It took me about 6 hours to design, cut, and re-cut parts until I had something I was happy with. I disabled the I2C master on the first TES 1361 SmartNixie board and replaced it with an Arduino Nano board connected in the unused RTC connector on the bottom of the backplane board. I poll the GPS RTC board via I2C to get the time and then send command over the I2C bus to the SmartNixie boards to display the digits.





Laser cut parts from 1/8 acrylic (The stuff I bought from Home Depot ended up being 2.2mm thick and not 3.175mm(1/8") so this drawing was designed for 2.2mm, but that isn't hard to change.)


Order these parts from http://www.tayloredge.com/storefront/index.html


1 x 1392 - 6 Digit IN18 Clock Backplane

6 x 1361 - SmartNixie IN18

1 x 1375 - SmartNixie GPS RTC

1 x 1364 - SmartNixie HVPS-H

1 x Active GPS Antenna

1 x Power Plug



I ordered my IN-18 tubes from super-gene on ebay: http://myworld.ebay.com/super-gene/

6 x IN-18 tubes



12V power supply and Arduino Nano can be ordered from Amazon here:

http://www.amazon.com/Wall-Adapter-Power-Supply-12VDC/dp/B006GEPUYA
http://www.amazon.com/Arduino-ARD-NANO30-Nano-v3-0/dp/B003YVL34O



Arduino Sketch:



 // Smart Nixie  
 // by Jason Garland <http://www.jasongarland.com>  
 #include <Wire.h>  
 #include <SeeedOLED.h>  
 #include <avr/pgmspace.h>  
 #include "DHT.h"  
 #define DHTPIN 2   // what pin Temperature sensor is connected to  
 #define DHTTYPE DHT22  // DHT 22 (AM2302)  
 DHT dht(DHTPIN, DHTTYPE);  
 byte tube[6]={0x0E, 0x0C, 0x0B, 0x0A, 0x09, 0x08};  
 char tubestate[7];  
 byte gps[14];  
 int tzoffset=-8;  
 char digit[7];  
 unsigned long counter=999999;  
 #define LEDPIN 13  
 int ledstate=0;  
 unsigned long lasttick = millis();  
 unsigned long lastdht = millis();  
 void setup()  
 {  
  Serial.begin(38400);  
  Serial.println("Starting up");  
  pinMode(A4, INPUT_PULLUP);  
  pinMode(A5, INPUT_PULLUP);  
  pinMode(LEDPIN, OUTPUT);  
  dht.begin();  
  Wire.begin(); // join i2c bus (address optional for master)  
  SeeedOled.init(); //initialze SEEED OLED display  
  DDRB|=0x21;      
  PORTB |= 0x21;  
  SeeedOled.setBrightness(255);  
  SeeedOled.clearDisplay();        // clear the screen and set start position to top left corner  
  SeeedOled.setNormalDisplay();   //Set display to normal mode (i.e non-inverse mode)  
  SeeedOled.setPageMode();      //Set addressing mode to Page Mode  
  SeeedOled.setTextXY(1,0);     //Set the cursor to Xth Page, Yth Column   
  SeeedOled.putString("Humidity:"); //Print the String "Hello World!"  
  SeeedOled.setTextXY(3,0);     //Set the cursor to Xth Page, Yth Column   
  SeeedOled.putString("Temperature:"); //Print the String "Hello World!"  
  SeeedOled.setTextXY(5,0);     //Set the cursor to Xth Page, Yth Column   
  SeeedOled.putString("Time: "); //Print the String "Hello World!"  
  init_gps(); // Initialize the GPS  
  //Set brightness on all tubes to 100%  
  for (int i=5; i>=0; i-- ){ setbrightness(i, 100); }  
 }  
 void loop() {  
  // Update once per 10th second  
  if (millis() - lasttick >= 100) {  
   lasttick = millis();  
   if ( random(1000) == 42) { pinball(); }  
   read_gps_time(digit);  
   update_display(digit);  
   SeeedOled.setTextXY(6,2);  
   SeeedOled.putString(digit);  
  }  
  update_oled_dht();  
   //Serial.println(counter);  
   //delay(1000);  
   //update_display(counter--);  
 }  
 void read_gps_time(char* digit_buffer) {  
  //int bytes=128;  
  int bytes=6;  
  Wire.requestFrom(81, bytes);  // request 14 bytes from slave device #81  
  int i=0;  
  while(Wire.available())  // slave may send less than requested  
  {  
   gps[i]=Wire.read();  
   i++;  
  }  
  char buffer[((bytes * 3) + 1)];  
  for(int j=0;j<bytes;j++){  
   sprintf(buffer+(j*3), "%02X ", gps[j]);  
   }  
  //Serial.println(buffer);  
  char hourbuffer[3];  
  int hour;  
  sprintf(hourbuffer, "%02X", gps[2]);  
  hour=atoi(hourbuffer);  
  //hour+=tzoffset;  
  if(hour < 0) {  
   hour+=24;  
  }  
  sprintf(digit_buffer,"%02d%02X%02X", hour, gps[1], gps[0]);  
  //Serial.println(digit_buffer);  
 }  
 void setbrightness(int place, int brightness) {  
   Wire.beginTransmission(tube[place]); // seconds 1s  
   Wire.write(byte(0x0B));    //register address=dimmer  
   Wire.write(brightness);    //dimmer=50%  
   Wire.endTransmission(); // stop transmitting  
 }  
 void update_display(unsigned long number){  
  char digit_buffer[7];  
  sprintf(digit_buffer, "%06lu",number%1000000);  
  update_display((char *)&digit_buffer);  
  }  
 void update_display(char* digit_buffer)  
 {  
  for (int i=5; i>=0; i-- ){  
   if ( tubestate[i]!=digit_buffer[i] ){  
    display_digit(i, digit_buffer[i]);  
    /*  
    Serial.print(tubestate[i]);  
    Serial.print(" ");  
    Serial.println(digit_buffer[i]);  
    //*/  
    //fade_digit(i, tubestate[i], digit_buffer[i]);  
    tubestate[i]=digit_buffer[i];  
   }  
  }  
  Serial.print("digit_buffer: ");  
  Serial.println(digit_buffer);  
  Serial.print("tubestate: ");  
  Serial.println(tubestate);  
  //*/  
 }  
 void fade_digit(int place, byte old_value, byte new_value){  
  for (int b=100; b>=30; b-=2 ){  
   Wire.beginTransmission(tube[place]); // seconds 1s  
   Wire.write(byte(0x0B));    //register address=dimmer  
   Wire.write(b);    //dimmer=50%  
   Wire.endTransmission(); // stop transmitting  
   delay(20);  
   }  
   Wire.beginTransmission(tube[place]); // tube  
   Wire.write(byte(0x00));    //set display  
   Wire.write(new_value-0x30);    //display digit  
   Wire.endTransmission(); // stop transmitting  
   for (int c=30; c<100; c+=2 ){  
   Wire.beginTransmission(tube[place]); // seconds 1s  
   Wire.write(byte(0x0B));    //register address=dimmer  
   Wire.write(c);    //dimmer=50%  
   Wire.endTransmission(); // stop transmitting  
   delay(20);  
   }  
  /*  
  for(int i=0; i<200; i++) {  
   display_digit(place, old_value);  
   for(int j=0; j<(200-i); j++) {  
    delayMicroseconds(1);  
   }  
   display_digit(place, new_value);  
   for(int j=0; j<i; j++) {  
    delayMicroseconds(4);  
   }  
  }  
  display_digit(place, new_value);  
  */  
 }  
 void display_digit(int place, byte value) {  
    if ( place == 5 ) { blink_led(); } // blink Arduino LED when the seconds digit increments  
    Wire.beginTransmission(tube[place]); // tube  
    Wire.write(byte(0x00));    //set display  
    Wire.write(value-0x30);    //display digit  
    Wire.endTransmission(); // stop transmitting  
 }  
 void init_gps() {  
    delay(500);  
    Wire.beginTransmission(byte(0x51)); // Write to GPS  
    Wire.write(byte(0x3C));    //set DL value  
    //Wire.write(byte(0x12));    //Set DL for Daylight Savings off  
    Wire.write(byte(0x22));    //Set DL for Daylight Savings on +1 hour  
    Wire.write(byte(0x08));    //set timezone hour offset to -8  
    Wire.endTransmission(); // stop transmitting  
    /*  
    Wire.beginTransmission(byte(0x51)); // Write to GPS  
    Wire.write(byte(0x3D));    //set timezone offset  
    Wire.write(byte(0x08));    //set timezone hour offset to -8  
    Wire.endTransmission(); // stop transmitting  
    */  
    Wire.beginTransmission(byte(0x51)); // Write to GPS  
    Wire.write(byte(0x02));    //start address 0x02  
    Wire.endTransmission(); // stop transmitting  
 }  
 void blink_led() {  
  ledstate = ~ledstate;  
  digitalWrite(LEDPIN, ledstate);  
 }  
 void pinball() {  
  char digit_buffer[6];  
  for (int i=0; i<100; i++ ){  
   sprintf(digit_buffer, "%06lu", random(1000000));  
   delay(50);  
   update_display(digit_buffer);  
   if (millis() - lasttick >= 100) {  
    lasttick = millis();  
    read_gps_time(digit);  
    SeeedOled.setTextXY(6,2);  
    SeeedOled.putString(digit);  
   }  
  }  
 }  
 //Celsius to Fahrenheit conversion  
 double Fahrenheit(double celsius)  
 {  
     return 1.8 * celsius + 32;  
 }  
 void update_oled_time() {  
 }  
 void update_oled_dht() {  
  if (millis() - lastdht >= 10000) {  
   lastdht = millis();  
   float h = dht.readHumidity();  
   float t = dht.readTemperature();  
   //SeeedOled.setTextXY(1,0);     //Set the cursor to Xth Page, Yth Column   
   //SeeedOled.putString("Humidity:"); //Print the String "Hello World!"  
   SeeedOled.setTextXY(2,2);     //Set the cursor to Xth Page, Yth Column   
   SeeedOled.putNumber(h); //Print the String  
   SeeedOled.putString("%");  
   //SeeedOled.setTextXY(3,0);     //Set the cursor to Xth Page, Yth Column   
   //SeeedOled.putString("Temperature:"); //Print the String "Hello World!"  
   SeeedOled.setTextXY(4,2);     //Set the cursor to Xth Page, Yth Column   
   SeeedOled.putNumber(Fahrenheit(t)); //Print the number  
   SeeedOled.putString(" F");  
  }  
 }  

No comments: