Project showcase

Digital Clock with Auto Correction Display © CC BY-NC-ND

This clock can be rotated in any position keeping the digits readable even upside down or in a mirrored image!

  • 3,354 views
  • 0 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

This project is about a digital clock with automatic correction of 7-Seg LED display and it is upgraded from my Digital Clock with Mirrored Display Driven by Accelerometers.

This clock can be rotated in any position keeping the digits readable even upside down or in a mirror image!

It is controlled by an Arduino and driven by accelerometers to find out the correct position in 3D coordinates.

Additionaly there is a feature to show the indoor ambient temperature in Celsius or in Fahrenheit degrees.

Now it is updated to Arduino 101.

The assemble is very simple and I hope you have fun using it!

Video 1

Video 2

1) Material List


Multi Function Shield (MFD):

The MFD can simplify and speed up the prototype development.

Main features:

  • 4 digit 7-segment LED display module driven by two serial 74HC595's
  • 4 x surface mount LED's in a parallel configuration
  • 10K adjustable precision potentiometer
  • 3 x independent push buttons
  • Piezo buzzer
  • DS18B20 temperature sensor interface
  • LM35 temperature sensor interface
  • Infrared receiver interface
  • Serial interface header for convenient connection to serial modules such as Bluetooth, wireless interface, voice module, a voice recognition module, etc.

Arduino 101:

This version of the Arduino is no longer produced despite having interesting features such as temperature sensor, a 6-axis accelerometer and a gyroscope on board.

It is very useful for this project avoiding an external MPU.

2) Assembly

The assembly is very simple and does not need any schematics:

  • Insert the Multi Shield into the Arduino.
  • Fasten the MPU-6050 breakout on the Arduino board using a tiny screw.

There only 04 jumper wires to be connected:

  • Red wire: Vcc (+5V)
  • Black wire: Gnd
  • Green wire: SCL of MPU-6050 breakout to port #6 in the Multi Shield.
  • Yellow wire: SDA of MPU-6050 breakout to port #5 in the Multi Shield.

3) Setup

There are 3 buttons to setup the clock:

  • Left button: Press to adjust the hours. Quickly press to set up step by step. Continuous press to advance the hours quickly.
  • Center button: Set the minutes. Continuous press to advance the hours quickly.
  • Right button: a quick press to move for temperature mode.

Note: In Temperature Mode is possible to change the status to Fahrenheit or Celsius pressing the Left button.

4) Code

The main functions of the code are:

  • Reading of accelerometers inclination angles.
  • Calculation of the transfer function for the 7-seg LED display (see pictures).

With the angles is possible to detect the spacial position of the clock and decide what routine will be released:

  • Front View - Clock Stand Up
  • Front View - Clock Upside Down
  • Mirror View - Clock Stand Up
  • Mirror View - Clock Upside Down

Code

Digital_Clock_Automatic_Rotation_Multi-Shield_Arduino_101_V1_1.inoArduino
/*
  Project:    Digital Clock with Automatic Rotation of 7-Seg LED
  Author:     LAGSILVA
  Hardware:   Arduino 101 / Multi-Function Shield  
  Revision:   V1.1 (Arduino 101)
  Date:       26.Ago.2018
  License:    CC BY-NC-ND 4.0
              (Attribution-NonCommercial-NoDerivatives 4.0 International)
*/

#define SDA_PORT PORTD
#define SDA_PIN 5
#define SCL_PORT PORTD
#define SCL_PIN 6

#include <CurieTimerOne.h>
#include <CurieIMU.h>

#include <Time.h>                               // Time library
#include <TimeLib.h>

// Module connection pins (Digital Pins)
#define LATCH_PIN 4                             // Arduino 101 conection on Pin #4  = Latch of Display Module
#define CLK_PIN 7                               // Arduino 101 conection on Pin #7  = Clock of Display Module
#define DATA_PIN 8                              // Arduino 101 conection on Pin #8  = Data of Display Module

#define BTN_1_PIN A1
#define BTN_2_PIN A2
#define BTN_3_PIN A3

