Introduction: Berlin Clock, Arduino Nano, DS1307 Real Time Clock. 74HC595N 8 Bit Shift Register.

Picture of Berlin Clock, Arduino Nano, DS1307 Real Time Clock. 74HC595N 8 Bit Shift Register.

For some time now I have wanted to build a Berlin clock. I don’t really know why? I just like the “different” approach to telling the time.

So how does it work??

Starting at the bottom there are 4 yellow lights each light represents 1 minute, so if there are none on this would be zero, one illuminated would be 1 minute and so on.

Next row is the 5 minute row, each lit light represents 5 minutes and the red lights indicate ¼’s of an hour. So to carry on from the bottom line once all 4 lights are lit the next number would be to increment the 2nd row and the bottom would be Zero.

The third row up is hours and like the minutes there are 4 lights (red) each one representing an hour. Once 4 are lit the next hour would be displayed on the top row as one * five hour.

The top row is 5 hours per light. 5, 10, 15 and 20. This is a 24 hour clock.

The last light is the round light at the top which blinks at a ½ Hz frequency i.e. 1 second on and 1 second off.

Step 1: The Mechanical Build.

Picture of The Mechanical Build.

I thought for a while how I was going to build this clock, then decided that the easiest way was to do was design the clock pieces using QCAD on my raspberry pi, then print out the sections 1:1 then stick the plans onto the
wood and cut out with my fret saw.

I did however want the clock to be dimensionally correct. So I found a few photos of the clock and measure the relevant bits and decided on a main area of 200mm by 200mm the top light will then go on top. The main clock is made out of 3 mm plywood, and the rounded corners are white oak. The glass lens are just frosted Perspex which I had left over from my plasma display.

So I am not going into great detail about the clock build, but you should find all the information you need in the photos and PDF files attached of the bits.

Sequence is as follows

  1. Print out plans and stick to the ply wood, double up the wood as required.
  2. Cut out the bits using a fret saw.
  3. Clean up the edges using sand paper and trial fit parts.
  4. Glue the LED separator parts together and stick to the front and clamp the sides all at once. I use grease proof paper (nick it from the kitchen draw) and this stops the wood sticking to the table or clamps.
  5. Then add the end pieces of ply and shaped corner bits.
  6. Varnish the front sections.
  7. Glue the frosted Acrylic Perspex windows.
  8. Fix all LED’s and connect wires.
  9. Glue in the led sheet.
  10. Glue all the sections together.
  11. Add all connecting wires.
  12. Add back section of ply.
  13. Add the back and buttons.

To make the round top section I formed 3 strips of 1/16" ply wood around a spray can then added a 3mm front and back.

I will point out that I tried a couple of different ways to construct the sections and gluing the back on before the ends didn’t work, you are better off gluing the ends on first and holding the back on temporary (with a weight) so it gets the ends inline for gluing.

For the spacers in-between I laminated 3 pieces of 1/8” ply wood, then cut to size and used a round nose cutter in my router to make the internal radius.

For the back section I have used 1/16” ply which I have carefully cut buttons into. The 1/16” ply was perfect for this and the switches are mounted to the back of the panel to get the correct spacing.

Step 2: The Electronics Build

Picture of The Electronics Build

For the circuits I am using “vero board” One bit is needed for the 3 shift registers, and another bit is needed for the 5 buttons. When I was thinking about the layout for the shift board I decided it would be best to bring Q0 output to the left side to join the other 7 outputs and also get rid of the 9th pin (Q7” serial output) to allow the ground to take its place, I did this by removing the pin from the chip holder, this then leaves a nice clean layout with all outputs on one side (with the ground) and the inputs on the other side. (See the pictures for more info)

I decided to fit the required LED resistors in the ground leg of the singles and in-between the two LED’s where they are mounted in two. This gives 4 different resistor values to give the required brightness.

Red single = 560 Ohms (5V – 1.88V / 560 = 5.5 mA)

Red double = 220 Ohms (5V – 1.88V – 1.88V / 220 = 5.6 mA)

Yellow single = 470 Ohms (5V – 2V / 470 = 6.4 mA)

Yellow double = 150 Ohms (5V – 2V – 2V / 150 = 6.6 mA)

Basically I chose a value of resistance which gave me the best brightness (with the two LED’s) then used a Multimeter to check the voltage and used the value to calculate the single value or resistance required.

Step 3: The Electronics and Program Explained

Picture of The Electronics and Program Explained

