15/01/2019

LED Matrix Fibonacci Clock

By snorlaxprime

I was inspired by all the Fibonacci clock out there, so I decided to design one my own. I am using the same LED Matrix circuit as described in earlier blog post.

So the idea is to show the Hours and Minute with the maximum of 12, it is behaving like the hour hand and minute hand displaying the time. So the left “Fibonacci” pattern is used to display the hour and the right Fibonacci pattern is used to display the minute.

I thought of displaying the seconds later, so that the clock seems alive, and the seconds is displayed using binary like the Binary clock in the previous post.

With the concept done, we are now ready to modify the Arduino code. But before that let’s have a look at how the pattern will be displayed in the following picture.

So the biggest challenge is to get the pattern combination right. To make sure the digit is showing correctly for each seconds, we need to make sure the data displayed correctly.

If you look at the output bytes, that is how it need to display to get the exact pattern as what is shown. For the seconds is showing in Binary we need to superimpose that on the pattern here. This is shown in the following code:

void display_seconds()
{
int sec_one = _second % 10;
int sec_ten = _second / 10;
output[0] = (sec_ten & 0x01) << 7 | (sec_one & 0x01) << 6 | (output[0] & 0x1F); // saved the previous minutes
output[1] = (sec_ten & 0x02) << 6 | (sec_one & 0x02) << 5 | (output[1] & 0x07);
output[2] = (sec_ten & 0x04) << 5 | (sec_one & 0x04) << 4 | (output[2] & 0x03);
output[3] = (sec_ten & 0x08) << 4 | (sec_one & 0x08) << 3 | (output[3] & 0x09);
}

As you can see to show the Seconds we need to break up the seconds into “one” and “ten” digit this is done in the first 2 line by dividing and modding the seconds with 10. Then the LSB will be shown in Output[0], and so on. Because the LED matrix LSB is at the bottom, we need to shift the digit 7 times for the “ten” to be displayed at the top, and the seconds will need to be shift 6 times to get it to the second row. Then we need to super impose the minute digit which is mask with Hexadecimal of 0x1F(the highest number for Output[0]). Thus the following code:

output[0] = (sec_ten & 0x01) << 7 | (sec_one & 0x01) << 6 | (output[0] & 0x1F);

The second bit is masked using 0x02 and because it is the second digit we only need to shift it 6 times for the “ten” and 5 times for the “one” and then masking the minute by 0x07 (the highest number for Output[1]). Hence the following code:

output[1] = (sec_ten & 0x02) << 6 | (sec_one & 0x02) << 5 | (output[1] & 0x07);

And so on until the last second digit, and hopefully you get the idea of the pattern.

The next challenge is to display the minute. To do that we need to understand the fibonacci number pattern first. We only use the first couple of numbers

1,1,2,3,5

Given the fibonacci numbers, number 1 can be represented either by the first 1 or the second 1 in the sequence, so we do a random number generator to choose which LED to light up. For number 2 can be represented by 1+1 or just 2, we also use the random number generator to choose which pattern to light up. Number 3 can be displayed as 2+1 (first), 2+1 (second) or just 3, this is also done using random number generator to choose which combination to light up. Continue this pattern until number 12 which need to light up 5+3+2+1+1. In simple terms, to read the minute we only need to count how many lights light up on the “right hand” corner. This is done in the following code:

void display_minute()
 {
   switch(_minute/5)
   {
     case 1:
       switch(random(2))
       {
         case 0:
           output[3] = 1; break;
         case 1:
           output[4] = 1; break;
  } break;
case 2:
  switch(random(2))
  {
    case 0:
      output[2] = 3; break;
    case 1:
      output[3] = 1;
      output[4] = 1; break;

  } break;
case 3:
  switch(random(3))
  {
    case 0:
      output[1] = 7; break;
    case 1:
      output[2] = 3;
      output[3] = 1; break;
    case 2:
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 4:
  switch(random(3))
  {
    case 0:
      output[1] = 7;
      output[3] = 1; break;
    case 1:
      output[1] = 7;
      output[4] = 1; break;
    case 2:
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 5:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F; break;
    case 1:
      output[1] = 7;
      output[2] = 3; break;
    case 2:
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break; 
  } break;
case 6:
  switch(random(4))
  {
    case 0:
      output[0] = 0x1F;
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[4] = 1; break;
    case 2:
      output[1] = 7;
      output[2] = 3;
      output[3] = 1; break;
    case 3:
      output[1] = 7;
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 7:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F;
      output[2] = 3; break;
    case 1:
      output[0] = 0x1F;
      output[3] = 1;
      output[4] = 1; break;
    case 2:
      output[1] = 7;
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 8:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7; break;
    case 1:
      output[0] = 0x1F;
      output[2] = 3;
      output[3] = 1; break;
    case 2:
      output[0] = 0x1F;
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 9:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[4] = 1; break;
  } break;
case 10:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 11:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; 
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3;
      output[4] = 1; break;        
  } break;
case 12:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; 
      output[3] = 1; 
      output[4] = 1; break;
}
}

We done the same with the top left corner of Fibonacci sequence to display the hour. However the one tricky bit is Output[3] and Output[4] is shared between hour and minute, so we need to mask the minute so that we didn’t lost it. This is done using the following code:

output[3] = 8 | (output[3] & 0x01);
output[4] = 8 | (output[4] & 0x01);

Then the output is combined and displayed. The full source code can be downloaded in the download section of shop. If you like this, please leave a comment or share it.

So the final result you can see in the following video: