UPDATE: This project has been successfully funded on Kickstarterand is now available for sale at http://store.basbrun.comThank you to all those who supported my campaign!

I present to you the Fibonacci Clock, a clock for nerds with style. Beautiful and fun at the same time, the clock uses the famous Fibonacci sequence to display time in a brand new way.

Step 1: How Do I Tell Time?

The Fibonacci sequence is a sequence of numbers created by the Italian mathematician Fibonacci in the 13th century. This is a sequence starting with 1 and 1, where each subsequent number is the sum of the previous two. For the clock I used the first 5 terms: 1, 1, 2, 3 and 5.

The screen of the clock is made up of five squares whose side lengths match the first five Fibonacci numbers: 1, 1, 2, 3 and 5. The hours are displayed using red and the minutes using green. When a square is used to display both the hours and minutes it turns blue. White squares are ignored. To tell time on the Fibonacci clock you need to do some math. To read the hour, simply add up the corresponding values of the red and blue squares. To read the minutes, do the same with the green and blue squares. The minutes are displayed in 5 minute increments (0 to 12) so you have to multiply your result by 5 to get the actual number.

Often, there are multiple ways to display a single time. To add to the challenge, the combinations are picked randomly from all the different ways a number can be displayed. There are, for example, 16 different ways to display 6:30 and you never know which one the clock will use!

Step 2: Circuit

I built the Fibonacci clock using an Atmega328P micro-controller using Arduino. You could buy an Arduino board and a DS1307 real-time clock break-out board and build a custom shield for your circuit but I preferred to build my own circuit board. That allows me to keep size small and price low.

Step 3: Buttons

The three buttons attached to Arduino pins #3,#4 and #6 are used together to change time. Button on pin #3 can be used alone to change the color palette of the LEDs. An extra button is attached to pin #5 to change between different modes of the clock. Two modes are lamp modes and the default mode is the clock. All buttons are connected to the Arduino pins with a 10K pull-down resistor in parallel.

Step 4: Real-Time Clock

The real-time clock chip DS1307 is connected to the Arduino analog pins 4 and 5 with two 22K pull-up resistors. The clock pin 5 (SDA) is connected to the Atmega328P pin 27 (Arduino A4) and the clock pin 6 (SCL) is connected to the Atmega329P pin 29 (Arduino A5). To keep time while unplugged the DS1307 chip needs a 3V battery connected to pint 3 and 4 of the chip. Finally, the real-time clock is driven by a 32KHz crystal connected on pins 1 and 2. A 5V power is applied on pin 8.

Step 5: LED Pixels Strip

I am using LED pixels built on top of the WS2811 drivers. These microcontrollers allows me to set the color of each individual LED with a single output on the Arduino microcontroller. The Arduino pin used to control the LEDs in this project is pin #8 (Atmega328P pin #14).

Step 6: Microcontroller

You will find all the details on how to connect the Atmega328P to make an Arduino clone on my post “Build an Arduino Clone“. I added a new feature in this project, an FTDI port to program your Arduino microcontroller directly on this circuit. You connect pin one to the reset pin of the Arduino trough a 0.1uF capacitor to synchronize your uploader with the chip bootup sequence.

Pin 2 (RX) of the FTDI port connects to pin 3 of the Atmega328P(Arduino 1-TX) and pin 3 (TX) of the FTDI connector connects to pin 2 of the Atmega328P (Arduino 0 – RX). Finally FTDI pin 4 goes to 5V and 5 and 6 to ground.

Step 7: The Enclosure

The video presents all the steps for the construction of the Fibonacci clock enclosure. The idea is to create 5 square compartments in the clock, two inches deep, matching the size of the five first terms of the Fibonacci sequence, 1, 1, 2, 3 and 5. The LEDs are distributed in all squares and connected in the back of the clock to the circuit board.

The enclosure is built out of birch plywood. The frame is 1/4″ thick and the back panel is 1/8″ thick. The separators are 1/16″ thick and can be made of any opaque material. The dimensions of the clock are 8″x5″x4″. The front of the clock is a piece of 1/8″ thick semi-transparent plexiglass. The separators are marked using a Sharpie pen.

The wood finish is a water based varnish applied after a good sanding using 220 sand paper.

Step 8: Make It a Lamp

The Fibonacci clock can also be converted into an ambiant lamp! The code published already support two lamp modes. Simply push the mode button to toggle between the three modes. The code is open for you to hack, feel free to implement your own modes!

Step 9: You'r Done

You are done! The Fibonacci clock is a fantastic discussion starter...bring it to your next NERD get together or to the Christmas family reunion!

Thanks for reading/watching!

Step 10: The Code

