/* Simulationsmodell für das blaue ESP32 Demo-Board
 * Alle Programme aus "Einführung ESP32.pdf" sollten hier laufen. 
 * Ausnahme ist der Touch-Sensor, der hier noch nicht umgesetzt ist.
 * Benötigte Bibliotheken
 * https://github.com/ThingPulse/esp8266-oled-ssd1306
 * https://github.com/adafruit/Adafruit_NeoPixel
 */
#include <Wire.h>
#include "SSD1306Wire.h"
#include <Adafruit_NeoPixel.h>

//***** Portpins für Ein-/Ausgänge ***************************************
const int Enc_A = 34, Enc_B = 35, Enc_Taster = 0, NEO_Pin=26;
const int LED_rot = 32, LED_gruen = 33, Taster2 = 2, Taster4 = 4;

//***** Objekte für Display und Neopixel anlegen
#define NUMPIXELS      1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NEO_Pin, NEO_GRB + NEO_KHZ800);
SSD1306Wire display(0x3c, SDA, SCL);

// ***** Globale Variablen ************************************************
int Encoder, Status; // zur Kommunikation zw. ISR und loop
int Digitalwert;
bool T2_neu, T2_alt, T4_neu, T4_alt;  // für Flankenerkennung
unsigned long nextMillis;

// ***** Initialisierung **************************************************
void setup() {
  Serial.begin(115200);            // Serielle Schnittstelle mit 115200Bit/s
  pinMode(LED_rot, OUTPUT);        // die LEDs beginnen danach
  pinMode(LED_gruen, OUTPUT);      // zu leuchten!
  digitalWrite(LED_rot, HIGH);     // also beide ausschalten
  digitalWrite(LED_gruen, HIGH);
  pinMode(Taster2, INPUT_PULLUP); // Taster brauchen hier den
  pinMode(Taster4, INPUT_PULLUP); // Pullup-Widerstand
  
  // SSD1306 Display initialisieren
  display.init();
  display.flipScreenVertically();
  display.setContrast(255);
  display.setFont(ArialMT_Plain_16);

  // Drehencoder 
  pinMode(Enc_A, INPUT);           // externe Pullups auf der Platine
  pinMode(Enc_B, INPUT);           // Spur B des Encoders
  pinMode(Enc_Taster, INPUT);      // Taster des Encoders = Flash-Taster!

  // Eine Encoder-Spur ruft die ISR void Auswertung(void) auf
  attachInterrupt(digitalPinToInterrupt(Enc_A), Auswertung, RISING);
  attachInterrupt(digitalPinToInterrupt(Taster4), Auswertung4, FALLING);
  Encoder = 0;
  Status = 0;
  
}

// ***** Endlosschleife ***************************************************
void loop() {
  unsigned long currentMillis = millis( );
  if ( currentMillis >= nextMillis ) {
    nextMillis = currentMillis + 1000;    // 1x pro Sekunde Messen
    Digitalwert = analogRead(A0);         // Poti einlesen
    Serial.printf("Digitalwert: %d\n", Digitalwert); 
    display.clear();
    display.drawString(16, 8, "Digitalwert");
    char buf[5];
    sprintf(buf, "%4d", Digitalwert);
    display.drawString(16, 32, buf);
    display.display( );
  }

  // Ausgabe des Drehencoder-Wertes, wenn in der ISR der Status auf 1 gesetzt wurde
  if(Status == 1) {
    Status = 0; // Signal wieder löschen
    Serial.printf("Drehencoder Wert: %4d\n", Encoder);
  }
  if(digitalRead(Enc_Taster) == false) {
    Encoder = 0;
    Serial.printf("\n\nZähler zurück gesetzt!\n\n");
    while(digitalRead(Enc_Taster) == false); // warte auf loslassen
  }
  
  // Flankenerkennung, Anmerkung: die Maustaster prellen scheinbar auch, so dass
  // die LED manchmal mehrfach umschaltet -> also auch hier noch entprellen
  T2_neu = digitalRead(Taster2);
  if ( T2_neu == 0 && T2_alt == 1) {  // fallende Flanke = Tastendruck
    digitalWrite(LED_rot, !digitalRead(LED_rot));  // toggeln
  }
  T2_alt = T2_neu;  // für Flankenerkennung
}

// ***** Eigene Funktionen ************************************************


// ***** Interrupt-Service Routinen ***************************************
// ***** Interrupt-Service Routine Drehencoder ****************************
void Auswertung( ) {
  if(digitalRead(Enc_B)==false) Encoder ++;
  else Encoder --;
  Status = 1;       // Signal an loop geben
}
// ***** Interrupt-Service Routine Taster4 ********************************
void Auswertung4( ) {
  Status = 1;       // Signal an loop geben
}

Taster2
Taster4
LED32
LED33
ESP32 Schulboard mit LEDs und Tastern, I2C-Bus mit Standard-Belegung
SSD1306 Display
WS2812 an Pin26