//    Front:       Upside Down:     Upside Down Mirror:     Front Mirror:
//      A               D                    D                   A
//     ----            ----                 ----                ----
//  F |    | B      C |    | E           E |    | C          B |    | F
//     -G -            -G -                 -G -                -G -
//  E |    | C      B |    | F           F |    | B          C |    | E
//     ----            ----                 ----                ----
//      D               A                    A                   D
//

//   Chars Code {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, , C, F}
byte N[] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0xC6, 0x9C, 0x8E};

int hora, minuto;
int unidadeHora, unidadeMinuto, dezenaHora, dezenaMinuto, delayRefresh;
byte mirror, tempStatus, lastStatus, tCF;
unsigned long ti;
boolean ajustaHora = true, ajustaMinuto = true, mostraTemperatura = true;

// Variaveis para armazenar valores dos sensores
float AcX, AcY, AcZ;
int Temp;


void setup() {

  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);

  pinMode(BTN_1_PIN, INPUT);
  pinMode(BTN_2_PIN, INPUT);
  // pinMode(BTN_3_PIN, INPUT);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  CurieTimerOne.start(200000, kbdRead);

  CurieIMU.begin();

  // Set the accelerometer range to 2G
  CurieIMU.setAccelerometerRange(2);

  mirror = 1;             // Front View (No Mirror as default)
  tempStatus = 0;
  lastStatus = 0;
  tCF = 0;

}


void loop() {

  delayRefresh = 50;

  Temp = (CurieIMU.readTemperature() / 512) + 13;          // Read the temperature in Celsius degrees (C)

  CurieIMU.readAccelerometerScaled(AcX, AcY, AcZ);            // Read the accelerometer axis

  if (AcX < 0 && AcZ > 0) {
    mirror = 1;                                               // Front View (No Mirror)
  }

  if (AcX < 0 && AcZ < 0) {
    mirror = 3;                                               // Upside Down Mirror View
  }

  if (AcX > 0 && AcZ < 0) {
    mirror = 2;                                               // Front Mirror View
  }

  if (AcX > 0 && AcZ > 0) {
    mirror = 4;                                               // Front View (Upside Down)
  }

  hora = hour();
  minuto = minute();
  unidadeHora = hora % 10;
  dezenaHora = hora / 10;
  unidadeMinuto = minuto % 10;
  dezenaMinuto = minuto / 10;

  if (tempStatus == 0) {                                                        // Display only the Time (HH:MM)

    ti = millis();                                                              // Initial time for blinking dot

    while ((millis() - ti) < delayRefresh) {                                    // Timer in miliseconds to refresh the display

      if (mirror < 3) {                                                         // No Mirror (1) or Front Mirror (2) mode
        displayChars(N[dezenaHora], mirror, 0);                                 // Display Digit 0
        displayChars(N[unidadeHora], mirror, 1);                                // Display Digit 1
        displayChars(N[dezenaMinuto], mirror, 2);                               // Display Digit 2
        displayChars(N[unidadeMinuto], mirror, 3);                              // Display Digit 3
        displayChars(0, 1, 3);                                                  // Clear Digit 3 (last digit)
      }

      if (mirror >= 3) {                                                        // Up Side Down Mirror (3) or Front Upside Down (4) mode
        displayChars(N[dezenaHora], mirror, 3);                                 // Display Digit 3
        displayChars(N[unidadeHora], mirror, 2);                                // Display Digit 2
        displayChars(N[dezenaMinuto], mirror, 1);                               // Display Digit 1
        displayChars(N[unidadeMinuto], mirror, 0);                              // Display Digit 0
        displayChars(0, 1, 0);                                                  // Clear Digit 0 (last digit)
      }

      displayChars(1, 1, 1);                                                    // Display Dot at Digit 1

    }

  }

  if (tempStatus == 1) {                                                        // Display only the Temperature (C or F)

    if (tCF == 1) {
      Temp = Temp * 9 / 5 + 32;
    }

    ti = millis();                                                              // Initial time for blinking dot

    while ((millis() - ti) < delayRefresh ) {                                   // Timer in miliseconds to refresh the display

      if (mirror < 3) {                                                         // No Mirror (1) or Front Mirror (2) mode
        displayChars(N[Temp / 10], mirror, 0);                                  // Display tenth of Temperature
        displayChars(N[Temp % 10], mirror, 1);                                  // Display unit of Temperature
        displayChars(N[10], mirror, 2);                                         // Display symbol of Degrees
        if (tCF == 0) {
          displayChars(N[11], mirror, 3);                                       // Display "C (symbol of Celsius Degrees)
        }
        else {
          displayChars(N[12], mirror, 3);                                       // Display "F" (symbol of Fahrenheit Degrees)
        }
        displayChars(0, 1, 3);                                                  // Clear Digit 3 (last digit)
      }

      if (mirror >= 3) {                                                        // Up Side Down Mirror (3) mode
        displayChars(N[Temp / 10], mirror, 3);                                  // Display tenth of Temperature
        displayChars(N[Temp % 10], mirror, 2);                                  // Display unit of Temperature
        displayChars(N[10], mirror, 1);                                         // Display symbol of Degrees
        if (tCF == 0) {
          displayChars(N[11], mirror, 0);                                       // Display "C (symbol of Celsius Degrees)
        }
        else {
          displayChars(N[12], mirror, 0);                                       // Display "F" (symbol of Fahrenheit Degrees)
        }
        displayChars(0, 1, 0);                                                  // Clear Digit 0 (last digit)
      }

    }

  }

}


