Published © MIT

Simple digital clock using DIGISPARK ATTINY85

Simple... No... VERY SIMPLE clock in case of old "Elektronika" clock

BeginnerShowcase (no instructions)7,052
Simple digital clock using DIGISPARK ATTINY85

Things used in this project

Hardware components

DS3231 RTC module
×1
DIGISPARK ATTINY85
×1
MAX7219 LED matrix (32x8 dots)
×1
Old clock's case
×1
Wires
×1
CR2032 Cell Battery
×1
2.1-5.5 Power Socket
×1
Arduino UNO
Arduino UNO
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Circuit diagram

Code

clock

C/C++
#include <DS3231.h>
#include <Wire.h>
#include <LedControl.h>
#include "symbols.h"
#include "button.h"

const byte PANEL_COUNT = 4;

DS3231 rtc;
//DIN, CLK, CS
LedControl lc(1, 5, 4, PANEL_COUNT);  
BUTTON btn(3);

const byte HH_MAX = 24;
const byte MM_MAX = 60;

bool h12 = false;
bool PM;

byte hh, mm, prev;

enum {rsNormal, rsSetH, rsSetM} rtcState;

void showTime(void) {
  byte f = 0;
  byte t = PANEL_COUNT;

  switch (rtcState) {
    case rsSetH: 
      f = PANEL_COUNT >> 1;
      for (byte i=0; i<f; i++) lc.clearDisplay(i);
      break;
    case rsSetM: 
      t = PANEL_COUNT >> 1;  
      for (byte i=t; i<PANEL_COUNT; i++) lc.clearDisplay(i);
      break;
  }
  
  byte digit;
  byte shift;
  
  for (byte i=f; i<t; i++) {
    switch (i) {
      case 0: digit = mm%10; shift = 1; break;
      case 1: digit = mm/10; shift = 0; break;
      case 2: digit = hh%10; shift = 3; break;
      case 3: digit = hh/10; shift = 2; break;
    }
   
    for (byte j=0; j<ROW_COUNT; j++) { 
      lc.setRow(i, j, pgm_read_byte(&symbols[digit][j]) << shift);
    }
  }

  lc.setLed(1, 1, 0, true);
  lc.setLed(1, 2, 0, true);
  lc.setLed(1, 5, 0, true);
  lc.setLed(1, 6, 0, true);

  lc.setLed(2, 1, 7, true);
  lc.setLed(2, 2, 7, true);
  lc.setLed(2, 5, 7, true);
  lc.setLed(2, 6, 7, true);
}

void setup() {
  Wire.begin();
  
  for (byte i=0; i<PANEL_COUNT; i++) {
    lc.shutdown(i, false);
    lc.setIntensity(i, 8);
    lc.clearDisplay(i);
  }
}

void loop() {
  if (rtcState == rsNormal) {
    mm = rtc.getMinute();

    if (mm != prev) {
      hh = rtc.getHour(h12, PM);
      showTime();
      prev = mm;
    }
  }
  
  switch (btn.isChanged()) {
    case bsPressed:
      switch (rtcState) {
        case rsSetH: hh = ++hh % HH_MAX; break;
        case rsSetM: mm = ++mm % MM_MAX; break;  
      }
      showTime(); 
      break;

    case bsLongPressed:
      switch (rtcState) {
        case rsNormal: rtcState = rsSetH; break;
        case rsSetH: rtc.setHour(hh); rtcState = rsSetM; break;
        case rsSetM: rtc.setMinute(mm); rtcState = rsNormal; break;
      }
      
      showTime();
      break;  
  }
}

button.cpp

C/C++
#include "button.h"

BUTTON::BUTTON(byte pin) {
  _pin = pin;
  pinMode(_pin, INPUT_PULLUP);
  _stateS = HIGH;
  _stateL = HIGH;
  _prevTime = millis();
}

btnState BUTTON::isChanged(void) {
  btnState res = bsNone;
  unsigned long currTime = millis();

  if (!digitalRead(_pin)) {
    if (_stateS && ((currTime - _prevTime) > DEBOUNCE_DELAY)) {
       _prevTime = currTime;
       _stateS = LOW;
       _stateL = HIGH;
    }

    if (_stateL && ((currTime - _prevTime) > LONG_PRESS)) {
      _stateL = LOW;
      res = bsLongPressed;
    }
  }
  else {
    if (!_stateS) {
      if ((currTime - _prevTime) > DEBOUNCE_DELAY) {
        _prevTime = currTime;
        _stateS = HIGH;
        if (_stateL) res = bsPressed; 
      }
    }
  }  

  return res;  
}

button.h

C/C++
#ifndef BUTTON_H
#define BUTTON_H

#include <Arduino.h>

const int DEBOUNCE_DELAY = 50;
const int LONG_PRESS = 500;

enum btnState {bsNone, bsPressed, bsLongPressed};

class BUTTON {
  private:
    byte _pin;
    unsigned long _prevTime;
    boolean _stateS, _stateL;
    btnState _state;
  public:
    BUTTON(byte pin);
    btnState isChanged(void);
};

#endif BUTTON_H

symbols.h

C/C++
#ifndef SYMBOLS_H
#define SYMBOLS_H

const byte ROW_COUNT = 8;
const byte SYM_COUNT = 10;

const byte symbols[SYM_COUNT][ROW_COUNT] PROGMEM = { 
  {B01110,  //0
   B11011,
   B11011,
   B11011,
   B11011,
   B11011,
   B11011,
   B01110},
  
  {B00010,  //1
   B00110,
   B01110,
   B00110,
   B00110,
   B00110,
   B00110,
   B00110},

  {B01110,  //2
   B11011,
   B00011,
   B00110,
   B01100,
   B11000,
   B11000,
   B11111},

  {B01110,  //3
   B11011,
   B00011,
   B00110,
   B00011,
   B10011,
   B11011,
   B01110},

  {B00011,  //4
   B00111,
   B01111,
   B11011,
   B10011,
   B11111,
   B00011,
   B00011},

  {B11111,  //5
   B11000,
   B11000,
   B11110,
   B00011,
   B00011,
   B11011,
   B01110},

  {B01110,  //6
   B11011,
   B11000,
   B11110,
   B11011,
   B11011,
   B11011,
   B01110},

  {B11111,  //7
   B10011,
   B00011,
   B00110,
   B01100,
   B11000,
   B11000,
   B11000},

  {B01110,  //8
   B11011,
   B11011,
   B01110,
   B11011,
   B11011,
   B11011,
   B01110},

  {B01110,  //9
   B11011,
   B11011,
   B01111,
   B00011,
   B00011,
   B11011,
   B01110} 
};

#endif

Credits

Comments