Domino Clock

So not too long ago I came across this domino clock that was featured on Hackaday. [ http://www.yankodesign.com/2010/12/14/domino-clock/ ] Now I figured that would be cool and I'm trying to figure it all out at once, so I decided to use shift registers to shift leds for the dots. Now I have read the shiftout tutorial a few times but still have some questions.

So if I'm correct for one register the binary value 100000000 will turn on the first pin of the register. But say I have 9 registers, my guess is I'll have a 71 bit value...

And using the internal clock instead of a real time clock. How could I have the time trigger the LEDs. ie. while(mins == 09) { digitalWrite(..... , HIGH); }

The only problem with doing this is that i have to write conditions for all 60 minutes and 12 hours. Is there an easier way to do this?

Thanks

Do a search for Stopwatch - this is an ongoing Exhibit project. The logic involved is pretty straightforward.

Alright I’ve done some work on it. Probably my way is way too long but anyways just see if it makes any sense.

#include <Time.h>

int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

byte dataArrayHour[12];

void setup() {

pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

     //Hour matrix bits
dataArrayHour[1] = 1024 //000000000000010000000000
dataArrayHour[2] = 525312 //000010000000010000000000
dataArrayHour[3] = 540736 //000010000100000001000000
dataArrayHour[4] = 8437824 //100000001100000001000000
dataArrayHour[5] = 8438848 //100000001100010001000000
dataArrayHour[6] = 8963136 //100010001100010001000000
dataArrayHour[7] = 8966464 //100010001101000101000000
dataArrayHour[8] = 10670400 //101000101101000101000000
dataArrayHour[9] = 10671424 //101000101101010101000000
dataArrayHour[10] = 11195712 //101010101101010101000000
dataArrayHour[11] = 11197248 //101010101101101101000000
dataArrayHour[12] = 11983680 //101101101101101101000000


}

void loop() {
  // put your main code here, to run repeatedly: 
if (hourFormat12() == 1) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, dataArrayHour[1]);
  digitalWrite(latchPin, HIGH);
}
else if (hourFormat12() == 2) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, dataArrayHour[2]);
  digitalWrite(latchPin, HIGH);
}
else if ........


}

You guys think this would work?

So no matter whether it would work or not, I had too much time so finished the code with a little bit of explanation.
I decided to use three shift register arrays so i can independantly change the displays.
The minute part is fairly long :slight_smile:

#include <Time.h>

//shift register array for hour stone
int latchPin1 = 8;
int clockPin1 = 12;
int dataPin1 = 11;

//shift register array for first minute stone
int latchPin2 = 2;
int clockPin2 = 4;
int dataPin2 = 3;

//shift register array for second minute stone
int latchPin3 = 5;
int clockPin3 = 7;
int dataPin3 = 6;

//hour and minute adjust buttons
const int hourPin = 9;
const int minPin = 10;

int hourState = 0;
int minState = 0;

byte dataArray[12];

void setup() {

pinMode(latchPin1, OUTPUT);
pinMode(clockPin1, OUTPUT);
pinMode(dataPin1, OUTPUT);

pinMode(latchPin2, OUTPUT);
pinMode(clockPin2, OUTPUT);
pinMode(dataPin2, OUTPUT);

pinMode(latchPin3, OUTPUT);
pinMode(clockPin3, OUTPUT);
pinMode(dataPin3, OUTPUT);

pinMode(hourPin, INPUT);
pinMode(minPin, INPUT);

     //Matrix bits
dataArray[1] = 1024; //000000000000010000000000
dataArray[2] = 525312; //000010000000010000000000
dataArray[3] = 540736; //000010000100000001000000
dataArray[4] = 8437824; //100000001100000001000000
dataArray[5] = 8438848; //100000001100010001000000
dataArray[6] = 8963136; //100010001100010001000000
dataArray[7] = 8966464; //100010001101000101000000
dataArray[8] = 10670400; //101000101101000101000000
dataArray[9] = 10671424; //101000101101010101000000
dataArray[10] = 11195712; //101010101101010101000000
dataArray[11] = 11197248; //101010101101101101000000
dataArray[12] = 11983680; //101101101101101101000000


}