void displayChars(byte num, byte statusM, byte disp) {                            // Chars Display Routine

  byte k, charsM = 0;

  if (statusM == 1) {                                                             // No Mirror
    charsM = num;
  }

  if (statusM == 2) {                                                             // Front Mirror
    for (k = 0; k <= 7; k++) {
      charsM = bitWrite(charsM, 7 - k, bitRead(num, k));
    }
    charsM = (charsM << 4 | (charsM << 2) >> 4 & 12 ) | ((charsM & 64) >> 5);
  }

  if (statusM == 3) {                                                             // Upside Down Mirror
    for (k = 0; k <= 7; k++) {
      charsM = bitWrite(charsM, 7 - k, bitRead(num, k));
    }
    charsM = (charsM << 7 | (charsM << 1) & 124 ) | ((charsM & 64) >> 5);
  }

  if (statusM == 4) {                                                             // Front Upside Down
    charsM = ((num >> 2) << 5) | ((num >> 5 ) << 2) | (num & 2);
  }

  digitalWrite(LATCH_PIN, LOW);
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, ~charsM);                                 // Display number
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, 128 >> disp);                             // Set Digit (0-1-2-3)
  digitalWrite(LATCH_PIN, HIGH);

}


void kbdRead() {                                                                  // Push Buttons Reading

  ajustaHora = digitalRead(BTN_1_PIN);
  ajustaMinuto = digitalRead(BTN_2_PIN);
  mostraTemperatura = digitalRead(BTN_3_PIN);

  if (!ajustaHora && tempStatus == 0) {                                           // Set Hour
    adjustTime(3600);
    delayRefresh = 150;
  }

  if (!ajustaMinuto && tempStatus == 0) {                                         // Set Minute
    adjustTime(60);
    delayRefresh = 150;
  }

  if (!mostraTemperatura) {                                                       // Move to Temperature Mode
    tempStatus = (tempStatus + 1) % 2;
    delay(200);
  }

  if (!ajustaHora && tempStatus == 1) {                                           // Set to C or F
    tCF = (tCF + 1) % 2;
    delay(200);
  }

}

Comments

Similar projects you might like

Digital & Binary Clock In 8 Digits x 7 Segments LED Display

Project showcase by LAGSILVA

  • 6,348 views
  • 4 comments
  • 16 respects

Digital Clock with Mirrored Display Driven by Accelerometers

Project showcase by LAGSILVA

  • 18,967 views
  • 2 comments
  • 47 respects

4-Stroke Digital Clock With Arduino

Project showcase by LAGSILVA

  • 18,127 views
  • 15 comments
  • 48 respects

Ternary Digital Clock with Arduino

Project showcase by LAGSILVA

  • 8,076 views
  • 6 comments
  • 19 respects

Digital Clock with Arduino, RTC and Shift Register 74HC595

Project showcase by LAGSILVA

  • 48,915 views
  • 36 comments
  • 98 respects

Digital And Binary Clock With Two LED Matrix And RTC

Project showcase by LAGSILVA

  • 19,590 views
  • 47 comments
  • 58 respects
Add projectSign up / Login