Deid Reimer September 2021
DS3231.h - Talk to the real time clock
Wire.h - Handle the I2C bus
TM1638plus.h Talk to and handle the proprietary bus
/* 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);
}