void loop() {

hourState = digitalRead(hourPin);
minState = digitalRead(minPin);

//Hour adjustment
if (hourState == HIGH) {
  time_t t = now();
  t = t + 3600;
  setTime(t);
}
//Minute adjustment
if (minState == HIGH) {
  time_t t = now();
  t = t + 60;
  setTime(t);
}
//Hour stone output
if (hourFormat12() == 1) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[1]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 2) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[2]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 3) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[3]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 4) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[4]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 5) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[5]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 6) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[6]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 7) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[7]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 8) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[8]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 9) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[9]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 10) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[10]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 11) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[11]);
  digitalWrite(latchPin1, HIGH);
}
if (hourFormat12() == 12) {
  digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, dataArray[12]);
  digitalWrite(latchPin1, HIGH);
}
//Minute stones output
if (minute() == 0) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, 0);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 1) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[1]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 2) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[2]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 3) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[3]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 4) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[4]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 5) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[5]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 6) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[6]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 7) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[7]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 8) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[8]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 9) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, 0);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[9]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 10) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, 0);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 11) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[1]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 12) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[2]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 13) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[3]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 14) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[4]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 15) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[5]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 16) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[6]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 17) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[7]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 18) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[8]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 19) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[1]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, dataArray[9]);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
if (minute() == 20) {
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, dataArray[2]);
  shiftOut(dataPin3, clockPin3, MSBFIRST, 0);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
}
 etc...

You need some code like this to keep track of the hours & minutes gone by

  // when started flag is pressed, start counting in 10mS increments
  if (started == 1){
    currentmicros = micros();  // read the time.
    elapsedmicros = currentmicros - previousmicros;

    if (elapsedmicros >= interval) // 10 milliseconds have gone by
    {
      previousmicros  = previousmicros + elapsedmicros;  // save the time for the next comparison
      time_update = 1; // set flag to shift out the new time
    }

    if (time_update == 1){  // no updating if not at 10ms interval, skip this whole section
      // increment the counters, roll as needed, shift the digits out

      time_update = 0; // reset for next pass thru

      hundredths = hundredths +1;

      if (hundredths == 10){
        hundredths = 0;
        tenths = tenths +1;
      }

      if (tenths == 10){
        tenths = 0;
          ones_seconds = ones_seconds +1;
      }

          if (ones_seconds == 10){
      ones_seconds = 0;
        hundredths = hundredths +3;   // Speed up the clock!
        tens_seconds = tens_seconds +1;
    }

            if (tens_seconds == 6){
       tens_seconds = 0;
         hundredths = hundredths +6;   // Speed up the clock!
         ones_minutes = ones_minutes +1;
    }

      if (ones_minutes == 10){
        ones_minutes = 0;
        tens_minutes = tens_minutes +1;
      }
      if (tens_minutes == 6){
        tens_minutes = 0;
        ones_hours = ones_hours +1;  // not used in actual application, only here for stability test over longer time periods
      }
      if (ones_hours == 13){  // not used in actual application, only here for stability test over longer time periods
        ones_hours = 0;
        tens_hours = tens_hours +1;
      }
      if (paused == 0){
        // not paused, update the display

        // counters are all updated now, just do the shiftout one time here:
        digitalWrite(latchpin, LOW); // send the digits down to the shift registers!
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[hundredths]); // print the hundredths digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[tenths]);     // print the tenths digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_seconds]); // print the lower seconds digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_seconds]); // print the upper seconds digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[ones_minutes]); // print the lower sinutes digit
        shiftOut(datapin, clockpin, MSBFIRST, segdisp[tens_minutes]); // print the upper minutes digit
        digitalWrite(latchpin, HIGH);
        if (tenths == 0 && hundredths == 0){ // update on screen once a second
          
        }  // end of 1 second check
      } // end of time update is not paused
    }  // end if time to be updated

Ok, looks like we posted at similar times and you have something similar worked out already.

Hehe alright.

But you think that my method of shifting out data works?

I have ordered all of the electronics parts so I'll be posting updates as I go along.

Oh does anyone have experience with the Time library? I based my code on the readme but am not sure if it's all correct.

No, the shifting out probable needs some adjusting.
Shiftout sends out one byte of data one bit at a time. If you are sending 3 bytes,
10110110 11011011 01000000 data array 12 for example you will need three shiftout commands

