Nixie Clock #3
 Page :   [ 1 ]    [ 2 ]    [ 3 ]    [ 4 ]    [ 5 ]  

Here's some simple code to dispay the time.  This is pretty barebones and illustrates how to get this thing to display the time!  Overall it's pretty straight forward :)

#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <TimeLib.h>

#define PIN_LE    16  //Shift Register Latch Enable
#define PIN_CLK   17  //Shift Register Clock
#define PIN_DATA  19  //Shift Register Data
#define PIN_BL    18  //Shift Register Blank (0=display off     1=display on)

WiFiMulti wifiMulti;

const int timeZone = 16; 
const int dst = 0;

// lookup tables for the high and low value of mins/sec to determine
// which number needs to be displayed on each of the minutes and seconds tubes
// e.g. if the clock is to diplay 26 minutes then it 
// will look up the values at the 26th position and display a 2 on the high mins tube and a 6 on the low mins tube
const byte minsec_high[]= {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,11};
const byte minsec_low[] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,11};

// lookup tables for the high and low value of hours to determine
// which number needs to be displayed on each of the tubes for the hour display
// it can handle if its 24hr display or not and also if a leading zeo is displayed
// the "10" values are to indicate if the leading zero is blanked or not since its outside the range of a normal digit of 0-9
const byte hour_high[2][2][24] = {{{1,10,10,10,10,10,10,10,10,10,1,1,1,10,10,10,10,10,10,10,10,10,1,1},{1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1}},{{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2},{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2}}};
const byte hour_low[2][2][24]  = {{{2, 1, 2, 3, 4, 5, 6, 7, 8, 9,0,1,2, 1, 2, 3, 4, 5, 6, 7, 8, 9,0,1},{2,1,2,3,4,5,6,7,8,9,0,1,2,1,2,3,4,5,6,7,8,9,0,1}},{{0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3},{0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3}}};


volatile int show24hr = false;
volatile int leadingZero = false;   // whether or not to show the 
                                    // leading zero when in 12 hour mode
                                    // e.g. 7am would either show as 7 or 07

// shift register positions for each digit in each tube
//       Digit  0   1   2   3   4   5   6   7   8   9
int tube1[] = {29, 28, 27, 26, 25, 24, 23, 32, 31, 30};
int tube2[] = {18, 17, 16, 15, 14, 13, 12, 22, 20, 19};
int tube3[] = { 7,  6,  5,  4,  3,  2,  1, 11,  9,  8};
int tube4[] = {60, 59, 58, 57, 56, 55, 54, 64, 62, 61};
int tube5[] = {49, 48, 47, 46, 45, 44, 43, 53, 51, 50};
int tube6[] = {39, 38, 37, 36, 35, 34, 33, 42, 41, 40};

// for future reference.  the decimal point pins wired up are
// Tube 2 Left Side : shift register pos 21
// Tube 3 Left Side : shift register pos 10
// Tube 4 Left Side : shift register pos 63
// Tube 5 Left Side : shift register pos 52


// how many milliseconds the display will be on and off for
// this is for dimming.
// can control these values via some sort of analog input or through software.
volatile int onDuration = 4;
volatile int offDuration = 8;


// setting up the timer interrupt for blanking (dimming) the display
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

volatile int interruptState = 0;     // whether the display is in on state or off state
volatile int interruptCounter = 0;   // for counting interrupts fired (milliseconds) between state changes


// the function called by the timer interrupt that handles the 
// actual blanking.  it keeps track of the state of the display (on or off) 
// and handles the duration for that state accordingly
void IRAM_ATTR onTimer() {

  portENTER_CRITICAL_ISR(&timerMux);
  interruptCounter++;
  
  if (interruptState == 0){
    if (interruptCounter >= offDuration){
       interruptState = !interruptState;
       interruptCounter = 0;   
       digitalWrite(PIN_BL, HIGH);
    }
  } else {
    if (interruptCounter >= onDuration){
       interruptState = !interruptState;
       interruptCounter = 0;     
       digitalWrite(PIN_BL, LOW);
    }
  }
  
  portEXIT_CRITICAL_ISR(&timerMux);
 
}


void setup() {

  pinMode(PIN_LE,  OUTPUT);
  pinMode(PIN_BL,  OUTPUT);
  pinMode(PIN_DATA,OUTPUT);
  pinMode(PIN_CLK, OUTPUT);

  digitalWrite(PIN_BL, LOW);

  Serial.begin(115200);
  
  wifiMulti.addAP("YOUR_ACCESS_POINT_SSID", "YOUR_WIFI_PASSWORD");

  if(wifiMulti.run() == WL_CONNECTED) {
    Serial.println("");
    Serial.println("WiFi connected");
  }

  // stuff for the timer interrupt (found this online somewhere!)
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000, true);
  timerAlarmEnable(timer);

  configTime(timeZone * 3600, dst * 0, "pool.ntp.org", "time.nist.gov");
  Serial.println("\nWaiting for time");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("");


}


unsigned long previousSRMillis = 0;    // keeping track last time shift register values were clocked in

void loop() {

  unsigned long currentMillis = millis();
  
  if (currentMillis - previousSRMillis >= 250) {  // clocking in 4 times a second
    
    previousSRMillis = currentMillis;

    boolean srBuffer[64] = {0};

    time_t now;
    struct tm * timeinfo;
    time(&now);
    timeinfo = localtime(&now);  

    int hours = timeinfo->tm_hour;
    int seconds = timeinfo->tm_sec;
    int minutes = timeinfo->tm_min;

    // doing the lookups for what number to display then
    // looking up which shift register position
    // for each tube
    // "10" from the lookup table indicates to blank the tube since it is out of range.
    srBuffer[tube1[hour_high[show24hr][leadingZero][hours]] - 1] = (hour_high[show24hr][leadingZero][hours] == 10) ? 0 : 1;
    srBuffer[tube2[hour_low[show24hr][leadingZero][hours]] - 1] = 1;
    srBuffer[tube3[minsec_high[minutes]] - 1] = 1;
    srBuffer[tube4[minsec_low[minutes]] - 1] = 1;
    srBuffer[tube5[minsec_high[seconds]] - 1] = 1;
    srBuffer[tube6[minsec_low[seconds]] - 1] = 1;

    srBuffer[10 - 1] = 1;    // tube 2 decimal point
    srBuffer[52 - 1] = 1;   // tube 5 decimal point

    digitalWrite(PIN_LE, LOW);

    for(int i = 63;i >= 0;i--){ 
      
      digitalWrite(PIN_DATA,srBuffer[i]);
      digitalWrite(PIN_CLK,HIGH);
      delayMicroseconds(5);
      digitalWrite(PIN_CLK,LOW);
      delayMicroseconds(5);

    }

    digitalWrite(PIN_LE, HIGH);
    
  }

}

 

 

 

(Page 5 of 5)