You can find the source code on my github account:


<p>Fascinating clock to build. Made it myself using hardboard enclosure and 8 MM RGB Neopixel LEDs</p>
<p>Here are some pictures. I failed in producing the original pcb so i decided to take the the design one step simpeler by using an arduino nano and a ds1307 module.</p><p>Then I needed to fabricate a custom pcb to house the parts. In Fritzing that is quite easy. Quite happy with the result. Still have to fabricate the back lid.</p><p>I will be using the fibonacci clock in the classes R&amp;D that i teach. And showing off to colleagues off course :-).</p>
<p>Hi friend, sorry I would like to know which library you have used with that module because I have mounted it as you using RTClib-master and it does not show me the hours or anything. a greeting</p>
<p>BTW i moved to the ds3231 module as it is much more accurate. Adapting the code for this module is very easy and available on request.</p>
<p>Here is the code for a setup with ds3231:</p><p>// Fibonacci Clock</p><p>//</p><p>// This program is free software; you can redistribute it and/or</p><p>// modify it under the terms of the GNU General Public License Version 2</p><p>//</p><p>// This program is distributed in the hope that it will be useful,</p><p>// but WITHOUT ANY WARRANTY; without even the implied warranty of</p><p>// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</p><p>// GNU General Public License for more details.</p><p>//</p><p>// You should have received a copy of the GNU General Public License</p><p>// along with this program; if not, write to the Free Software</p><p>// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p><p>//</p><p>// You will find the latest version of this code at the following address:</p><p>// https://github.com/pchretien/fibo</p><p>//</p><p>// This project contains code and libraries provided by Adafruit Industries and can be found on their Github account at:</p><p>// https://github.com/adafruit</p><p>//</p><p>// Credits:</p><p>// See the credit.txt file for the list of all the backers of the Kickstarter campaign.</p><p>// https://www.kickstarter.com/projects/basbrun/fibonacci-clock-an-open-source-clock-for-nerds-wit/description</p><p>//</p><p>#include &lt;Wire.h&gt;</p><p>#include &quot;RTClib.h&quot;</p><p>#include &lt;Adafruit_NeoPixel.h&gt;</p><p>#define STRIP_PIN 8</p><p>#define HOUR_PIN 3 // RED</p><p>#define MINUTE_PIN 4 // GREEN</p><p>#define BTN_PIN 5 // BLACK</p><p>#define SET_PIN 6 // WHITE</p><p>#define DEBOUNCE_DELAY 10</p><p>#define MAX_BUTTONS_INPUT 20</p><p>#define MAX_MODES 3</p><p>#define MAX_PALETTES 10</p><p>#define TOTAL_PALETTES 10</p><p>#define CLOCK_PIXELS 5</p><p>// Parameter 1 = number of pixels in strip</p><p>// Parameter 2 = pin number (most are valid)</p><p>// Parameter 3 = pixel type flags, add together as needed:</p><p>// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)</p><p>// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)</p><p>// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)</p><p>// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)</p><p>Adafruit_NeoPixel strip = Adafruit_NeoPixel(9, STRIP_PIN, NEO_RGB + NEO_KHZ800);</p><p>byte bits[CLOCK_PIXELS];</p><p>uint32_t black = strip.Color(0,0,0);</p><p>uint32_t colors[TOTAL_PALETTES][4] = </p><p> {</p><p> {</p><p> // #1 RGB</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(255,10,10), // hours</p><p> strip.Color(10,255,10), // minutes</p><p> strip.Color(10,10,255) // both;</p><p> }, </p><p> {</p><p> // #2 Mondrian</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(255,10,10), // hours</p><p> strip.Color(248,222,0), // minutes</p><p> strip.Color(10,10,255) // both;</p><p> }, </p><p> {</p><p> // #3 Basbrun</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(80,40,0), // hours</p><p> strip.Color(20,200,20), // minutes</p><p> strip.Color(255,100,10) // both;</p><p> },</p><p> {</p><p> // #4 80's</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(245,100,201), // hours</p><p> strip.Color(114,247,54), // minutes</p><p> strip.Color(113,235,219) // both;</p><p> }</p><p> ,</p><p> {</p><p> // #5 Pastel</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(255,123,123), // hours</p><p> strip.Color(143,255,112), // minutes</p><p> strip.Color(120,120,255) // both;</p><p> }</p><p> ,</p><p> {</p><p> // #6 Modern</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(212,49,45), // hours</p><p> strip.Color(145,210,49), // minutes</p><p> strip.Color(141,95,224) // both;</p><p> }</p><p> ,</p><p> {</p><p> // #7 Cold</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(209,62,200), // hours</p><p> strip.Color(69,232,224), // minutes</p><p> strip.Color(80,70,202) // both;</p><p> }</p><p> ,</p><p> {</p><p> // #8 Warm</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(237,20,20), // hours</p><p> strip.Color(246,243,54), // minutes</p><p> strip.Color(255,126,21) // both;</p><p> }</p><p> ,</p><p> {</p><p> //#9 Earth</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(70,35,0), // hours</p><p> strip.Color(70,122,10), // minutes</p><p> strip.Color(200,182,0) // both;</p><p> }</p><p> ,</p><p> {</p><p> // #10 Dark</p><p> strip.Color(255,255,255), // off</p><p> strip.Color(211,34,34), // hours</p><p> strip.Color(80,151,78), // minutes</p><p> strip.Color(16,24,149) // both;</p><p> }</p><p> }; </p><p>RTC_DS3231 rtc;</p><p>boolean on = true;</p><p>byte oldHours = 0;</p><p>byte oldMinutes = 0;</p><p>int lastButtonValue[MAX_BUTTONS_INPUT];</p><p>int currentButtonValue[MAX_BUTTONS_INPUT];</p><p>int mode = 0;</p><p>int palette = 0;</p><p>byte error = 0;</p><p>byte oldError = 0;</p><p>void setup() </p><p>{</p><p> Serial.begin(9600);</p><p> delay(3000); // wait for console opening</p><p> // Initialize the strip and set all pixels to 'off'</p><p> strip.begin();</p><p> strip.show(); </p><p> Wire.begin();</p><p> rtc.begin();</p><p> if (! rtc.begin()) {</p><p> Serial.println(&quot;Couldn't find RTC&quot;);</p><p> while (1);</p><p> }</p><p> if (rtc.lostPower()) {</p><p> Serial.println(&quot;RTC lost power, lets set the time!&quot;);</p><p> // following line sets the RTC to the date &amp; time this sketch was compiled</p><p> rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));</p><p> // This line sets the RTC with an explicit date &amp; time, for example to set</p><p> // January 21, 2014 at 3am you would call:</p><p> // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));</p><p> }</p><p> // Make the random() function return unpredictable results</p><p> randomSeed(rtc.now().unixtime());</p><p> pinMode(HOUR_PIN, INPUT); //RED</p><p> pinMode(MINUTE_PIN, INPUT); //GREEN</p><p> pinMode(BTN_PIN, INPUT); //BLACK</p><p> pinMode(SET_PIN, INPUT); //WHITE</p><p> pinMode(13, OUTPUT);</p><p> for(int i=0;i&lt;4;i++)</p><p> {</p><p> digitalWrite(13, HIGH);</p><p> delay(250);</p><p> digitalWrite(13, LOW);</p><p> delay(250);</p><p> }</p><p> // Make sure the time is always displayed the first </p><p> // time the clock is powered on.</p><p> oldHours = 99;</p><p> DateTime now = rtc.now();</p><p> Serial.print(now.hour(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(now.minute(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(now.second(), DEC);</p><p> Serial.println(); </p><p>}</p><p>void loop() </p><p>{</p><p> // 9:25</p><p>// setPixel(0, strip.Color(255,255,255));</p><p>// setPixel(1, strip.Color(255,10,10));</p><p>// setPixel(2, strip.Color(10,255,10));</p><p>// setPixel(3, strip.Color(10,10,255));</p><p>// setPixel(4, strip.Color(255,10,10));</p><p>// strip.show();</p><p>// return; </p><p> // Read buttons</p><p> int set_button = debounce(SET_PIN);</p><p> int hour_button = debounce(HOUR_PIN);</p><p> int minute_button = debounce(MINUTE_PIN);</p><p> int button = debounce(BTN_PIN);</p><p> if(set_button &amp;&amp; button &amp;&amp; hasChanged(BTN_PIN))</p><p> { </p><p> for(int i=0; i&lt;100; i++)</p><p> {</p><p> if(!debounce(SET_PIN) || !debounce(BTN_PIN))</p><p> break;</p><p> }</p><p> if(debounce(SET_PIN) &amp;&amp; debounce(BTN_PIN))</p><p> {</p><p> checkErrors();</p><p> }</p><p> } </p><p> else if( set_button &amp;&amp; hour_button &amp;&amp; hasChanged(HOUR_PIN))</p><p> {</p><p> DateTime newTime = DateTime(rtc.now().unixtime()+3600);</p><p> rtc.adjust( newTime );</p><p> displayCurrentTime();</p><p> }</p><p> else if( set_button &amp;&amp; minute_button &amp;&amp; hasChanged(MINUTE_PIN))</p><p> {</p><p> DateTime fixTime = rtc.now();</p><p> DateTime newTime = DateTime(</p><p> fixTime.year(), </p><p> fixTime.month(), </p><p> fixTime.day(), </p><p> fixTime.hour(), </p><p> ((fixTime.minute()-fixTime.minute()%5)+5)%60, </p><p> 0);</p><p> rtc.adjust( newTime );</p><p> displayCurrentTime();</p><p> }</p><p> else if( minute_button &amp;&amp; hasChanged(MINUTE_PIN))</p><p> {</p><p> toggleOnOff();</p><p> } </p><p> else if( hour_button &amp;&amp; hasChanged(HOUR_PIN))</p><p> {</p><p> palette = (palette+1)%MAX_PALETTES;</p><p> oldHours = 99;</p><p> oldError = 99;</p><p> } </p><p> else if( button &amp;&amp; hasChanged(BTN_PIN))</p><p> {</p><p> mode = mode + 1;</p><p> if(mode &gt;= MAX_MODES)</p><p> mode = 0;</p><p> }</p><p> // Store buttons new values</p><p> resetButtonValues();</p><p> switch(mode)</p><p> {</p><p> case 0: </p><p> displayCurrentTime();</p><p> break;</p><p> case 1:</p><p> oldHours = 99;</p><p> rainbowCycle(20);</p><p> break;</p><p> case 2:</p><p> oldHours = 99;</p><p> rainbow(20);</p><p> break;</p><p> case 3:</p><p> oldHours = 99;</p><p> // Display error code</p><p> displayErrorCode();</p><p> break;</p><p> } </p><p>}</p><p>int debounce(int pin)</p><p>{</p><p> int val = digitalRead(pin);</p><p> if( val == lastButtonValue[pin] )</p><p> {</p><p> currentButtonValue[pin] = val;</p><p> return val;</p><p> }</p><p> delay(DEBOUNCE_DELAY);</p><p> val = digitalRead(pin);</p><p> if( val != lastButtonValue[pin] )</p><p> {</p><p> currentButtonValue[pin] = val;</p><p> return val;</p><p> }</p><p> currentButtonValue[pin] = lastButtonValue[pin];</p><p> return lastButtonValue[pin];</p><p>}</p><p>boolean hasChanged(int pin)</p><p>{</p><p> return lastButtonValue[pin] != currentButtonValue[pin];</p><p>}</p><p>void resetButtonValues()</p><p>{</p><p> for(int i=0; i&lt;MAX_BUTTONS_INPUT; i++)</p><p> lastButtonValue[i] = currentButtonValue[i];</p><p>}</p><p>void displayCurrentTime()</p><p>{</p><p> DateTime now = rtc.now(); </p><p> setTime(now.hour()%12, now.minute()); </p><p>}</p><p>void setTime(byte hours, byte minutes)</p><p>{</p><p> if(oldHours == hours &amp;&amp; oldMinutes/5 == minutes/5)</p><p> return;</p><p> oldHours = hours;</p><p> oldMinutes = minutes;</p><p> for(int i=0; i&lt;CLOCK_PIXELS; i++)</p><p> bits[i] = 0;</p><p> setBits(hours, 0x01);</p><p> setBits(minutes/5, 0x02);</p><p> for(int i=0; i&lt;CLOCK_PIXELS; i++)</p><p> { </p><p> setPixel(i, colors[palette][bits[i]]);</p><p> strip.show();</p><p> }</p><p>}</p><p>void displayErrorCode()</p><p>{</p><p> if(oldError == error)</p><p> return;</p><p> oldError = error;</p><p> for(int i=0; i&lt;CLOCK_PIXELS; i++)</p><p> bits[i] = 0;</p><p> if(error == 0)</p><p> {</p><p> setBits(12, 0x02);</p><p> }</p><p> else</p><p> {</p><p> setBits(error, 0x01);</p><p> }</p><p> for(int i=0; i&lt;CLOCK_PIXELS; i++)</p><p> { </p><p> setPixel(i, colors[palette][bits[i]]);</p><p> }</p><p> strip.show();</p><p>}</p><p>void setBits(byte value, byte offset)</p><p>{</p><p> switch(value)</p><p> {</p><p> case 1:</p><p> switch(random(2))</p><p> {</p><p> case 0:</p><p> bits[0]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[1]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 2:</p><p> switch(random(2))</p><p> {</p><p> case 0:</p><p> bits[2]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 3:</p><p> switch(random(3))</p><p> {</p><p> case 0:</p><p> bits[3]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[0]|=offset;</p><p> bits[2]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 4:</p><p> switch(random(3))</p><p> {</p><p> case 0:</p><p> bits[0]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[1]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 5:</p><p> switch(random(3))</p><p> {</p><p> case 0:</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 6:</p><p> switch(random(4))</p><p> {</p><p> case 0:</p><p> bits[0]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[1]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[0]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> case 3:</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 7:</p><p> switch(random(3))</p><p> {</p><p> case 0:</p><p> bits[2]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> break;</p><p> }</p><p> break;</p><p> case 8:</p><p> switch(random(3))</p><p> {</p><p> case 0:</p><p> bits[3]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[0]|=offset;</p><p> bits[2]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 2:</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> } </p><p> break;</p><p> case 9:</p><p> switch(random(2))</p><p> {</p><p> case 0:</p><p> bits[0]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[1]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> } </p><p> break;</p><p> case 10:</p><p> switch(random(2))</p><p> {</p><p> case 0:</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> case 1:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset;</p><p> break;</p><p> } </p><p> break;</p><p> case 11:</p><p> switch(random(2))</p><p> {</p><p> case 0:</p><p> bits[0]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset; </p><p> break;</p><p> case 1:</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset; </p><p> break;</p><p> } </p><p> break;</p><p> case 12:</p><p> bits[0]|=offset;</p><p> bits[1]|=offset;</p><p> bits[2]|=offset;</p><p> bits[3]|=offset;</p><p> bits[4]|=offset; </p><p> break;</p><p> }</p><p>}</p><p>void setPixel(byte pixel, uint32_t color)</p><p>{</p><p> if(!on)</p><p> return;</p><p> switch(pixel)</p><p> {</p><p> case 0:</p><p> strip.setPixelColor(0, color);</p><p> break;</p><p> case 1:</p><p> strip.setPixelColor(1, color);</p><p> break;</p><p> case 2:</p><p> strip.setPixelColor(2, color);</p><p> break;</p><p> case 3:</p><p> strip.setPixelColor(3, color);</p><p> strip.setPixelColor(4, color);</p><p> break;</p><p> case 4:</p><p> strip.setPixelColor(5, color);</p><p> strip.setPixelColor(6, color);</p><p> strip.setPixelColor(7, color);</p><p> strip.setPixelColor(8, color);</p><p> strip.setPixelColor(9, color);</p><p> break;</p><p> };</p><p>}</p><p>void rainbow(uint8_t wait) </p><p>{</p><p> uint16_t i, j;</p><p> for(j=0; j&lt;256; j++) </p><p> {</p><p> for(i=0; i&lt; CLOCK_PIXELS; i++) </p><p> {</p><p> setPixel(i, Wheel((i+j) &amp; 255));</p><p> }</p><p> strip.show();</p><p> delay(wait);</p><p> if(debounce(BTN_PIN) &amp;&amp; hasChanged(BTN_PIN))</p><p> {</p><p> mode = (mode + 1)%MAX_MODES;</p><p> resetButtonValues();</p><p> return;</p><p> }</p><p> if(debounce(MINUTE_PIN) &amp;&amp; hasChanged(MINUTE_PIN))</p><p> {</p><p> toggleOnOff();</p><p> resetButtonValues();</p><p> return;</p><p> }</p><p> resetButtonValues();</p><p> }</p><p>}</p><p>// Slightly different, this makes the rainbow equally distributed throughout</p><p>void rainbowCycle(uint8_t wait) </p><p>{</p><p> uint16_t i, j;</p><p> for(j=0; j&lt;256*5; j++) </p><p> { </p><p> // 5 cycles of all colors on wheel</p><p> for(i=0; i&lt; CLOCK_PIXELS; i++) </p><p> {</p><p> setPixel(i, Wheel(((i * 256 / CLOCK_PIXELS) + j) &amp; 255));</p><p> }</p><p> strip.show();</p><p> delay(wait);</p><p> if(debounce(BTN_PIN) &amp;&amp; hasChanged(BTN_PIN))</p><p> {</p><p> mode = (mode + 1)%MAX_MODES;</p><p> resetButtonValues();</p><p> return;</p><p> }</p><p> if(debounce(MINUTE_PIN) &amp;&amp; hasChanged(MINUTE_PIN))</p><p> {</p><p> toggleOnOff();</p><p> resetButtonValues();</p><p> return;</p><p> }</p><p> resetButtonValues();</p><p> }</p><p>}</p><p>// Input a value 0 to 255 to get a color value.</p><p>// The colours are a transition r - g - b - back to r.</p><p>uint32_t Wheel(byte WheelPos) </p><p>{</p><p> if(WheelPos &lt; 85) </p><p> {</p><p> return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);</p><p> } </p><p> else if(WheelPos &lt; 170) </p><p> {</p><p> WheelPos -= 85;</p><p> return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);</p><p> } </p><p> else </p><p> {</p><p> WheelPos -= 170;</p><p> return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);</p><p> }</p><p>}</p><p>void toggleOnOff()</p><p>{</p><p> if( on )</p><p> {</p><p> for( int i=0; i&lt;CLOCK_PIXELS; i++)</p><p> setPixel(i, black);</p><p> strip.show();</p><p> }</p><p> on = !on;</p><p> if(on)</p><p> {</p><p> oldHours = 99;</p><p> oldError = 99;</p><p> }</p><p>}</p><p>void checkErrors()</p><p>{</p><p> error = 0;</p><p> oldError = 99;</p><p> mode = 3;</p><p> palette = 0;</p><p> // Test sequence</p><p> if (! rtc.begin())</p><p> {</p><p> error |= 0x1;</p><p> }</p><p> int time1 = rtc.now().unixtime();</p><p> delay(1200);</p><p> int time2 = rtc.now().unixtime();</p><p> if(time1 == time2)</p><p> {</p><p> error |= 0x02;</p><p> } </p><p>}</p><p>void printDateTime(DateTime now)</p><p>{</p><p> Serial.print(now.year(), DEC);</p><p> Serial.print('/');</p><p> Serial.print(now.month(), DEC);</p><p> Serial.print('/');</p><p> Serial.print(now.day(), DEC);</p><p> Serial.print(' ');</p><p> Serial.print(now.hour(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(now.minute(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(now.second(), DEC);</p><p> Serial.println();</p><p> Serial.print(&quot; since midnight 1/1/1970 = &quot;);</p><p> Serial.print(now.unixtime());</p><p> Serial.print(&quot;s = &quot;);</p><p> Serial.print(now.unixtime() / 86400L);</p><p> Serial.println(&quot;d&quot;);</p><p> // calculate a date which is 7 days and 30 seconds into the future</p><p> DateTime future (now.unixtime() + 7 * 86400L + 30);</p><p> Serial.print(&quot; now + 7d + 30s: &quot;);</p><p> Serial.print(future.year(), DEC);</p><p> Serial.print('/');</p><p> Serial.print(future.month(), DEC);</p><p> Serial.print('/');</p><p> Serial.print(future.day(), DEC);</p><p> Serial.print(' ');</p><p> Serial.print(future.hour(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(future.minute(), DEC);</p><p> Serial.print(':');</p><p> Serial.print(future.second(), DEC);</p><p> Serial.println();</p><p> Serial.println();</p><p> delay(1000);</p><p>}</p>
<p>Wow, great. Thanks a lot</p>
<p>Hi,</p><p>Your project looks great. Would you mind sharing your code or how you changed the original code? Thanks!</p>
<p>Did you rename the library folder from RTClib-master to RTClib?</p>
<p>It is the same library as in the original design.</p><p>Maybe give this a try:</p><p>https://github.com/adafruit/RTClib</p>
<p>Hi,</p><p>Your clock looks great! I like the way you built your circuit ... What and where are you teaching? </p><p>Thanks for sharing with the community!</p><p>Phil</p>
<p>Hah, its a bit quick and dirty, but it works.</p><p>I am a teacher in biology and research&amp;development to youngster aging from 12 to 17 years old in the Netherlands.</p><p>Your clock is a demonstration of what can emerge when creativity and technology meet.... ingenuity!</p><p>For over two month's now, I have a lot of fun with your clock on a daily basis. Designing the custom pcb, the woodworking, sourcing the parts, the build and, off course the final result.</p><p>THANK YOU FOR SHARING THE FIBONACCI CLOCK IN THE OPEN SOURCE MANNER.</p><p>Maybe there is a market for ready made clocks in the Netherlands....;-)</p>
<p>Here are the pictures of my project. I realized it by using an arduino nano and an ds3231. It was a great pleasure to build it although my hair turned gray sometimes. </p><p>To house the parts I used a veroboard. I placed this board in a way that I still can reach the mini-usb from the arduino nano. This allows me to change the program and use other color schemes for example.</p>
<p>I have just published an article here at Instructables. I hope you can appreciate it. Regards, Eric</p><p><a href="https://www.instructables.com/id/Fibonacci-Clock-Modified" rel="nofollow">https://www.instructables.com/id/Fibonacci-Clock-Mo...</a></p>
<p>Thanks to your project I built <a href="https://www.instructables.com/id/Geek-Clock-FiBiNo-Fibonacci-Binary-Arduino-Clock/">my watch</a>, which I published today.</p><p>It is a bit easier (I did not use the Neopixel) but I added the minutes and the seconds in binary format and I also added a display</p>
<p>I am trying to build the fibonacci clock, I have already bought all the components excepct the case and the pcb. I want to order the pcb but I have big problems in the specifications because I can not see this information in the fritzing program. The fabric ask me for this specifications for my order:</p><p>material: normal FR4 board / aluminium board / blind vias board ?</p><p>fr4-tg: tg130-140/ 150-160 / 170-180 ?</p><p>thickness: from 0.4 to 2.4 mm &iquest;1.6?</p><p>min track/spacing: 4/4mil, 5/5mil, 6/6mil ?</p><p>min hole size: 0.2mm, 0.25, 0.3 ?</p><p>surface finish: HASL with lead, HASL lead free, inmersion gold, hard gold ?</p><p>via process: tenting vias, plugged vias, vias no covered ?</p><p>finished copper: 1 oz Cu, 2,3, 4 ?</p><p>Somebody can help me, please?</p>
<p>What a neat idea! I'm not a HW guy, more of a SW person. Really like the way blue functions as a double signifier, for hours and minutes, in order to permit two seperate tallyings from 0 to 11 on the clock. But I think it needs a third tally, some mechanism to get in all the minutes from 0 to 59 onto the display.</p><p>Thought of two approaches to this. </p><p>First thought was to add a third signal to the display which basically counts from 0 to 4, incrementing every minute. This signal would tell how many single minutes to add to the calculated time based upon the previously existing two tallies. My idea would be to arc counter-clockwise from the single 1x1 cell which is strictly in the interior of the fibo rectangle, i.e the one without any exterior edges. That (interior) 1X1 cell would indicate: 0 added minutes. The other 1X1 cell directly north of it (moving counter-clockwise) would indicate: 1 added minute. The 2X2 square would indicate:2; and the 3X3 square would indicate:3; finally the 5X5 square cell would indicate: 4 added minutes. </p><p>How to distinguish which of the five cells are &quot;on&quot; in order to know how many single minutes to add? I suppose color saturation. Normally, I'd envision all colors to be muted for the other two tallies (hours and 5-minute intervals). The one brighter square would give the number of added minutes. If some sore of analog(?) design could be used to give a gradual shading depth during the course of 60 seconds, then you could even build in a rough visual signal about how far along within the course of a given minute the current time is. This would make for a more living, constantly subtly changing clockface.</p><p>What do you think?</p><p>The second idea I had, which is still half-baked, revolved around playing with primary colors and secondary ones. If either a white or blue or green or red square were to move towards (or suddenly be) grey, purple, yellow, or orange -- then this could also serve as a signal about how many minutes, 0 thru 4, to add.</p><p>Anyway, just messing around with the concept. I could see how the software coding for adding a third tally would not present huge problems, but have no idea what complexity it introduces in the hardware.</p><p>~RS</p>
<p>Hi,</p><p>That's a great idea! Many people wrote me about their solution for a clock accurate to the minute! I think it's awesome that people get so involved in this weird project. This is what open source is all about! </p><p>A teacher from the UK wrote me a message about the class he gave using my clock project. He asked the kids what they would do to improve the clock ... there are some pretty cool ideas! I posted an article on my blog: <a href="http://basbrun.com/2015/05/29/the-fibonacci-clock-in-the-classroom/" rel="nofollow">http://basbrun.com/2015/05/29/the-fibonacci-clock-...</a></p><p>Have a nice day!</p>
<p>Hi any direct link by using Arduino Uno and RTC?</p>
<p>If you google your question you'll find tons of samples!</p><p>Thanks for stopping by ...</p>
<p>Sorry, i could not locate the wiring diagram @github. I am more specifically wanting to know the LED sequencing as there are 5 sets to be sequenced in series.</p><p>can u pls share this detail as i am unable to proceed with your project due to this step not being clear? Any other readers who have figured out the wiring can kindly help?</p>
<p>Hi ravijag,</p><p>The LEDs are driven by the WS2811 LED driver ... you only need three wires connected to an SPI port to drive all the LED independently.</p>
<p>Some chinese ledstrips come with 5 wires; 2 white (both ground) 2 red (both 5v) and a green wire to drive the leds. You can clip off the extra red and white wires.</p>
<p>Are you trying to connect the ledstrip to the pcb?</p>
<p>I recently finished my first fibonacci lamp. I had some trouble producing my own pcb so i moved to a ready made arduino board and a ds 1307 breakout. Now I only have to make small pcb to accomodate the buttons.</p>
<p>That's awesome! Would love to see the final result! Thanks for sharing!</p>
<p>Hi</p><p>i want to build this for myself but am unable to understand the wiring sequence of the LED modules (DO to DI between modules). The picture or schematic is not clear on this critical connection. Can u please elaborate this step?</p>
Hello, <br>All the schematics are in the git repo on github. <br>P.
<p> Can we convert the double sided pcb to single sided one???</p>
Sure you can... The Fritzing file is in the git repo. You can also find the pub at https://store.basbrun.com if you want to go faster! :)
<p>is there any substitute for the type of led strips used?</p><p>can we use separate red, yellow and green leds?<br>if so plese tell me how?</p><p>i would like to do this project</p><p>the led strips are not available in my place and it is undeliverable area in inernet shopping sites.</p><p>please help me</p>
<p>Hi,</p><p>Thanks for your message ... You can use any WS2811 based LED strip. You should be able to find it on eBay or Alibaba.</p><p>Using distinct red,green and blue LEDs won't produce the same effect and you'll need multiple LED drivers to drive that many LEDs.</p><p>Where are you located?</p>
<p>An RGB LED is actually 3 seperate LEDs with either the anodes or cathodes tied together, take a red a green and a blue, twist either all the anodes or cathodes together and you have yourself a common anode or cathode (depending on which you tied) RGB LED, although, you will not get the same diffusion, it will work.</p><p>If you wish you can replace all the colours with any available LED colour, it would even be possible to make an IR clock that displays the led at 3 different brightnesses by tying different resistors to the anode or cathode that can only be seen through a camera with its IR filter removed for extra confusion!!!!</p>
<p>But how to programme it???</p>
<p>I certainly will. Right now i am sourcing the right of plexiglass..</p>
<p>OMG, I tried to drive the pixelstrip from the wrong end. </p><p>Problem solved!</p>
<p>Hi,</p><p>Glad you solved your problem! Would love to see the final result!</p><p>Philippe</p>
<p>I love the idea of this clock. Very creative i must say.</p><p>I am trying to build one myself. Shipping costs to the Netherlands are a bit steep and i don't want to miss out on the DIY fun</p><p>Already fabricated my first pcb. So proud of myself. Now i want try the breadbord version before i go into soldering, but i run into some trouble now.</p><p>I bought a strip of 50 lights and cut them up in strands of 9. The first 9 led work just fine but the other cut up pieces don't ligt up. De complete strand of 50 lights worked fine also. Maybe i want to build some more as a gift so i would very much like the strands to work to.</p><p>Do you have any idea of what is going wrong here?</p><p>Thx in advance!</p>
That's really cool. <br>Do you think is possible to merge your project with a INKA CALCULATOR ( YUPANA ) <br><br>http://www.quipus.it/english/Andean%20Calculators.pdf
<p>Hi ccarpio2,</p><p>This Inca calculator is a magnificent object! Sure it could be merge together ... if you do it let us know!</p>
Hey, Philippe...<br><br>Congratulations for this awesome project! Answering your question from two days ago, I'm from Rio de Janeiro, Brazil, and I received the link for your project in a Instructable's tweet earlier today. Funny that I only realized that your article was posted a year ago when you mentioned it in your comment. :-)
<p>Oh great! I got more than 30 000 views in a weekend, one year after I published the article! :) Instructables.com is THE place to be in the DIY community!</p>
<p>Awwwh. It's not for sale? I have to build it? I like the pretty colors.</p>
<p>It is actually ... <a href="http://store.basbrun.com">http://store.basbrun.com</a></p><p>Thanks!</p>
<p>I have enough trouble keeping track of all of the Mickey Mouse appendages on my wrist watch, I'm not ready to learn any new tricks. Looks like a nice little DIY though. Thanks for the look into the future.......;) Semper Fi</p>
Cool project! Congratualtions on your Kickstarter campaign. I've posted a linl / pic of your clock on Pinterest, hope it helps!!
<p>Thanks man!</p>
<p>beautiful! </p>
<p>Beautiful, geeky, love it!</p><p>Quick tip, though: Arduino (Atmega328P, whatever) has INPUT_PULLUP, so by just inverting your button logic you can save yourself those (admittedly cheap) pull-down resistors, bit of space, bit of wiring. Not sure if the same applies to your other pull-up resistors too?</p><p>Very cool clock though. I'm just wondering if you should go all the way up to 34 so you don't have to do the &quot;multiply by 5&quot; thing ;-)</p>
<p>Thanks NoseyNick,</p><p>I tried it with more squares but if I keep the same scale the clock would be enormous and to complicate things, you would have more calculations to do in less than one minute! :)</p><p>Thanks for the input!</p><p>Philippe</p>

About This Instructable




More by pchretien:The Fibonacci Clock RGB / RFID Lamp Halloween Tombstone Decoration 
Add instructable to: