Projekt HOME Control Teil 3 Menü

Im dritten Teil erstellen wir ein Menü das am TFT-Display angezeigt wird. Mit dem Rotary-Encoder aus dem 35in1 Sensor-Kit können wir einen Eintrag im Menü auswählen. Sind mehr Menüeinträge als Display-Zeilen scrollt die Anzeige automatisch nach oben oder nach unten sodass der ausgewählte Eintrag immer zu sehen ist.

Verdrahtung:

Programm:

 

#include <adafruit_gfx.h>        // Core graphics library
#include <adafruit_st7735.h> // Hardware-specific library
//Einbindung von Font Bibliotheken
#include <Fonts/FreeSans9pt7b.h> //Font für Logo
#include <Fonts/FreeSansBold9pt7b.h> //Font für Logo

#include <spi.h>
#include <sd.h>

//Definition der verwendeten Pins
#define TFT_CS    5    // Chip select line for TFT display
#define TFT_RST    22    // Reset line for TFT
#define TFT_DC     21    // Data/command line for TFT

#define SD_CS        16    // Chip select line for SD card


//tft instance
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

char *menu[] = {"Eintrag 1", "Eintrag 2", "Eintrag 3", "Eintrag 4",
               "Eintrag 5", "Eintrag 6", "Eintrag 7", "Eintrag 8", "Eintrag 9",
               "Eintrag 10", "Eintrag 11", "Eintrag 12", "Eintrag 13", "Eintrag 14"};
               
uint8_t menu_lines = 14; //Anzahl der Menüeinträge

const byte button = 15;
const byte pulse = 14;
const byte pulseDirection = 4 ;

portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
volatile int menuUp = 0;
volatile int menuDown = 0;
volatile int menuBtn = 0;

//globale Variablen für das Menü
uint8_t line_len = 127; //Anzahl der pixels pro Zeile
uint8_t start_menu = 32; //Zeile in der das Menü beginnt
uint8_t menu_size = 12; //Anzahl Menü zeilen a 10 Pixel
uint16_t fnt_color = ST7735_WHITE; //Schriftfarbe
uint16_t bg_color = ST7735_BLACK; //Menühintergrund
uint16_t sel_fnt_color = ST7735_BLACK; //Schriftfarbe für Auswahl
uint16_t sel_bg_color = ST7735_GREEN; //Hintergrund für Auswahl
uint8_t line_selected = 0; //Ausgewählte Menüzeile
uint8_t top_line = 0; //erste dargestellte Menüzeile

//Funktion zum Schreiben einer selektierten Zeile
void menuSelLine(uint8_t line, char *txt){
   uint8_t y1 = line * 10 + start_menu; //Oberkante der Zeile
   tft.setCursor(4,y1);
   tft.setTextColor(sel_fnt_color,sel_bg_color);
   tft.print(txt);
}

//Funktion zum Schreiben einer Zeile
void menuLine(uint8_t line, char *txt){
   uint8_t y1 = line * 10 + start_menu; //Oberkante der Zeile
   tft.setCursor(4,y1);
   tft.setTextColor(fnt_color,bg_color);
   tft.print(txt);
}

//Funktion zum Anzeigen des Menüs
void showMenu() {
   //zuerst den Hintergrund löschen
   tft.fillRect(0,(start_menu),line_len,(menu_size * 10),bg_color);
   uint8_t mlin = top_line;
   while ((mlin < menu_lines) && ((mlin - top_line) < menu_size)) {
       if (mlin == line_selected) {
           menuSelLine(mlin-top_line,menu[mlin]);
       } else {
           menuLine(mlin-top_line,menu[mlin]);
       }
       mlin++;
   }
   
}

//Funktion um die Auswahl nach unten zu verschieben
void selectionDown() {
       line_selected++;
       if (line_selected >= menu_lines) line_selected = menu_lines-1;
       if ((line_selected - top_line) >= menu_size) top_line++;
       showMenu();
}


//Funktion um die Auswahl nach oben zu verschieben
void selectionUp() {
       if (line_selected > 0) line_selected--;
       if (line_selected < top_line) top_line--;
       showMenu();
}

//Funktion zum Anzeigen eines Textes am Display in einer bestimmten Farbe
void displayText(char *text , uint16_t color) {
   tft.setTextColor(color);
   tft.setTextWrap(true); //automatischer Zeilenumbruch wird aktiviert

   tft.print(text);
}