As explained I am using an Arduino Nano (or clone) to drive 3 * 595 shift registers and a RTC connected to the I2C to keep time. At this point I will try and explain the more challenging parts of the code, as it’s not an obvious one to work out, (although easy once you work it out).

The time is supplied by the Real Time Clock as seconds 0-59, minutes 0-59, and hours 0-23. Because the clock is based on 5’s you need to divide the minutes (and hours) by 5 first this will give you the “5 minutes” row (second
one up) if you then work out the modulus of the calculation then that gives you the remainder which is the 0-4 minutes (bottom) line.

i.e. minutes = 48

48/5 = 9 (store it as minFives)

48%5 = 3 (store it as minUnits)

9 lights on the second row for 45 minutes then 3 lights on the bottom row for 3 minutes add the two together gives you 48.

staying with the minutes the next problem is the 595 shift register only holds 8 bits and I need to use one completely and then 3 “bits” of another register.

So to do this look at the minFives (0-11) and if the number is greater than 7 then split the value into two values.

i.e. if (minFives > 7)

if (minFives > 7)

{
regOne = minFives;
regTwo = minFives – 8;
}
else
{
regOne = minFives;
regTwo = 0;
}

The next issue is to display all the lights and not just the actual number, so in the above example (48) you have 3 lights on the bottom row and 9 lights on the second row. So to correct this for the bottom row you need to turn on light 1and light 2 and light 3, meaning a number of 7 (total 1+2+4) needs to be sent to the serial register. I am sure there is more than one way to do this but I chose to run a loop for the given number and for each loop double the index number and add to the file. (see below for pow() function as an alternative)

i.e.

k = 1; //number to be added each time but will double for each loop.
j = 0; // number of times the loop will run. 
while (j < (regOne))// regOne is a number 0-8 
{ 
  minFivesBar1 = minFivesBar1 + k; 
  k = k * 2; 
  j = j + 1; 
}

hopefully you can work this out, but basically you will get the correct required number of LED’s lit for a given input number.

i.e. 1=1, 2=3, 3=7, 4=15, 5=31

I realised after I wrote this that I could use the pow() function so I will have a try and see if its more efficient. example, input 6 (pow(2,6))-1 = 63

