Clock

This project is to build simple clock.

Phase 1 – Displays

Hardware

I will be using:

  • 4 x 7 segment displays
  • 4 x 2n3904 NPN transistors
  • 1 x CD4511BE – BCD to seven segment decoder
  • ATmega328p
  • 11 x 330 ohm resistors
My design is based off this schematic from Practical Electronics for Inventors

In this case I decided to multiplex the displays. This means I can use one decoder for all the segments which saves on cost and helps simplify the code. If we wanted the refresh rate on the segments to be very fast I would not multiplex them, however this will be perfectly fine for this use case.


The example schematic uses a 74HC5411 however I had some CD4511BE chips on hand. These chips function the same and in this case is a easy swap to make. While I could have driven the display segments directly from the micro controller the decoder makes this significantly simpler.

I have used the ATmega328p as a standalone chip in previous projects and in order to get familiar with that workflow I decided to use this chip in this project. I have also not made a decision about how we are going to get the time, so having a controller with lots of flexibility is useful.

Code

This currently is programmed directly in C. Depending on how we get the time I may move to using the Arduino framework, however I didnt feel it was necessary to include it in this bit of code.

#include <avr/io.h>
#include <util/delay.h>


void display(uint8_t number, int segment);


int main (void){

//Setup
  DDRC = 0b00001111; //Setup BCD Outputs
  DDRB = 0b00001111; //Setup Multiplex outputs
  
//Loop 
  while(1){

    display(1, 0);
    display(7, 1);
  }

  return(0);
}


void display(uint8_t number, int segment){
  PORTC = number;
  PORTB = (1 << segment);
  _delay_ms(1);
}

This code directly addresses the registers for the banks of pins we are using. The DDRx registers are used to set the pin mode, the equivalent of pinMode(x , OUTPUT); in the Arduino framework. The PORTx register is the current state of the pins, the equivalent of digitalWrite(x, HIGH);

I chose pins for the BCD outputs to the decoder that started at PC0. Doing this lets me assign a decimal number to the PORTC register which will set the outputs to the binary of that number. Which is exactly what we need for the input of the decoder to show that number on the display.

For the multiplexing I once again aligned the pins for the transistors to the start of a register, in this case PORTB. This lets me set the register using a bit shift for what segment we want to control. So overwrite the register with a 1 shifted into whatever position we want.

This code will overwrite every pin on the PORTC and PORTB registers. This really should be masked out so that they only overwrite the pins we actually are using for this purpose. Also input limits would be advisable so that we don’t write above were we want to in the registers. This is fine for testing but will be needed for future versions.

Next Steps

Next I am going to solder up a test board with the displays, transistors and decoder. This will simplify wiring on the breadboard and get all the displays functional as right now I am only using two to reduce the number of wires. While I do that I will also be looking at the best way to get the time for this clock.