Modifying the shiftout example from 2 bytes to 3 would yield something like this:

// Do this for MSBFIRST serial
// replace 'data' with you array definition
// shift out highbyte
shiftOut(dataPin, clock, MSBFIRST, (data >> 8));  
// shift out middlebyte
shiftOut(data, clock, MSBFIRST, (data>>8));
// shift out lowbyte
shiftOut(data, clock, MSBFIRST, data8);

This part is reading some buttons? You will need some debounce to keep from getting multiple presses:

hourState = digitalRead(hourPin);
minState = digitalRead(minPin);

//Hour adjustment
if (hourState == HIGH) {
  time_t t = now();
  t = t + 3600;
  setTime(t);
}
//Minute adjustment
if (minState == HIGH) {
  time_t t = now();
  t = t + 60;
  setTime(t);
}

Why not simply the code for writing out the display? You are only updating once a minute and once an hour, right?
So keep track of when the minute changes or when the hour changes and then send out an update.
It looks like
if (hourFormat12() == 11)
&
if (minute() == 0)
do the time tracking for you.
Just sit in a loop, and when you detect a difference, then do the shiftout commands

ex. old_hours = 0;
old_minutes = 0;
new_hours = hourformat12();
new_minutes = minute();
if (new_hours != old_hours) {
// send out new hours
hours = dataArray[new_hours] 
   digitalWrite(latchPin1, LOW);
  shiftOut(dataPin1, clockPin1, MSBFIRST, hours);
  digitalWrite(latchPin1, HIGH);
old_hours = new_hours;
}
if (new_minutes != old_minutes){
// do your math here to break up into tens_minutes & ones_minutes
//example 
// high_digit = 0
// if (new_minutes <10) {high_digit = 0;  low_digit = new_minutes;}  // minutes is from 00 to 09
// while (new_minutes >=10 { // loop thru as needed and lop off 10 minutes at a time,
//     high_digit = high_digit+1;  // updating the high_digit for every 10 minutes
//     new_minutes = new_minutes -10;}
//     low_digit = new_minutes;  // when less than 10 is left, the balance is the low digit
//     }
// 

tens_minutes = dataArray[high_digit];
ones_minutes = dataArray[low_digit];
  digitalWrite(latchPin2, LOW);
  digitalWrite(latchPin3, LOW);
  shiftOut(dataPin2, clockPin2, MSBFIRST, tens_minutes);
  shiftOut(dataPin3, clockPin3, MSBFIRST, one_minutes);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);
old_minutes = new_minutes;
}

Cool I’ll start adjusting the shiftout first and use that with the original code and as soon as thats working then ill try to implement some math to it.
Although it surprised me that the difference between shifting out the first and second byte is only a space.

shiftOut(dataPin, clock, MSBFIRST, (data >> 8));

shiftOut(data, clock, MSBFIRST, (data>>8));

The spaces are ignored during compiling. The " >>8" indicate the data is shifted by 8 places. Might even need to be 16, then 8, then none.

So I got all the parts in and started on the boards for the shift registers. The first one is a bit of a mess as i designed the layout on the go.

And two more of these

So I have my main board in the middle stone together with the arduino and through the 5 pin sockets it sends the clock, latch, data and power the the other two. I should get started on the housing this weekend so more to come.

Interesting looking board, where is that from?

Im from Holland and the easiest place to get everything is a place called Conrad. Bit over priced but they have most things you need. Heres a link to it, it's called a euro processor circuit board: http://www2.conrad-uk.com/goto.php?artikel=527831

You should update your profile to show that, there are others from Holland who could provide local help if needed, or suggest sources, etc. Must be like 2:30 AM there? While for me is just 8:30PM on a chilly winter night (and colder tomorrow, -7F tomorrow night!).

For another update: Turns out it actually works :) Used a very simple bit of code to just blink pin 1 on the register. Which actually blinks pin 1 on all three registers.

    digitalWrite(latchPin, LOW);
    delay(500);  
    shiftOut(dataPin, clockPin, MSBFIRST, 2);  
    digitalWrite(latchPin, HIGH);
    delay(500);
    digitalWrite(latchPin, LOW);
    delay(500);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);

