Wednesday, March 11, 2020

Rothko Clock Nixie Shield with 6 IN-17 tubes

This compact 6-tube Nixie shield was designed by Tyler a long time ago, when kickstarter was young, and I was following closely and contributing often. Soon after the successful campaign, this open source project, together with its supporting documentation and web site, seemed to have disappeared from the internet.
I already reviewed the Nixie shield here (as part of the "Rothko" clock), and covered it a bit more in another post.
Since I found it appealing, both as a soldering kit and as a miniature Nixie board, I also:
  • modified slightly the original schematic (eliminated the under-the-tube LEDs)
  • redesigned the PCB
  • named the clock "Rothko", to accompany my other clocks in the masters series, "Mondrian" and "Kandinsky". Note that, in this case, the "Rothko" clock is the union of 2 boards: this 6-tube Nixie shield and wsduino (which itself can be replaced by any Arduino with an RTC).


A kit for the Nixie shield is offered on Tindie. The PCB was designed to be self explanatory, but some people prefer the safety of assembly instructions. The slides below, recycled from the original deck, show the sequence of steps.


Once fully assembled, plug the Nixie shield into your Arduino, then upload this basic clock sketch (reads RTC and displays hours and seconds; no setting buttons, no Bluetooth, no buzzer/alarm):

#include "Arduino.h"
#include "avr/pgmspace.h"
#include "Wire.h"
#include "DS1307.h"
#include "avr/io.h"
#include "avr/interrupt.h"

// global variables
unsigned char INDEX = 1;   /* 1 to 6 */
unsigned char HOUR  = 7;   /* 1 to 12 */
unsigned char MINUTE = 45;  /* 0 to 59 */
unsigned char SECOND = 23;  /* 0 to 59 */

boolean is12HMode = false;


// read time from DS1307 at intervals;

#define MAX_TIME_READING_COUNTER  15000
long timeReadingCounter = MAX_TIME_READING_COUNTER;


// timer2 used for nixie tube multiplexing

ISR(TIMER2_COMPA_vect)
{
/* HOUR = 10, 11, or 12 or top of minute?*/
if ((HOUR / 10) || SECOND==0)
{
PORTB = 0x10;  // turn HOUR tens LED on
}
else
{
PORTB = 0x00;  // turn HOUR tens LED off
}

switch(INDEX++)

{
/* HOUR tens place */
case 1:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (HOUR / 10);

/* only turn anode on if one */

if (HOUR / 10)
{
PORTD = 0x04;    
}
break;

/* HOUR ones place */

case 2:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (HOUR % 10);

/* turn on anode */

PORTD = 0x08;
break;

/* MINUTE tens place */

case 3:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (MINUTE / 10);

/* turn on anode */

PORTD = 0x10;
break;

/* MINUTE ones place */

case 4:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (MINUTE % 10);

/* turn on anode */

PORTD = 0x20;
break;

/* SECOND tens place */

case 5:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (SECOND / 10);

/* turn on anode */

PORTD = 0x40;
break;

/* SECOND ones place */

case 6:
/* blank anodes */
PORTD = 0x00;

/* set cathode */

PORTB |= (SECOND % 10);

/* turn on anode */

PORTD = 0x80;

/* reset index */

INDEX = 1;
break;
}
}

void setup()
{
// configure pins
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);

cli();  // disable global interrupts


// timer2 1kHz interrupt

TCCR2A = 0x00;
TCCR2B = 0x00;
TCNT2 = 0x00;
OCR2A = 0xF9;
TCCR2A |= (1 << WGM21);
TCCR2B |= (1 << CS22);
TIMSK2 |= (1 << OCIE2A);

sei(); // enable global interrupts

}

void loop()
{
    timeReadingCounter++;
    if (timeReadingCounter > MAX_TIME_READING_COUNTER)
    {
      getTimeFromRTC();
      timeReadingCounter = 0;
    }
}

void getTimeFromRTC()
{
int16_t rtc[7];

RTC_DS1307.get(rtc, true);


SECOND = rtc[0];

MINUTE = rtc[1];
HOUR = rtc[2];
if (is12HMode && HOUR > 12)
HOUR = HOUR - 12;
}

void setTime(int hour, int minute, int second)
{
  RTC_DS1307.stop();
  RTC_DS1307.set(DS1307_SEC, second);
  RTC_DS1307.set(DS1307_MIN, minute);
  RTC_DS1307.set(DS1307_HR, hour);
  RTC_DS1307.start();
}



5 comments:

  1. So does this need a special Arduino with an RTC? Do you have to have an RTC to get this running??

    ReplyDelete
    Replies
    1. Hi Jack,
      The Nixie Shield requires an Arduino (or any other board with a controller, for that matter) to drive it.
      The timekeeping is done by an RTC, but you could also get the time from other sources (PC, through the serial port, NTP/WiFi etc.)
      I think the easiest and most independent way is still an RTC as is DS1307/DS3231.
      I have designed an Arduino-compatible board that has DS3231 on it, called, wsduino (also available in store), which is the easiest way to drive and control this Nixie shield.
      I hope this helps.
      Thank you.
      FlorinC

      Delete
    2. Jack,
      Link for the wsduino is here:
      http://timewitharduino.blogspot.com/2015/07/introducing-wsduino.html
      I can assemble it, program it with Rothko Nixie Clock and test if for you at the same price as the kit.

      Delete
  2. So do you need an Arduino with an RTC to get this running? Or will the clock display without an RTC (i.e. the RTC is optional)?

    ReplyDelete
    Replies
    1. RTC is optional as long as you read the time from some source. The Nixie shield could be used to display any other 6-digit number (e.g. the number of subscribers to your youtube channel), and not necessarily the time. I just used the shield to make a clock, one of the simpler applications.

      Delete