//Funktion zum Anzeigen eines Textes an einem beliebigen Punkt (x,y) auf
//dem Display. Die Farbe kann gewählt werden
void displayText(uint16_t x, uint16_t y, char *text , uint16_t color) {
   tft.setCursor(x, y);
   displayText(text,color);
}

//Funktion zum Anzeigen des Logos ganz oben am Display
void displayLogo() {
   //Hintergrund füllen
   tft.fillRect(0,0,127,30,ST7735_YELLOW);
   //Rahmen zeichnen
   tft.drawRect(1,1,125,28,ST7735_BLUE);
   //Font für das Wort HOME fett
    tft.setFont(&FreeSansBold9pt7b);
    //Cursor positionieren
    tft.setCursor(7,20);
    //Text in schwarz ausgeben
    tft.setTextColor(ST7735_BLACK);
    tft.print("HOME");
    //Font für das Wort Control nicht fett
    tft.setFont(&FreeSans9pt7b);
    //Text in rot ausgeben
    tft.setTextColor(ST7735_RED);
    tft.print("Control");
    //Font auf default zurücksetzen
    tft.setFont(NULL);
}

//interrupt service for switch
//change current color
void IRAM_ATTR btnClick() {
   portENTER_CRITICAL_ISR(&mux);
   menuBtn = 1;
   portEXIT_CRITICAL_ISR(&mux);
}

//interrupt for rotary pulse
void IRAM_ATTR rotaryPulse() {
   byte dir = digitalRead(pulseDirection);
   if ((menuUp == 0) && (menuDown == 0)) {
       portENTER_CRITICAL_ISR(&mux);
       if (dir==0) {
           menuUp = 1;
       } else {
           menuDown = 1;
       }
       portEXIT_CRITICAL_ISR(&mux);
   }
}

   
void setup() {
   Serial.begin(115200);
   //tft initialisieren und schwarzer Hintergrund
   tft.initR(INITR_BLACKTAB);
   tft.fillScreen(ST7735_BLACK);
   //Logo anzeigen
   displayLogo();
   //SD-Karte initialisieren und Ergebnis anzeigen
   if (!SD.begin(SD_CS)) {
       displayText(25,40,"Keine SD-Card",ST7735_YELLOW);
   } else {
       displayText(34,40,"SD-Card OK",ST7735_GREEN);
   }
   delay(1000);
   showMenu();
   //define input pins
   pinMode(button, INPUT_PULLUP);
   pinMode(pulse, INPUT_PULLUP);
   pinMode(pulseDirection, INPUT_PULLUP);
   //define interrupts
   attachInterrupt(digitalPinToInterrupt(pulse),rotaryPulse, FALLING);
   attachInterrupt(digitalPinToInterrupt(button),btnClick, FALLING);
}

void loop() {
   if (menuUp) {
           delay(100); //Zum entprellen
           portENTER_CRITICAL(&mux);
           menuUp = 0;
           menuDown=0;
           portEXIT_CRITICAL(&mux);
           selectionUp();
           Serial.println("Up");
   }
   if (menuDown) {
           delay(100); //Zum entprellen
           portENTER_CRITICAL(&mux);
           menuUp=0;
           menuDown = 0;
           portEXIT_CRITICAL(&mux);
           selectionDown();
           Serial.println("Down!");
   }


}

 

Beschreibung der Parameter:

  • line_len = 127 Breite einer Displayzeile in Pixel
  • start_menu = 32 Position der Oberkante der ersten Zeile des Manüs
  • menu_size = 12 Anzahl der Zeilen die für das Menü verwendet werden
  • fnt_color = ST7735_WHITE Farbe der Schrift für einen Eintrag
  • bg_color = ST7735_BLACK Farbe des Hintergrunds für einen Eintrag
  • sel_fnt_color = ST7735_BLACK Farbe der Schrift für einen ausgewälten Eintrag
  • sel_bg_color = ST7735_GREEN Farbe des Hintergrunds für einen ausgewälten Eintrag
  • line_selected = 0 Nummer der Zeile im Menü, die gerade ausgewählt ist
  • top_line = 0 Nummer der Zeile im Menü die zu oberst im Display erscheint. Ein Wert größer 0 bewirkt das Scrollen des Menüs

 

Das Programm kann auch als File von GIT-Hub geladen werden. Datei zentrale.ino im ZIP-Paket

https://github.com/GerLech/HomeControl/archive/master.zip

Letzter Artikel LCD KeyPad Shield

Hinterlasse einen Kommentar

Kommentare müssen vor der Veröffentlichung überprüft werden

Erforderliche Angabe