So step 1 is done. Just step 2 of controlling the registers seperately still baffles me. If I shift them: shiftOut(dataPin, clockPin, MSBFIRST, (2 >> 8)); Nothing happens to pin 1 of the second shift register.

Hehe to be honest it is starting to piss me off because it can't be that hard right?? Anyone any tips??

Son Bitch!!! With my thoughts of 30 minutes ago: this can't be so hard I finally figured it out:

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);   //Last Register 
    shiftOut(dataPin, clockPin, MSBFIRST, 0);   //Second register
    shiftOut(dataPin, clockPin, MSBFIRST, 1);  //First Register
    digitalWrite(latchPin, HIGH);

And thats it, maybe some already knew but this was my eureka moment :) Anyways I visualised the chain of registers as a tube that you fill with marbles. You gotta start with the marbles (bits) that you want at the end of the chain and finish with the ones you want on top. So hereby an explaination just in case other semi-retarded people like me don't get this problem. hahaha

In this part 2 >> 8

2 is supposed to be the name of a 16-bit variable (something that is type 'int'). Then you shift out twice: shiftOut(dataPin, clockPin, MSBFIRST, minutes); // 1 numeral of minutes goes out shiftOut(dataPin, clockPin, MSBFIRST, (minutes>>8)); // 2nd numeral of minutes goes out

assuming you had previously converted the minutes into two 8 bit pieces to go out to the individual dots on the minutes dominos.

Can you post the hardware schematic you have hooked up? I think I am getting myself confused, you are using the time library which stores 2 numbers, hours & minutes, that you are then mapping to the domino dots?

Hmm i sort of get that but I finally worked out the code a bit:
This is at least with the way I figured it out, probably still not very efficient but better than the old “seperate definition for every minute of the hour”

#include <Time.h>


//Data Lines to the hour stone
int hlatchPin = 3;
int hclockPin = 4;
int hdataPin = 5;

//Data Lines to the decimal minute stone
int dlatchPin = 6;
int dclockPin = 7;
int ddataPin = 8;

//Data Lines to the single minute stone
int mlatchPin = 9;
int mclockPin = 10;
int mdataPin = 11;

int h = 0;
int m = 0;
int mins = 0;
int d = 0;
int previousHours = 0;
int previousMins = 0;

//I found it easiest to make a seperate data array for each shift register
byte dataArray1[12];
byte dataArray2[12];
byte dataArray3[12];



void setup() {

  pinMode(hlatchPin, OUTPUT);
  pinMode(hclockPin, OUTPUT);
  pinMode(hdataPin, OUTPUT);
  
  pinMode(dlatchPin, OUTPUT);
  pinMode(dclockPin, OUTPUT);
  pinMode(ddataPin, OUTPUT);
  
  pinMode(mlatchPin, OUTPUT);
  pinMode(mclockPin, OUTPUT);
  pinMode(mdataPin, OUTPUT);

  dataArray1[1] = 0;         dataArray2[1] = 0;      dataArray3[1] = 0;     
  dataArray1[2] = 0;         dataArray2[2] = 0;      dataArray3[2] = 0;      
  dataArray1[3] = 0;         dataArray2[3] = 0;      dataArray3[3] = 0;      
  dataArray1[4] = 0;         dataArray2[4] = 0;      dataArray3[4] = 0;      
  dataArray1[5] = 0;         dataArray2[5] = 0;      dataArray3[5] = 0;      
  dataArray1[6] = 0;         dataArray2[6] = 0;      dataArray3[6] = 0;      
  dataArray1[7] = 0;         dataArray2[7] = 0;      dataArray3[7] = 0;      
  dataArray1[8] = 0;         dataArray2[8] = 0;      dataArray3[8] = 0;      
  dataArray1[9] = 0;         dataArray2[9] = 0;      dataArray3[9] = 0;      
  dataArray1[10] = 0;        dataArray2[10] = 0;     dataArray3[10] = 0;
  dataArray1[11] = 0;        dataArray2[11] = 0;     dataArray3[11] = 0; 
  dataArray1[12] = 0;        dataArray2[12] = 0;     dataArray3[12] = 0;

}

