Sorry, Here is the sketch:
/*
MIT License
Copyright (c) 2018 Leon van den Beukel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Source:
https://github.com/leonvandenbeukel/3D-7-Segment-Digital-Clock
External libraries you need:
Adafruit Sensor Library: https://github.com/adafruit/Adafruit_Sensor
Adafruit RTCLib: https://github.com/adafruit/RTClib
FastLED: https://github.com/FastLED/FastLED
Timer Library: https://github.com/JChristensen/Timer
*/
#include <DHT.h>
#include <DHT_U.h>
#include <FastLED.h>
#include <Wire.h>
#include "RTClib.h"
#include <SoftwareSerial.h>
#include "Timer.h"
#define DHTPIN 12
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
#define NUM_LED_PRO_SEG 3
#define NUM_LEDS (NUM_LED_PRO_SEG * 7 * 4 + 2)
#define DATA_PIN 6
CRGB LEDs[NUM_LEDS];
SoftwareSerial BTserial(8, 9);
RTC_DS3231 rtc;
Timer t1;
Timer t2;
Timer t3;
String btBuffer;
CRGB colorCRGB = CRGB::Red; // Change this if you want another default color, for example CRGB::Blue
CHSV colorCHSV = CHSV(95, 255, 255); // Green
//CRGB colorOFF = CRGB(20, 20, 20); // Color of the segments that are 'disabled'. You can also set it to CRGB::Black
CRGB colorOFF = CRGB::Black; // Color of the segments that are 'disabled'. You can also set it to CRGB::Black
volatile byte colorMODE = 1; // 0=CRGB, 1=CHSV, 2=Constant Color Changing pattern
volatile byte mode = 0; // 0=Clock, 1=Temperature, 2=Humidity, 3=Scoreboard, 4=Time counter
volatile byte scoreLeft = 0;
volatile byte scoreRight = 0;
volatile long timerValue = 0;
volatile int timerRunning = 0;
#define blinkDots 0 // Set this to 1 if you want the dots to blink in clock mode, set it to value 0 to disable
#define hourFormat 12 // Set this to 12 or to 24 hour format
#define temperatureMode 'C' // Set this to 'C' for Celcius or 'F' for Fahrenheit
#define Seg4 (21 * NUM_LED_PRO_SEG + 2)
#define Seg3 (14 * NUM_LED_PRO_SEG + 2)
#define Seg2 (7 * NUM_LED_PRO_SEG)
void setup() {
// Initialize LED strip
FastLED.delay(3000);
// Check if you're LED strip is a RGB or GRB version (third parameter)
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(LEDs, NUM_LEDS);
Serial.begin(9600);
while (!Serial) {
/* Wait until serial is ready */
}
BTserial.begin(9600);
Serial.println("BTserial started at 9600");
dht.begin();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1)
;
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
t1.every(1000 * 29, refreshDisplay);
t2.every(1000, refreshTimer);
t3.every(50, updateHue);
refreshDisplay();
}
void loop() {
t1.update();
t2.update();
t3.update();
if (BTserial.available() > 0) {
char received = BTserial.read();
btBuffer += received;
if (received == '|') {
processCommand();
btBuffer = "";
}
}
}
void updateHue() {
if (colorMODE != 2)
return;
colorCHSV.sat = 255;
colorCHSV.val = 255;
if (colorCHSV.hue >= 255) {
colorCHSV.hue = 0;
} else {
colorCHSV.hue++;
}
refreshDisplay();
}
void refreshDisplay() {
switch (mode) {
case 0:
displayClock();
break;
case 1:
displayTemperature();
break;
case 2:
displayHumidity();
break;
case 3:
displayScoreboard();
break;
case 4:
// Time counter has it's own timer
break;
default:
break;
}
}
void refreshTimer() {
if (mode == 0 && blinkDots == 1) {
displayDots(3);
} else if (mode == 4 && timerRunning == 1 && timerValue < 6000) {
timerValue++;
byte m1 = (timerValue / 60) / 10;
byte m2 = (timerValue / 60) % 10;
byte s1 = (timerValue % 60) / 10;
byte s2 = (timerValue % 60) % 10;
displaySegments(0, s2);
displaySegments(Seg2, s1);
displaySegments(Seg3, m2);
displaySegments(Seg4, m1);
displayDots(0);
FastLED.show();
}
}
void processCommand() {
if (btBuffer.startsWith("RGBD")) {
int R = getValue(btBuffer, ',', 1).toInt();
int G = getValue(btBuffer, ',', 2).toInt();
int B = getValue(btBuffer, ',', 3).toInt();
int D = getValue(btBuffer, ',', 4).toInt();
colorCRGB.red = R;
colorCRGB.green = G;
colorCRGB.blue = B;
colorMODE = 0;
if (D > 0) FastLED.setBrightness(D);
} else if (btBuffer.startsWith("HSVD")) {
int H = getValue(btBuffer, ',', 1).toInt();
int S = getValue(btBuffer, ',', 2).toInt();
int V = getValue(btBuffer, ',', 3).toInt();
int D = getValue(btBuffer, ',', 4).toInt();
colorCHSV.hue = H;
colorCHSV.sat = S;
colorCHSV.val = V;
colorMODE = 1;
if (D > 0) FastLED.setBrightness(D);
} else if (btBuffer.startsWith("RTC")) {
int y = getValue(btBuffer, ',', 1).toInt();
int m = getValue(btBuffer, ',', 2).toInt();
int d = getValue(btBuffer, ',', 3).toInt();
int h = getValue(btBuffer, ',', 4).toInt();
int mm = getValue(btBuffer, ',', 5).toInt();
int s = getValue(btBuffer, ',', 6).toInt();
rtc.adjust(DateTime(y, m, d, h, mm, s));
Serial.println("DateTime set");
} else if (btBuffer.startsWith("CLOCK")) {
mode = 0;
} else if (btBuffer.startsWith("TEMPERATURE")) {
mode = 1;
} else if (btBuffer.startsWith("HUMIDITY")) {
mode = 2;
} else if (btBuffer.startsWith("SCOREBOARD")) {
scoreLeft = getValue(btBuffer, ',', 1).toInt();
scoreRight = getValue(btBuffer, ',', 2).toInt();
mode = 3;
} else if (btBuffer.startsWith("STARTTIMER")) {
timerValue = 0;
timerRunning = 1;
mode = 4;
} else if (btBuffer.startsWith("STOPTIMER")) {
timerRunning = 0;
mode = 4;
} else if (btBuffer.startsWith("CHANGINGPATTERN")) {
colorMODE = 2;
}
refreshDisplay();
}
void displayClock() {
DateTime now = rtc.now();
byte h = now.hour();
if (hourFormat == 12 && h > 12)
h = h - 12;
byte m = now.minute();
displaySegments(0, m % 10);
displaySegments(Seg2, m / 10);
displaySegments(Seg3, h % 10);
displaySegments(Seg4, (h / 10) == 0 ? 13 : (h / 10));
displayDots(0);
FastLED.show();
}
void displayTemperature() {
Serial.println("In the temperature loop");
float tmp = dht.readTemperature(temperatureMode == 'F' ? true : false);
Serial.println("Temperature successfully read!");
if (isnan(tmp)) {
Serial.println("Failed to read from DHT sensor!");
} else {
int tmp1 = tmp / 10;
int tmp2 = ((int)tmp) % 10;
displaySegments(Seg4, tmp1);
displaySegments(Seg3, tmp2);
displaySegments(Seg2, 10);
displaySegments(0, (temperatureMode == 'F' ? 14 : 11));
displayDots(1);
FastLED.show();
}
}
void displayHumidity() {
float hum = dht.readHumidity();
if (isnan(hum)) {
Serial.println("Failed to read from DHT sensor!");
} else {
int hum1 = hum / 10;
int hum2 = ((int)hum) % 10;
displaySegments(Seg4, hum1);
displaySegments(Seg3, hum2);
displaySegments(Seg2, 10);
displaySegments(0, 12);
displayDots(1);
FastLED.show();
}
}
void displayScoreboard() {
byte s1 = scoreLeft % 10;
byte s2 = scoreLeft / 10;
byte s3 = scoreRight % 10;
byte s4 = scoreRight / 10;
displaySegments(0, s3);
displaySegments(Seg2, s4);
displaySegments(Seg3, s1);
displaySegments(Seg4, s2);
displayDots(2);
FastLED.show();
}
void displayDots(byte dotMode) {
const int Ind = 14 * NUM_LED_PRO_SEG;
// dotMode: 0=Both on, 1=Both Off, 2=Bottom On, 3=Blink
switch (dotMode) {
case 0:
LEDs[Ind] = colorMODE == 0 ? colorCRGB : colorCHSV;
LEDs[1 + Ind] = colorMODE == 0 ? colorCRGB : colorCHSV;
break;
case 1:
LEDs[Ind] = colorOFF;
LEDs[1 + Ind] = colorOFF;
break;
case 2:
LEDs[Ind] = colorOFF;
LEDs[1 + Ind] = colorMODE == 0 ? colorCRGB : colorCHSV;
break;
case 3:
LEDs[Ind] = (LEDs[Ind] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
LEDs[1 + Ind] = (LEDs[1 + Ind] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
FastLED.show();
break;
default:
break;
}
}
void displaySegments(byte startindex, byte number) {
/*
__ __ __ __ __ __ __ __ __ 12 13 14
__ __ __ __ __ __ 11 15
__ __ __ __ __ __ 10 16
__ __ __ __ 42 __ __ _9 17
__ __ __ __ __ __ __ __ __ 20 19 18
__ 65 __ 44 43 __ 21 _8 _0
__ __ __ __ __ __ _7 _1
__ __ __ __ __ __ _6 _2
__ __ __ __ __ __ __ __ __ _5 _4 _3
*/
byte numbers[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
0b01100011, // º 10
0b00111001, // C(elcius) 11
0b01011100, // º lower 12
0b00000000, // Empty 13
0b01110001, // F(ahrenheit) 14
};
for (byte i = 0; i < 7; i++)
for (byte j = 0; j < NUM_LED_PRO_SEG; j++)
LEDs[i * NUM_LED_PRO_SEG + startindex + j] = ((numbers[number] & 1 << i) == 1 << i) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
}
String getValue(String data, char separator, byte index) {
byte found = 0;
int strIndex[] = { 0, -1 };
byte maxIndex = data.length() - 1;
for (byte i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}