// Schnupperlehre: 2024-02-14
// HW: MCU (ESP32-C3-Super Mini), Rotary Encoder & 24-er LED-Ring
// Mit dem Rotary Encoder können verschiedene Anzeigemodi gewählt werden:
// - Drehbewegung neuer Modus wählen
// - Mit Button gewählter Modus anzeigen
// Bibliotheken einbinden
#include <Adafruit_NeoPixel.h> // <x.h> in Standard-Bibliotheks-Verzeichnis
#include "color.h" // "x.h" eine eigene Bibliotheks-Datei im gleichen Projekt-Verzeichnis
// Rotary Encoder definieren
#define BTN_NEXT 0 // Button "Next" nächster Modus wählen
#define BTN_OK 1 // Tastern "OK" gewählter Modus anzeigen
#define MODE_MAX 12 // Anzahl Anzeigeeffekte
// Zeiten definieren => Wert * 10ms
#define TIME_INTERVAL_SLOW 100
#define TIME_INTERVAL_NORM 50
#define TIME_INTERVAL_FAST 25
// Funktions-Deklarationen (müssen vor dem erstmaligen benützen bekannt gemacht (deklariert) werden
void check_button_mode (void);
void check_button_show_mode (void);
byte step_next (byte limit);
byte step_previous (byte start);
// Variabeln deklarieren und initialisieren
// boolean (true or false), byte (0 ... 255), unsigned int (0 ... 65535)
boolean btn_next_bup = false;
boolean btn_ok_bup = false;
boolean show_mode = false;
boolean first = true;
byte i;
byte mode_nr = 0;
byte step_nr = 0;
boolean direction = false;
unsigned int time_counter = 0;
unsigned int time_interval = 0;
boolean interval = false;
// ------------------------------------------------------------------------------------
// SETUP
// ------------------------------------------------------------------------------------
void setup() {
led_ring.begin(); // LED-Ring inititalisieren
Serial.begin(115200);
Serial.println("---------------------------------------------------------");
pinMode(BTN_NEXT, INPUT_PULLUP);
pinMode(BTN_OK, INPUT_PULLUP);
// Power-On-Test => für 2s leuchten alle LEDs weiss
setAllLedsToColor(0xFF, 0xFF, 0xFF);
delay(2000);
//led_ring.clear(); // Set all pixel colors to ’off’
setDotRainbow(mode_nr);
}
// ------------------------------------------------------------------------------------
// LOOP
// ------------------------------------------------------------------------------------
void loop() {
// **********************************************************************************
// Abfrage der Taster
// **********************************************************************************
check_button_mode();
check_button_show_mode();
// **********************************************************************************
// Anzeige ded gewählen Modus
// **********************************************************************************
if (show_mode == true) {
switch (mode_nr) {
// Modus "Alle LEDs rot"
case 0: // Wenn first = true ist, dann führen wir diesen Codeteil genau einmal aus
if (first == true) {
first = false;
time_interval = TIME_INTERVAL_FAST;
}
if (interval == true) {
interval = false;
setDotRainbow(step_nr);
step_nr = step_next(NUM_PIXELS - 1);
}
break;
// Modus "Alle LEDs grün"
case 1: if (first == true) {
first = false;
setAllLedsToColor(0x00, 0xFF, 0x00);
}
break;
// Modus "Alle LEDs blau"
case 2: if (first == true) {
first = false;
setAllLedsToColor(0x00, 0x00, 0xFF);
}
break;
// Modus "Alle LEDs weiss"
case 3: if (first == true) {
first = false;
setAllLedsToColor(0xFF, 0xFF, 0xFF);
}
break;
// Modus "Alle LEDs in 24 Stufen durch den Regenbogen"
case 4: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_SLOW;
r = 240;
g = 0;
b = 0;
}
// interval wird in gewissen Zeitabständen (TIME_INTERVAL_SLOW) true
// und dann wollen wir diesen Codeteil ausführen
if (interval == true) {
interval = false;
setAllLedsToColor(r, g, b);
Serial.print("Step: "); Serial.print(step_nr); Serial.print(" R: "); Serial.print(r); Serial.print(", G: "); Serial.print(g); Serial.print(", B: "); Serial.println(b);
if (step_nr < 8) {
r -= 30;
g += 30;
} else if (step_nr < 16 ) {
g -= 30;
b += 30;
} else {
b -= 30;
r += 30;
}
step_nr = step_next(23);
}
break;
// Modus "Alle LEDs der Reihen nach im Uhrzeigersinn und den Farben entsprechend einschalten"
case 5: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_NORM;
}
if (interval == true) {
interval = false;
setBarGraphOneColor(step_nr, 255, 0, 255);
step_nr = step_next(NUM_PIXELS - 1);
}
break;
// Modus "Alle LEDs der Reihen nach im Gegen-Uhrzeigersinn und in den 2 Farben entsprechend einschalten"
case 6: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_NORM;
step_nr = NUM_PIXELS - 1;
}
if (interval == true) {
interval = false;
setBarGraphTwoColor(step_nr, 0, 0, 255, 255, 255, 0);
step_nr = step_previous(NUM_PIXELS - 1);
}
break;
// Modus "Alle LEDs der Reihen nach im Gegen-Uhrzeigersinn und in den 2 Farben entsprechend einschalten"
case 7: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_NORM;
step_nr = NUM_PIXELS - 1;
}
if (interval == true) {
interval = false;
setBarGraphMyColorArray(step_nr);
step_nr = step_previous(NUM_PIXELS - 1);
}
break;
// Modus "Einen Punkt im Uhrzeigersinn wandern lassen und dann im Gegen-Uhrzeigersinn zurück"
case 8: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_FAST;
direction = true;
}
if (interval == true) {
interval = false;
setDotOneColor(step_nr, 0, 255, 255);
if (direction == true) {
if (step_nr < (NUM_PIXELS - 1)) {
step_nr++;
} else {
direction = false;
step_nr = NUM_PIXELS - 2;
}
} else {
if (step_nr > 0) {
step_nr--;
} else {
direction = true;
step_nr = 1;
}
}
}
break;
// Modus "Alle LEDs der Reihen nach im Uhrzeigersinn und den Farben im Array entsprechend einschalten"
case 9: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_FAST;
}
if (interval == true) {
interval = false;
for(i = 0; i < NUM_PIXELS; i++) {
if (i <= step_nr) {
led_ring.setPixelColor(i, led_ring.Color(rgb_array[i][0], rgb_array[i][1], rgb_array[i][2]));
} else {
led_ring.setPixelColor(i, led_ring.Color(0x00, 0x00, 0x00));
}
}
led_ring.show();
step_nr = step_next(NUM_PIXELS - 1);
}
break;
// Modus "Alle LEDs leuchten in den regenbogenfarben"
case 10: if (first == true) {
first = false;
setAllLedsToRainbow();
}
break;
// Modus "Alle LEDs der Reihen nach im Uhrzeigersinn in den Regenbogen-Farben entsprechend einschalten"
case 11: if (first == true) {
first = false;
time_interval = TIME_INTERVAL_NORM;
}
if (interval == true) {
interval = false;
setDotRainbow(step_nr);
step_nr = step_next(NUM_PIXELS - 1);
}
break;
case 23:
default: break;
}
// Blinkzeit managen
if (time_counter >= time_interval) {
time_counter = 0;
interval = true;
} else {
time_counter++;
}
}
delay(10); // Warte 10ms
}
// --------------------------------------------------------------------------------------
// Funktion: check_button_mode()
// Frägt den Button für die Moduswahl ab und setzt die entsprechenden die Steuervariablen
// --------------------------------------------------------------------------------------
void check_button_mode (void) {
if ((digitalRead(BTN_NEXT) == LOW) && (btn_next_bup == false)) {
btn_next_bup = true;
if (mode_nr < (MODE_MAX - 1)) {
mode_nr++;
} else {
mode_nr = 0;
}
show_mode = false;
setDotRainbow(mode_nr);
Serial.print("State: "); Serial.println(mode_nr);
}
if ((digitalRead(BTN_NEXT) == HIGH) && (btn_next_bup == true)) {
btn_next_bup = false;
}
}
// --------------------------------------------------------------------------------------
// Funktion: check_button_show_mode()
// Frägt den Button für die Modusanzeige ab und setzt die entsprechenden die Steuervariablen
// --------------------------------------------------------------------------------------
void check_button_show_mode (void) {
if ((digitalRead(BTN_OK) == LOW) && (btn_ok_bup == false)) {
btn_ok_bup = true;
first = true;
show_mode = true;
time_counter = 0;
interval = true;
step_nr = 0;
Serial.print("Show mode");
}
if ((digitalRead(BTN_OK) == HIGH) && (btn_ok_bup == true)) {
btn_ok_bup = false;
}
}
// --------------------------------------------------------------------------------------
// Funktion: step_next(limit) => Uhrzeigersinn
// Erhöht step_nr um 1, bzw. beginnt wieder bei 0 wenn limit erreicht ist
// --------------------------------------------------------------------------------------
byte step_next (byte limit) {
if (step_nr < limit) {
step_nr++;
} else {
step_nr = 0;
}
return step_nr;
}
// --------------------------------------------------------------------------------------
// Funktion: step_previos(start) <= Gegen-Uhrzeigersinn
// Erniedrigt step_nr um 1, bzw. beginnt wieder bei start wenn 0 erreicht ist
// --------------------------------------------------------------------------------------
byte step_previous (byte start) {
if (step_nr > 0) {
step_nr--;
} else {
step_nr = start;
}
return step_nr;
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:18
esp:19
esp:GND.1
esp:3V3.1
esp:3V3.2
esp:GND.2
esp:RST
esp:GND.3
esp:GND.4
esp:5V.1
esp:5V.2
esp:GND.5
esp:GND.6
esp:GND.7
esp:GND.8
esp:GND.9
esp:RX
esp:TX
esp:GND.10
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r