void loop() {
  
    h = hourFormat12();
    m = minute();

    if(previousHours != h) {
      digitalWrite(hlatchPin, LOW);
      shiftOut(hdataPin, hclockPin, MSBFIRST, dataArray1[h]);
      shiftOut(hdataPin, hclockPin, MSBFIRST, dataArray2[h]);
      shiftOut(hdataPin, hclockPin, MSBFIRST, dataArray3[h]);
      digitalWrite(hlatchPin, HIGH);
      previousHours = h;
    }
    if(previousMins != m) {  
      mins = m;
      if(mins >= 10) {
        d = 0;
        while(mins >= 10) {
          mins = mins - 10;
          d = d + 1;
        }
        digitalWrite(dlatchPin, LOW);
        shiftOut(ddataPin, dclockPin, MSBFIRST, dataArray1[d]);
        shiftOut(ddataPin, dclockPin, MSBFIRST, dataArray2[d]);
        shiftOut(ddataPin, dclockPin, MSBFIRST, dataArray3[d]);
        digitalWrite(dlatchPin, HIGH);
        digitalWrite(mlatchPin, LOW);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray1[mins]);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray2[mins]);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray2[mins]);
        digitalWrite(mlatchPin, HIGH);        
      }
      else {
        digitalWrite(dlatchPin, LOW);
        shiftOut(ddataPin, dclockPin, MSBFIRST, 0);
        shiftOut(ddataPin, dclockPin, MSBFIRST, 0);
        shiftOut(ddataPin, dclockPin, MSBFIRST, 0);
        digitalWrite(dlatchPin, HIGH);
        digitalWrite(mlatchPin, LOW);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray1[mins]);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray2[mins]);
        shiftOut(mdataPin, mclockPin, MSBFIRST, dataArray3[mins]);
        digitalWrite(mlatchPin, HIGH);
      }
      previousMins = m;
    }

}

The hardware hookup i have to draw together as I did most on the go. The pin out from the shift registers i got to figure out because the wiring is a mess :slight_smile:
But to keep it short:
Each stone has its own dedicated data, clock and latch pin. And contains 3 shift registers.
Anyways ill post the circuit this afternoon / evening / some time soon.

Ok, I can follow that nicely!

One question - for the minutes, where the display is only 0-5 & 0-9, you could probably get by with smaller arrays.

Ah - just occurred to me - you probably have double-six as the domino acting as the display, so you need 12. Can't seem to scroll back to the original post while I reply, will have to go look at that again.

Anyway, now that you have a seperate variable for each digit, I don't think you have to worry about the >> as you don't have the shift registers tied together serially.

Okay, I envision this as your setup. You will need 2 shiftouts per digit, so the >> will come into play anyway. Hours: Flesh this out, I think you're basically there, just need the mapping in the array to go out to the LEDs

int hours_display[13];
number_to_display[0] =   B0000000000000000; // not used, convenient to have 1-12 = 1-12 later
number_t0_display[1] =  B0000000001000000;
number_to_display[2] =  B0100000001000000;
:
:
number_to_display[12] = B0011111100111111;
/* format for shifting out
// shift out highbyte
shiftOut(dataPin, clock, MSBFIRST, (data >> 8));  
// shift out lowbyte
shiftOut(data, clock, MSBFIRST, data);
*/
//hours
digitalWrite(hlatchPin, LOW);
shiftOut(hdataPin, hclockPin, MSBFIRST, (number_to_display[h] >>8));
shiftOut(hdataPin, hclockPin, MSBFIRST, hours_display[h]);
digitalWrite(hlatchPin, HIGH);
:
:
// upper minutes digit
digitalWrite(dlatchPin, LOW);
shiftOut(ddataPin, dclockPin, MSBFIRST, (number_to_display[d] >> 8));
shiftOut(ddataPin, dclockPin, MSBFIRST, number_to_display[d]);
digitalWrite(dlatchPin, HIGH);
// lower minutes digit
digitalWrite(mlatchPin, LOW);
shiftOut(mdataPin, mclockPin, MSBFIRST, (number_to_display[mins] >> 8));
shiftOut(mdataPin, mclockPin, MSBFIRST, number_to_display[mins]);
digitalWrite(mlatchPin, HIGH);
:
: