/* Umprogrammierte Version 2.0 mit folgenden Verbesserungen:
- Im Programmirmodus blinkt die Zeiteinheit, die grade programmiert wird
- KlickButton-Library zum Einlesen der Buttons
- Sollte die Backup-Batterie leer sein, wird Zeit voreingestellt und in SET gesprungen
- Sollte RTC nicht erkannt werden wir in Fehlermodus gesprungen
- Umstieg auf RTCLib von Adafruit
Zuletzt modifiziert: 01.11.17
Zuletzt hochgeladen: 05.11.2018
Status: Funktioniert
Modified by Mirko Pavleski: 27.03.2021
*/
#include <Wire.h>
#include "RTClib.h" // RTClib in Version 1.2.0
// RTC-Instanz initialisieren
RTC_DS3231 realTimeClock;
#include <FastLED.h> // FastLED in Version 3.1.6
#include "ClickButton.h" // ClickButton in Version 1.0.0
#include <elapsedMillis.h> // elapsedMillis in Version 1.0.4
// Definitionen fuer den RGB Streifen (WS2813 RGB Strip, 60 LEDs/m. Gekauft bei led-stuebchen.de
#define LED_PIN 5
#define NUM_LEDS 34
#define LED_TYPE WS2813
#define COLOR_ORDER GRB
#define TASTER_PLUS 4
#define TASTER_MENU 3
#define TASTER_MINUS 2
#define MAX_BRIGHTNESS 100 // Thats full on, watch the power!
#define MIN_BRIGHTNESS 0 // set to a minimum of 25%
const int brightnessInPin = A0;
CRGB leds[NUM_LEDS];
#define UPDATES_PER_SECOND 100
#define FARBE_STUNDEN Crimson
#define FARBE_ZEHNERMINUTEN LimeGreen
#define FARBE_MINUTEN Yellow
// Taster einbinden
ClickButton TasterMenu (TASTER_MENU, LOW, CLICKBTN_PULLUP);
ClickButton TasterPlus (TASTER_PLUS, LOW, CLICKBTN_PULLUP);
ClickButton TasterMinus (TASTER_MINUS, LOW, CLICKBTN_PULLUP);
#define EINZELKLICK 1
#define DOPPELKLICK 2
#define LANGERKLICK -1
elapsedMillis IntervallSensorLesen;
elapsedMillis ZeitAnzeigenIntervall; //
elapsedMillis regularClear; // Strip loschen, damit Ueberlaufe richtig angezeigt werden
elapsedMillis blinkenStunden; // Funktion, um LEDs im SET-Modus zu blinken
elapsedMillis blinkenZehnerminuten; // Funktion, um LEDs im SET-Modus zu blinken
elapsedMillis blinkenEinerminuten; // Funktion, um LEDs im SET-Modus zu blinken
bool ERRORFLAG = false;
// State-Machine Funktions-Namen
typedef enum {
HOCHFAHREN,
ANZEIGE_ZEIT,
EINSTELLEN_ZEIT,
FEHLER
} modus;
modus Funktion = HOCHFAHREN; // Startfunktion der State-Machine
// State-Machine RTC-Stellmodus
typedef enum {
STUNDEN,
ZEHNERMINUTEN,
EINERMINUTEN
} set_modus;
set_modus Funktion_Set = STUNDEN; // Startfunktion der SET Funktion
void setup() {
//Serial.begin(9600);
// Initialisierung der LEDs
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness(MAX_BRIGHTNESS);
//realTimeClock.adjust(DateTime(2014, 1, 21, 11, 40, 55));
}
void loop() {
int mappedValue = map(analogRead(brightnessInPin), 0, 1023, 0, 100);
FastLED.setBrightness(constrain(mappedValue, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
if (ERRORFLAG == true) {
Funktion = FEHLER;
}
// Taser lesen und Wert abspeichern
TasterMinus.Update();
int taster_minus = TasterMinus.clicks;
TasterMenu.Update();
int taster_menu = TasterMenu.clicks;
TasterPlus.Update();
int taster_plus = TasterPlus.clicks;
switch (Funktion) {
case HOCHFAHREN: {
// Hier werden Initialisierungen durchgefuhrt
// Wenn RTC nicht erkannt wird: I2C-Problem. In den Fehlermodus springen
if (!realTimeClock.begin()) {
Funktion = FEHLER;
}
// Wenn RTC-Backup-Batterie gewechselt wurde, Zeit voreinstellen und in SET springen. 01.01.2017 07:08:09Uhr
else if (realTimeClock.lostPower())
{
realTimeClock.adjust(DateTime(2000, 1, 1, 12, 55, 0));
Funktion = EINSTELLEN_ZEIT;
}
else {
ClearStrip();
Funktion = ANZEIGE_ZEIT;
}
} // Ende HOCHFAHREN
break;
case ANZEIGE_ZEIT: {
ZeigeZeit();
if (taster_menu == LANGERKLICK) {
ClearStrip();
Funktion = EINSTELLEN_ZEIT;
}
} // Ende ANZEIGE_ZEIT
break;
case EINSTELLEN_ZEIT: {
static bool set_fertig = false;
static int jahr_fest = 2017;
static int monat_fest = 1;
static int tag_fest = 1;
static int stundenuebergabe = 0;
static int zehnerminutenuebergabe = 0;
static int einerminutenuebergabe = 0;
if (set_fertig == false) // Wenn "frisch" in SET gesprungen wird, wird die aktuelle Zeit eingelesen.
{
DateTime now = realTimeClock.now();
stundenuebergabe = now.hour();
zehnerminutenuebergabe = (now.minute() / 10) % 10; // Zehnerminuten berechnen
einerminutenuebergabe = (now.minute() % 10); // Einerminuten berechnen
set_fertig = true;
}
switch (Funktion_Set) {
case STUNDEN: {
if (taster_minus == EINZELKLICK)
{
stundenuebergabe--;
if (stundenuebergabe > 23) stundenuebergabe = 0;
else if (stundenuebergabe < 0) stundenuebergabe = 23;
}
if (taster_plus == EINZELKLICK)
{
stundenuebergabe++;
if (stundenuebergabe > 23) stundenuebergabe = 0;
else if (stundenuebergabe < 0) stundenuebergabe = 23;
}
if (taster_menu == EINZELKLICK)
{
Funktion_Set = ZEHNERMINUTEN;
}
AnzeigeStundenBlinkend(stundenuebergabe);
//AnzeigeZehnerminuten(zehnerminutenuebergabe);
//AnzeigeEinerminuten(einerminutenuebergabe);
} // Ende STUNDEN
break;
case ZEHNERMINUTEN: {
if (taster_minus == EINZELKLICK)
{
zehnerminutenuebergabe--;
if (zehnerminutenuebergabe > 5) zehnerminutenuebergabe = 0;
else if (zehnerminutenuebergabe < 0) zehnerminutenuebergabe = 5;
}
if (taster_plus == EINZELKLICK)
{
zehnerminutenuebergabe++;
if (zehnerminutenuebergabe > 5) zehnerminutenuebergabe = 0;
else if (zehnerminutenuebergabe < 0) zehnerminutenuebergabe = 5;
}
if (taster_menu == EINZELKLICK)
{
Funktion_Set = EINERMINUTEN;
}
AnzeigeZehnerminutenBlinkend(zehnerminutenuebergabe);
} // Ende ZEHNERMINUTEN
break;
case EINERMINUTEN: {
if (taster_minus == EINZELKLICK)
{
einerminutenuebergabe--;
if (einerminutenuebergabe > 9) einerminutenuebergabe = 0;
else if (einerminutenuebergabe < 0) einerminutenuebergabe = 9;
}
if (taster_plus == EINZELKLICK)
{
einerminutenuebergabe++;
if (einerminutenuebergabe > 9) einerminutenuebergabe = 0;
else if (einerminutenuebergabe < 0) einerminutenuebergabe = 9;
}
if (taster_menu == EINZELKLICK)
{
Funktion_Set = STUNDEN;
}
AnzeigeEinerminutenBlinkend(einerminutenuebergabe);
} // Ende EINERMINUTEN
break;
}
if (taster_menu == LANGERKLICK)
{
realTimeClock.adjust(DateTime(jahr_fest, monat_fest, tag_fest, stundenuebergabe, (einerminutenuebergabe + (zehnerminutenuebergabe * 10)), 0));
set_fertig = false;
Funktion_Set = STUNDEN;
ClearStrip();
ZeigeZeit();
Funktion = ANZEIGE_ZEIT;
}
} // Ende EINSTELLEN_ZEIT
break;
case FEHLER: { // bei Fehlern gesamten LED Strip rot blinken
leds[0] = CRGB::Red;
leds[NUM_LEDS - 1] = CRGB::Red;
FastLED.show();
while (1);
} // Ende FEHLER
break;
}
}
int ZeigeZeit() {
DateTime now = realTimeClock.now(); //Aktuelle Zeit aus der RTC holen und in "now" zwischenspeichern
AnzeigeStunden(now.hour());
AnzeigeZehnerminuten ((now.minute() / 10) % 10);
AnzeigeEinerminuten (now.minute() % 10);
ZeitAnzeigenIntervall = 0;
}
void ClearStrip() { // Alle LEDs in einer fliessenden Bewegung von rechts nach links loeschen (Black)
for (int i = 0; i <= NUM_LEDS - 1; i++) {
leds[i] = CRGB::Black;
FastLED.show();
}
}
int AnzeigeStunden (int wert) { // Funktion, um die Stunden anzuzeigen. 24h wird in 12h "runtergebrochen"
if (wert > 12) wert = (wert - 12);
else if (wert > 23) wert = 0;
int werte_led_tabelle[12][2] = { // Umrechnungstabelle. {1, 19} heisst = alle LEDs bis 19 leuchten, {5, 24} alle LEDs bis 24 leuchten
//(STUNDE, LED-NR im Strip)
{1, 19},
{2, 20},
{3, 21},
//Sprung, eine LED zwischendrin frei (Nr 22)
{4, 23},
{5, 24},
{6, 25},
//Sprung, eine LED zwischendrin frei (Nr 26)
{7, 27},
{8, 28},
{9, 29},
//Sprung, eine LED zwischendrin frei (Nr 30)
{10, 31},
{11, 32},
{12, 33}
};
for (int i = 0; i <= wert - 1; i++) {
leds[(werte_led_tabelle[i][1])] = CRGB::FARBE_STUNDEN;
FastLED.show();
}
for (int f = wert; f <= 11; f++) {
leds[(werte_led_tabelle[f][1])].fadeToBlackBy(255);
FastLED.delay(10);
FastLED.show();
}
}
void AnzeigeStundenBlinkend(int stunden) {
if (blinkenStunden > 350) {
static bool lastMode = 0;
if (lastMode == 0)
{
AnzeigeStunden(stunden);
lastMode = 1;
}
else
{
ClearStrip();
lastMode = 0;
}
blinkenStunden = 0;
}
}
int AnzeigeZehnerminuten (int wert) { // Funktion, um die Zehnerminuten anzuzeigen.
if (wert > 5 || wert < 0) {
wert = 0;
}
int werte_led_tabelle[5][2] = {
{1, 17},
{2, 16},
{3, 15},
//Sprung, eine LED zwischendrin frei
{4, 13},
{5, 12}
};
for (int j = 0; j <= wert - 1; j++) {
leds[(werte_led_tabelle[j][1])] = CRGB::FARBE_ZEHNERMINUTEN;
FastLED.show();
}
for (int g = wert; g <= 4; g++) {
leds[(werte_led_tabelle[g][1])].fadeToBlackBy(255);
FastLED.delay(10);
FastLED.show();
}
}
void AnzeigeZehnerminutenBlinkend(int wert) {
if (blinkenZehnerminuten > 350) {
static bool lastMode = 0;
if (lastMode == 0)
{
AnzeigeZehnerminuten(wert);
lastMode = 1;
}
else
{
ClearStrip();
lastMode = 0;
}
blinkenZehnerminuten = 0;
}
}
int AnzeigeEinerminuten (int wert) { // // Funktion, um die Einerminuten anzuzeigen. LEDs 0 - 10 von links
if (wert > 9 || wert < 0) {
wert = 0;
}
int werte_led_tabelle[9][2] = {
{1, 10},
{2, 9},
{3, 8},
//Sprung, eine LED zwischendrin frei
{4, 6},
{5, 5},
{6, 4},
//Sprung, eine LED zwischendrin frei
{7, 2},
{8, 1},
{9, 0} // erste LED im Streifen = LED 0, weil Array bei 0 beginnt
};
for (int k = 0; k <= wert - 1; k++) {
leds[(werte_led_tabelle[k][1])] = CRGB::FARBE_MINUTEN;
FastLED.show();
}
for (int m = wert; m <= 8; m++) {
leds[(werte_led_tabelle[m][1])].fadeToBlackBy(255);
FastLED.delay(10);
FastLED.show();
}
}
void AnzeigeEinerminutenBlinkend(int wert) {
if (blinkenEinerminuten > 350) {
static bool lastMode = 0;
if (lastMode == 0)
{
AnzeigeEinerminuten(wert);
lastMode = 1;
}
else
{
ClearStrip();
lastMode = 0;
}
blinkenEinerminuten = 0;
}
}
Comments
Please log in or sign up to comment.