(I tried it out and there really isn't much difference in the time, both are really quick. I guess the pow() looks neater but I stuck with the above function)

Step 4: Shift Registers

Picture of Shift Registers

Right at this stage we have three values:-

minFivesBar1 (8 bits used for LSB of the second row)

minFivesBar2 (3 bits used for the MSB of the second row)

minBar(4 bits used for the first row)

Now I only want to use 3 shift registers so I need to combine minBar and minFivesBar into the same register, which thankfully is easy to do.

File rotate the minBar 3 times and add to the register.

i.e.

minBar = minBar << 3;
minFivesBar2 = minFivesBar2 + minBar; 

That leaves one last position in the 8 bit register and that will be used for the second pulse, and implemented by determining where the seconds is odd or even and then adding 128 to the file as required. The code looks something like…

if (seconds%2) 
{
  minFivesBar2 = minFivesBar2 + 128; 
}
else 
{
  minFivesBar2 = minFivesBar2 – 128;
}

as I was writing this it didn’t seem correct so in the end I check not only if the number was even but also if it was (AND) greater than 128.

The hours will again have to, firstly be divided by 5 then work out the modulus this will give you the two numbers, then as before work out the “running” total and then store the two 4bit values in one register by file rotating one value 4 times so it occupies the 4 MSB and adding it to the other number which is in the 4 LSB.

The command for driving the 595 serial register is very easy, and requires 4 arguments.

which pin to use for data
which pin to use for clock
whether to send MSB or LSB first
Data to be sent.


Once the command has run the data then needs to be latched by setting the relevant latch pin low then high.

Adjustment

I wasn’t really sure how I was going to adjust this clock when I started to build it, but then I decided that because I had enough input spare I would have 4 buttons and one switch and generate a sub routine to set the RTC depending on which button is pressed. I have also made a GPS clock which can be used to compare the RTC
to GPS and correct it as required (but that’s for another instructable!)

Step 5: The Full Program

Picture of The Full Program
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
int i = 0;
int k = 0;
int x = 0;
int minFivesMSB = 0;
int minFivesLSB = 0;
int temp = 0;
int minFives = 0;
int hours = 0;
int hoursFives = 0;
int minUnits = 0;
int oldHoursFives = hoursFives;
const int changeTime = 14;
const int setHourPos = 15;
const int setMinPos = 16;
const int setHourNeg = 17;
const int setMinNeg = 11;
tmElements_t tm;
void setup()
{
  pinMode(2, OUTPUT);//latchOne
  pinMode(3, OUTPUT);//latchTwo
  pinMode(4, OUTPUT);//latchThree
  pinMode(5, OUTPUT);//clockPinOne
  pinMode(6, OUTPUT);//clockPinTwo
  pinMode(7, OUTPUT);//clockPinThree
  pinMode(8, OUTPUT);//dataPinOne
  pinMode(9, OUTPUT);//dataPinTwo
  pinMode(10, OUTPUT);//dataPinThree
  pinMode(changeTime, INPUT);
  pinMode(setHourPos, INPUT);
  pinMode(setMinPos, INPUT);
  pinMode(setHourNeg, INPUT);    
  pinMode(setMinNeg, INPUT);
  Serial.begin(9600);
}
void runningTotal(int number)
{
  int s = 1;
  int j = 0;
  temp = 0;
  while (j < number)
  {
    temp = temp + s;
    s = s * 2;
    j = j + 1;
  }
}
void obtainNo()
{
  minFives = i/5;
  minUnits = i%5;
  hoursFives = k/5;
  hours = k%5;
  if (minFives > 7)//split minutes as it rolls over two shift registers
  {
    minFivesLSB = 8;
    minFivesMSB = minFives - 8;
  }
  else
  {
    minFivesLSB = minFives;
    minFivesMSB = 0;
  }
}
void obtainRunning()
{
  runningTotal(minUnits);
  minUnits = temp;
  runningTotal(minFivesLSB);
  minFivesLSB = temp;
  runningTotal(minFivesMSB);
  minFivesMSB = temp;
  runningTotal(hours);
  hours = temp;
  runningTotal(hoursFives);
  hoursFives = temp;
}
void compileRegs()
{
  minUnits = minUnits<<3;
  minUnits = minUnits + minFivesMSB;
  hoursFives = hoursFives <<4;
  hoursFives = hoursFives + hours;
  if ((tm.Second)  % 2 && minUnits < 128)
  {
    minUnits = minUnits + 128;
  }
  else 
  {
    if (minUnits > 128)
    {
      minUnits = minUnits - 128; 
    }
  }
}
void sendToRegs()
{
  shiftOut(8, 5, MSBFIRST, minFivesLSB);
  digitalWrite(2, LOW);
  digitalWrite(2, HIGH);
  shiftOut(9, 6, MSBFIRST, minUnits);
  digitalWrite(3, LOW); 
  digitalWrite(3, HIGH);
  shiftOut(10, 7, MSBFIRST, hoursFives);
  digitalWrite(4, LOW);
  digitalWrite(4, HIGH);
}
void checkAdj()
{
  if (digitalRead(changeTime) == HIGH)
  {
    if (digitalRead(setHourPos) == HIGH)
    {
      unsigned long v = RTC.get();
      v = v + 3600;
      RTC.set(v);
    }
    if (digitalRead(setMinPos) == HIGH)
    {
      unsigned long v = RTC.get();
      v = v + 60;
      RTC.set(v);
    }
    if (digitalRead(setHourNeg) == HIGH)
    {
      unsigned long v = RTC.get();
      v = v - 3600;
      RTC.set(v);
    }
    if (digitalRead(setMinNeg) == HIGH)
    {
      unsigned long v = RTC.get();
      v = v - 60;
      RTC.set(v);
    }
    i = (tm.Minute);
    k = (tm.Hour);
    obtainNo();
    obtainRunning();
    compileRegs();
    sendToRegs();
    delay(300);
  }  
}
void loop()
{
  if (RTC.read(tm))
  {
    checkAdj();
    i = (tm.Minute);
    k = (tm.Hour);
    obtainNo();
    obtainRunning();
    compileRegs();
    sendToRegs();
  }
}

Comments

RuudK5 made it! (author)2017-05-14

Hi mr Fid

I also made this clock. I'll try to include an image.

mr_fid (author)RuudK52017-05-15

I really like it! when i was making mine i wanted it made from Stainless steel but it was going to be to much work!

RuudK5 (author)mr_fid2017-05-15

Hi mr Fid

It's not stainless steel. It is painted silver with a bunch of materials like MDF, PVC, wood, plywood etc.

ptjj999 (author)2016-12-17

Hello Mr Fid, Love this project but have a question.

In your connection drawings the switch connections show a pin number and a number in brackets. I assume the bracket is the arduino designation e.g. A1 is Analog 1 etc, but I dont follow the pin number reference.

e.g. Set hours + = pin 15 (A1) but I see A1 as Nano pin 20 (or 328 pin 24)

Can you clarify the pinouts. I suspect I am reading things wrong.

Regards Terry

mr_fid (author)ptjj9992016-12-17

Good question, because i am using an Analogue pin as a digital pin you add 14 to the A1 pin so what is A1 becomes Digital pin 15. Drawing wasn't very clear but hopefully that makes sense? Or put another way Set hours is connected to A1, however it is called 15 in the program because it is used as a digital input.

ptjj999 (author)mr_fid2016-12-17

Tnx for the prompt answer Sir. So if I understand, pin15 is only a label for the sketch, The physical pin is Analog 01 (nano 20). Pin 11 is not labelled in the drawing so I assume it is the actual Digital 11 on the nano.

Sri for the questions, I am still quite new to Arduino :)

