YAD Yet another Display

Deid Reimer September 2021

I needed a clock for our new travel trailer - so, contrary to Mark's advice of going to Walmart and buying one ...



where's the fun in that?  I built the following



                 A 3D printed case is in a design state

It has 3 components:

DS3231 Module Battery Issues

The issues:

The solution:



The picture on the left is modified.  It has the resistor removed and the bright power LED covered. Both circled in orange.   The picture on the right is the original with no modifications.

The thick black wires in the left picture are holding the RTC on the cardboard and are not part of the circuit

A new CR2023 button cell should run the RTC module for about 8 years without power applied.

Led and buttons usage

Leds numbered from the left

  1. heartbeat monitor once per second
  2. hours selected for change
  3. minutes selected for change
  4. flashes when seconds zeroed

Buttons numbered from the left

  1. Control display:
    1.  1st push turn off heartbeat
    2.  2nd push turn off display
    3.  3rd push all on ...
  2. Select time set mode
  3. Increase selected time
  4. Decrease selected time
  5. Zero seconds.  Use this to sync seconds with a reliable time source
  6. Choose temperature or seconds display

Schematic (breadboard)

Code:


/*  A combination of:
    TM1638 Hello World Example and
    DS3231 set echo example
*/

#include <DS3231.h>
#include <Wire.h>

#include <TM1638plus.h>

// Instantiate the real time clock I2C.
DS3231 rtclock;

// TM1638 Constructor object (GPIO STB , GPIO CLOCK , GPIO DIO, use
// high freq MCU)
// Instantiate the display
TM1638plus tm(D7, D6, D5);

// Variables
int8_t hour;     // time hours  - signed so that it wraps properly at 0
int8_t minute;   // time minutes - same signed
int8_t seconds;  // time seconds
bool h12Flag;    // read from rtc
bool pmFlag;     // read from rtc
bool heart = 1;  // heartbeat display
char out[12];    // buffer for the 8 segment display
byte buttons;    // byte to hold input button reading

unsigned long previousMillis = 0;  //Used for debouncing the buttons
const long  interval  = 225;  // Delay for debounce

// Button definitions

int dsp = 0;  // Clock display on off
int sel = 1;  // Select hour min to set
int up = 2;   // Increase value
int down = 3; // Decrease value
int zero = 4; // Zero seconds
int secs = 5; // Display seconds/temperature

// LEDs
int beat = 0;
int sethour = 1;
int setmin = 2;
int blinkzero = 3;

int selval = 0;  // 0: not in set mode, 1: set hour, 2: set minute
int dspval = 0;  // 0: all on, 1: blink off, 2: all off
int secsval = 0;  // 0: Temperature, 1: seconds

/* Functions */
// Read and debounce the buttons from the TM1638
byte buttonsRead(void) {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    buttons = tm.readButtons();
  }
  return buttons;
}

void setup() {
  // Start the serial port
  Serial.begin(9600);

  // Start the I2C interface
  // Wire.begin(int int sda, int scl)  ESP8266 pin numbers.  (0, 2) on the
  // D1 mini.
  // Else defaults to (4, 5) D2, D1
  Wire.begin();

  // Start the display
  tm.displayBegin();
  tm.brightness(0);
}

void loop() {
  // Get the hour and minute
  hour = rtclock.getHour(h12Flag, pmFlag);
  minute = rtclock.getMinute();

  // Get buttons
  buttons = buttonsRead();

  /******************************
     Display Button
  */
  // Is the display button pressed?  Increment and check display value
  if (bitRead(buttons, dsp)) {
    dspval++;
    if (dspval > 2) {
      dspval = 0;
    }
  }
  // Is display all on
  if (dspval == 0) {
    // Yes blink heartbeat led
    heart = !heart;
    tm.setLED(beat, heart);
    // if no heartbeat turn off led
  } else if (dspval == 1) {
    tm.setLED(beat, 0);
  }
  // Display off is handled in display section below

  /******************************
      Handle the time set.  It uses 3 buttons:
      1 - the select button to select hour or minute to set and turn on the
          appropriate led
      2 - increment the selected time
      3 - decrement the selected time
  */
  // Check select button and increment select value if on
  if (bitRead(buttons, sel)) {
    selval++;

    // Clear both select leds
    tm.setLED(sethour, 0);
    tm.setLED(setmin, 0);

    // All done leave both leds off
    if (selval > 2) {
      selval = 0;
    }

    // If not done set appropriate led
    if (selval != 0) {
      tm.setLED(selval, 1);
    }
  }

  // Increment/decrement the times as appropriate
  if (selval > 0) {

    // Handle up button
    if (bitRead(buttons, up)) {

      // if hour selected
      if (selval == sethour) {
        hour++;
        if (hour >= 24) {
          hour = 0;
        }
        rtclock.setHour(hour);

        // if minute selected
      } else if (selval == setmin) {
        minute++;
        if (minute >= 60) {
          minute = 0;
        }
        rtclock.setMinute(minute);
      }

      // Handle down button
    } else if (bitRead(buttons, down)) {

      // if hour selected
      if (selval == sethour) {
        hour--;
        if (hour < 0) {
          hour = 23;
        }
        rtclock.setHour(hour);

        // if minute selected
      } else if (selval == setmin) {
        minute--;
        if (minute < 0) {
          minute = 59;
        }
        rtclock.setMinute(minute);
      }
    }
  }
  /*******************************************
    Handle the Zero seconds button
  */
  if (bitRead(buttons, zero)) {
    rtclock.setSecond(0);
    tm.setLED(blinkzero, 1);
    delay(500);
    tm.setLED(blinkzero, 0);
  }
  /*******************************************
    Handle the seconds/temperature button
  */
  if (bitRead(buttons, secs)) {
    secsval++;
    if (secsval > 1) {
      secsval = 0;
    }
  }

  /********************************
     Display the time and temperature
  */
  // Get temperature
  float temp = rtclock.getTemperature();

  // If the display is turned off fill with spaces.
  if (dspval == 2) {
    for (int i = 0; i < 12; i++) {
      out[i] = ' ';
    }
    out[11] = 0;
  } else {
    // Format the output.  The Period does not count
    // as a char. in the display but it does count in the char array
    hour = rtclock.getHour(h12Flag, pmFlag);
    minute = rtclock.getMinute();
    int theTime = hour * 100 + minute;
    sprintf(&out[0], "%04d", theTime);
    // 0-3 it the time
    // 4 is decimal.  It will be stripped by the displayText
    // routine and the 8th segment turned on
    out[4] = '.';                      
    if (secsval == 0) {
      sprintf(&out[5], "%05.1f", temp);
      //If not minus replace the leading 0 with a space.
      if (temp >= 0) {
        out[5] = ' ';
      }
    } else {
      seconds = rtclock.getSecond();
      sprintf(&out[5], "%02d%2s", seconds,"  ");
    }
  }

  tm.displayText(out);

  delay(1000);
}

References:

Parts