Terry

mr_fid (author)ptjj9992016-12-18

Thats correct i used 3 analogue pins and one digital.

ptjj999 (author)mr_fid2016-12-18

Again Thanks for your info. I think I have it sorted now. I am planning a build around a homemade controller. I have attached my layout :)

Hopefully the next pic will be a finished unit :)

BEHROOZK2 made it! (author)2016-09-09

i made it and it worked ! but because this was intentionally a messy prototype(in order to make it quick with less components) i didnt follow instruction entirely and i didnt add keys and even rows are ugly and color of leds arent right i even didnt use proper resistance , but it work great with that beautiful blinking on top i will make a pcb and i will design case for laser cutter then again i will put it here

thanx m_fid

mr_fid (author)BEHROOZK22016-09-09

Looks good, i am glad it worked for you.

BEHROOZK2 (author)2016-07-30

you are amazing!

mr_fid (author)BEHROOZK22016-09-05

Thanks, and i have replied you your personnal message as below.

I have added a drawing to the final page of the instructables which shows all the circuits. you need to follow the program to work out what wire goes to what pin.

I also amended the full program which had the typo at the start (thanks for pointing that out!) i then copied the whole program from the instructables page and pasted the text into the arduino sketch, and i can confirm it works perfectly. I even changed a few of the buttons around just to make sure.

On a project like this i firstly like to make the circuit on bread board, then once i am happy with the circuit i make it, but in the case of buttons i place the wires where they look neat (or reach if you cut them short) and then change the pin numbers in the program to suit.

I hope that has helped you.

Eric Brouwer (author)2016-06-20

Very cool

MattsInstructables (author)2016-02-12

Very nice :)

Thanks!

uwezi (author)2016-01-09

I actually had forgotten about this clock. As a kid I was fascinated by it, always wanted to have one of these, just that they were too expensive. Now, I could easily build one - thank you!

ChiefInstructor (author)2015-12-03

I saw the original years ago. My dad was with me at the time and bought a miniature replica as a gift, which I still have. It still works.

ThomasK19 (author)2015-11-23

It's probably more than 20 years ago I last saw it on Kudamm. Does it still work?

mr_fid (author)ThomasK192015-11-24

Simple answer I don't know! I had a look on the internet and cant find any very recent information on it. It was decommissioned in 1995, then found a new home in front of the Europa Center. It was originally decommissioned because of the running costs! (5000 Euros a year) Hope fully mine wont cost that much to run!!!

ThomasK19 (author)mr_fid2015-11-24

Now I found it: https://en.wikipedia.org/wiki/Mengenlehreuhr It's at the other side of the Europa Center right in front of the building.

ThomasK19 (author)mr_fid2015-11-24

Haha, hopefully :-) Actually I live only 30 km away but too far anyway. I took a ride with Google street view. No trace of it.

Place your model on a piece of painted concrete and pretend it's from the Berlin wall xD

wooduino (author)2015-11-24

Great design... Any chance of a video?

mr_fid (author)wooduino2015-11-24

Thanks for your comments and I have just uploaded a video, I will add it to the above.

mr_fid (author)mr_fid2015-11-24

The video is in the first set of pictures so you will have to expand them to see it.

DIY Hacks and How Tos (author)2015-11-22

Awesome clock

About This Instructable

4,715views

72favorites

License:

Bio: I love making things. I have for as long as I can remember liked to make stuff. Now days I have two kids (Thomas and ... More »
More by mr_fid:Radio Controlled Electric Hovercraft  Release Hook for Quadcopter (The Flying Beaver Called Pig!)Simple Quadcopter, Basic Tools Only.
Add instructable to: