OK

Při poskytování služeb nám pomáhají soubory cookie. Používáním našich služeb vyjadřujete souhlas s naším používáním souborů cookie. Více informací

Úvodní stránka » Arduino » Arduino v příkladech - XI. díl - Displej - tlačítka trochu jinak

Arduino v příkladech - XI. díl - Displej - tlačítka trochu jinak

Kreslení tlačítek mě osobně vůbec nebaví. A když otočím displej, celé se to rozpadne. Řešení je přitom jednoduché. Tak pojďme počítat, použít definici pole typu struct, pak bombónek a na závěr kreslení barevných obrázků.

Kreslení vypočítaných tlačítek

Abychom stále nemuseli psát několikrák za sebou ttlačítko tady, tlačítko tamhle, spočítek pozici a ono to ještě není ono a ten text není zarovnaný na středu, vytvořil jsem pro Vás příklad, kde se tlačítka vypočítají podle pár zadaných hodnot a sami se přizpůsobí orientaci displeje. Za pomoci funkce drawButton(int place, int y, int height, int color, char* text, byte font) to bude mnohem jednodušší. Parametry: place – umístění (LEFT, CENTER, RIGHT), y – umístění na výšku, height – výška tlačítka, color – barva tlačítka, text – text tlačítka a font – typ písma.

I zpětná vazba pro dotykovou plochu je jednoduchá. Hodnoty x se pro dané umístění nemění, stačí zkopírovat z programu, pouze určujete pozici y.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne pro urceni umisteni tlacitka
#define LEFT       0   // promenna pro urceni zobrazeni tlacitka
#define CENTER     1   // promenna pro urceni zobrazeni tlacitka
#define RIGHT      2   // promenna pro urceni zobrazeni tlacitka
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime prvni tlacitka
  drawButton(CENTER, 60, 50, TFT_RED, "ON", 2); // nakresli tlacitko
  drawButton(RIGHT, 230, 50, TFT_RED, "ON", 4); // nakresli tlacitko
  drawButton(LEFT, 230, 50, TFT_RED, "ON", 1); // nakresli tlacitko
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // overeni stisku tlacitka a spusteni souvisejici akce
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      if ((x >= 60 && x <= 180) && (y >= 60 && y <= 110)) {  // tlacitko na stredu
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(LEFT, 230, 50, TFT_RED, "ON", 1); // nakresli tlacitko
      }
      else if ((x >= 10 && x <= 110) && (y >= 230 && y <= 280)) {  // tlacitko vlevo
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(RIGHT, 230, 50, TFT_RED, "ON", 4); // nakresli tlacitko
      }
      else if ((x >= 130 && x <= 230) && (y >= 230 && y <= 280)) {  // tlacitko vpravo
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(CENTER, 60, 50, TFT_RED, "ON", 2); // nakresli tlacitko
      }
    }
  }
}
//------------------------------------------------------------------
// funkce kresleni tlacitka
void drawButton(int place, int y, int height, int color, char* text, byte font) {
  int x = tft.width(); // zjisteni sirky displeje
  int width = 100; // sirka tlacitka pro umisteni vlevo a vpravo
  //------------------------------------------------------------------
  if (place == 0) x = (x / 2) - (x / 4); // urceni x pro tlacitko vlevo
  else if (place == 1) { // tlacitko uprostred
    x = x / 2; // urceni x pro tlacitko uprostred
    width = 120; // urceni sirky pro tlacitko uprostred
  }
  else if (place == 2) x = (x / 2) + (x / 4); // urceni x pro tlacitko vpravo
  //------------------------------------------------------------------
  tft.fillRoundRect((x - (width / 2)) - 1, y - 1, width + 2, height + 2, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(x - (width / 2), y, width, height, 10, color); // zobrazeni tlacitka
  //------------------------------------------------------------------
  if (font == 4 ) y = (y + (height / 2)) - 10; // urceni pozice y pro font 4
  else if (font == 2 ) y = (y + (height / 2)) - 8; // urceni pozice y pro font 2
  else y = (y + (height / 2)) - 3; // urceni pozice y pro font 1
  //------------------------------------------------------------------
  tft.drawCentreString(text, x, y, font); // zobrazeni textu
}

Tlačítka definované polem struct

Existuje přehlednější řešení za pomoci pole struct. Pro začátečníky to bude novinka, ale snařil jsem se to napsat opravdu jednoduše. Jak na to. V hlavičce pole jsme definovali pole struct a pak jednotlivá tlačítka jako globální proměnné. Pak už je pouze voláme v jednotlivých funkcích. Pouze se nesmí zapomenout předpona např. drawButton(button1); Tak tlačítka nejen kreslíme, ale dotazujeme se i na stisknuté tlačítko. Pro ukázku jsme využili předchozí program, který se nám poněkud prodloužil, úložiště mi snad odpustí, ale výrazně se zjednodušilo psaní a čtení programu. Také jsem pro ukázku přidal čtvrté tlačítko, kde uvidíte jak na základě nějaké podmínky měnit barvu a text tlačítka přímo v poli struct a potom opět jenom kreslíme.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne pro urceni umisteni tlacitka
#define LEFT       0   // promenna pro urceni zobrazeni tlacitka
#define CENTER     1   // promenna pro urceni zobrazeni tlacitka
#define RIGHT      2   // promenna pro urceni zobrazeni tlacitka
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
// Vytvoreni promennych pro tlacitka
struct defineButton {
  int place;
  int y;
  int height;
  int color;
  char* text;
  byte font;
};
//------------------------------------------------------------------
// Vytvoreni jednotlivych tlacitek
defineButton button1 = {CENTER, 60, 50, TFT_RED, "CENTER", 2};
defineButton button2 = {RIGHT, 230, 50, TFT_RED, "RIGHT", 4};
defineButton button3 = {LEFT, 230, 50, TFT_RED, "LEFT", 1};
defineButton button4 = {CENTER, 140, 50, TFT_RED, "OFF", 4};
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime prvni tlacitka
  drawButton(&button1); // nakresli tlacitko
  drawButton(&button2); // nakresli tlacitko
  drawButton(&button3); // nakresli tlacitko
  drawButton(&button4); // nakresli tlacitko
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // overeni stisku tlacitka a spusteni souvisejici akce
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      if (checkTouch(&button1)) {  // tlacitko na stredu
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(&button3); // nakresli tlacitko
        drawButton(&button4); // nakresli tlacitko
      }
      else if (checkTouch(&button3)) {  // tlacitko vlevo
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(&button2); // nakresli tlacitko
        drawButton(&button4); // nakresli tlacitko
      }
      else if (checkTouch(&button2)) {  // tlacitko vpravo
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(&button1); // nakresli tlacitko
        drawButton(&button4); // nakresli tlacitko
      }
      else if (checkTouch(&button4)) {  // tlacitko zap/vyp menime barvu
        tft.fillScreen(TFT_WHITE); // nastaveni pozadi
        drawButton(&button1); // nakresli tlacitko
        drawButton(&button2); // nakresli tlacitko
        drawButton(&button3); // nakresli tlacitko
        //------------------------------------------------------------------
        // zkontrolujeme barvu tlacitka a nastavime nove hodnoty
        if (button4.color == TFT_RED) { // zkontrolujeme stav tlacitka
          button4.color = TFT_GREEN; // nastavime novou barvu
          button4.text = "ON"; // nastavime novy text
        }
        else {
          button4.color = TFT_RED; // nastavime novou barvu
          button4.text = "OFF"; // nastavime novy text
        }
        drawButton(&button4); // nakresli tlacitko
      }
    }
  }
}
//------------------------------------------------------------------
// kontrola zda bylo stisknuto tlacitko
boolean checkTouch (struct defineButton *b) {
  boolean press = false; // hodnota pro potvrzeni stisku
  int xTouch = tft.width(); // zjisteni sirky displeje
  int width = 100 / 2; // sirka tlacitka pro umisteni vlevo a vpravo
  //------------------------------------------------------------------
  if (b->place == 0) xTouch = (xTouch / 2) - (xTouch / 4); // urceni x pro tlacitko vlevo
  else if (b->place == 1) { // tlacitko uprostred
    xTouch = xTouch / 2; // urceni x pro tlacitko uprostred
    width = 120 / 2; // urceni sirky pro tlacitko uprostred
  }
  else if (b->place == 2) xTouch = (xTouch / 2) + (xTouch / 4); // urceni x pro tlacitko vpravo

  if ((x >= (xTouch - (width)) && x <= (xTouch + (width))) && (y >= b->y && y <= (b->y + b->height))) {
    press = true; // nastav novou hodnotu
  }
  return press; // vrat hodnotu
}
//------------------------------------------------------------------
// funkce kresleni tlacitka
void drawButton(struct defineButton *b) {
  int xTouch = tft.width(); // zjisteni sirky displeje
  int width = 100; // sirka tlacitka pro umisteni vlevo a vpravo
  int yText; // pozice textu
  //------------------------------------------------------------------
  if (b->place == 0) xTouch = (xTouch / 2) - (xTouch / 4); // urceni x pro tlacitko vlevo
  else if (b->place == 1) { // tlacitko uprostred
    xTouch = xTouch / 2; // urceni x pro tlacitko uprostred
    width = 120; // urceni sirky pro tlacitko uprostred
  }
  else if (b->place == 2) xTouch = (xTouch / 2) + (xTouch / 4); // urceni x pro tlacitko vpravo
  //------------------------------------------------------------------
  tft.fillRoundRect((xTouch - (width / 2)) - 1, b->y - 1, width + 2, b->height + 2, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(xTouch - (width / 2), b->y, width, b->height, 10, b->color); // zobrazeni tlacitka
  //------------------------------------------------------------------
  if (b->font == 4 ) yText = (b->y + (b->height / 2)) - 10; // urceni pozice y pro font 4
  else if (b->font == 2 ) yText = (b->y + (b->height / 2)) - 8; // urceni pozice y pro font 2
  else yText = (b->y + (b->height / 2)) - 3; // urceni pozice y pro font 1
  //------------------------------------------------------------------
  tft.drawCentreString(b->text, xTouch, yText, b->font); // zobrazeni textu
}

V poli struct můžete definovat celé tlačítko a nic nemusíte počítat. To je jeho velká výhoda.

Zpět k počítání - klávesnice

Tak tohle to může napsat jenom masochista. Vlastně jsem to napsal, aby bylo možné nakreslit jednoduše sadu tlačítek, třeba jako klávesnici. Jenom zadáte hodnoty, řeknete programu na jaké stránce se jaká klávesnice nachází a celé se to jenom počítá. Je tam i popis jak s tím pracovat.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
// promenne ktere je nutne vytvorit na globalni urovni
#define MAX_POCET_TLACITEK 12  // nastaveni maximalniho poctu tlacitek v ramci celeho displeje
//------------------------------------------------------------------
// data klavesnice zobrazeni na displej - nastavuji se u konkretniho zobrazeni
char* textT[MAX_POCET_TLACITEK]; // text jednotlivych tlacitek
byte cisloKlavesnice; // nastavte cislo klavesnice
int ttfs; // sirka vykresleni tlacitek (displeje)
int ttfv; // vyska vykresleni tlacitek spodni hrana (displeje)
byte ptls; // pocet tlacitek do sirky
byte ptlv; // počet tlacitek do vysky
byte tv; // vyska tlacitka
byte ts; // sirka tlacitka - vypoctena
byte ob; // oblouk rohu tlacitka
byte m; // mezera mezi tlacitky
char charText[8]; // promenna pro zobrazeni textu
byte pozice; // promenna pro vypocet umisteni pole
int bx[MAX_POCET_TLACITEK]; // nutno zadat rucne pocet poli = pocet tlacitek, muze byt vice
int by[MAX_POCET_TLACITEK]; // nutno zadat rucne pocet poli = pocet tlacitek, muze byt vice
byte pocitadloS; // promenna sirka pro cyklus for
byte pocitadloV; // promenna vyska pro cyklus for
int poleX; // pozice pole pro zobrazeni hodnot
int poleY; // pozice pole pro zobrazeni hodnot
int poleD; // delka pole pro zobrazeni hodnot
int poleV; // pozice pole pro zobrazeni hodnot
int obPole; // oblouk rohu pole pro zobrazeni hodnot
int barvaT[MAX_POCET_TLACITEK]; // barva jednotlivych tlacitek
int barvaPisma; // barva pisma a pozadi
int barvaPozadi; // barva pozadi
int barvaObrys; // barva obrysu
//------------------------------------------------------------------
// data pro textové pole klavesnice
byte TEXT_MAX; // maximalni pocet znaku pole
String textPole = ""; // promenna pro zobrazeni hodnot na displeji
byte textPole_i = 0; // promenna pro index poli
//------------------------------------------------------------------
void setup(void) {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  klavesnice(); // zobrazeni klavesnice
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk();
  }
}
void dotyk () {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // zjisteni stavu stranek, overeni stisku tlacitka a spusteni souvisejiciho programu
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      //------------------------------------------------------------------
      // kontrola stisku klavesy
      for (pozice = 0; pozice < (ptls * ptlv); pozice++) { // nastav pozici
        if ((x >= bx[pozice] && x <= bx[pozice] + ts) && (y >= by[pozice] && y <= by[pozice] + tv)) { // zkontroluj stisknute tlacitko
          pole(); // spust reakci na dotyk
          break; // kdyz odpovida stisknute tlacitko ukonci cyklus
        }
      }
    }
  }
}
//------------------------------------------------------------------
void pole() { //pole zobrazeni hodnot a akce na tlacitka
  //------------------------------------------------------------------
  tft.setTextColor(barvaPisma, barvaPozadi); // nastav barvu a pozadi textoveho pole
  //------------------------------------------------------------------
  switch (pozice) {
    case 9: // kdyz je stisknuto tlacitko Esc (nutno snizit o 1 - pocita se od 0)
      if (textPole != "") { // kdyz pole neni prazdne
        textPole_i --; // zmensi index pole o jednu hodnuto
        textPole = textPole.substring(0, textPole_i); // zmensi text o jednu hodnotu
        textPole.toCharArray(charText, TEXT_MAX + 1); // preved string na char
        tft.fillRoundRect(poleX + 1, poleY + 1, poleD - 2, poleV - 2, obPole, barvaPozadi); // vycisti pole
        tft.drawCentreString(charText, poleX + (poleD / 2), poleY + (poleV / 2) - 10, 4); // nakresli text
      }
      else { // jinak se vrat na predchozi stranu
        klavesnice(); // navrat na predchozi stranku
      }
      break;
    case 11: // kdyz je stisknuto tlacitko OK (nutno snizit o 1 - pocita se od 0)
      klavesnice(); // zobraz dalsi stranku
      break;
    default: // kdyz neni splnena zadna predchozi podminka
      if (textPole_i < TEXT_MAX) { // kdyz je delka retezce mensi nez max povolena
        textPole = textPole + String(textT[pozice]);
        textPole.toCharArray(charText, TEXT_MAX + 1); // preved string na char
        tft.drawCentreString(charText, poleX + (poleD / 2), poleY + (poleV / 2) - 10, 4); // nakresli text
        textPole_i ++;
      }
      break;
  }
}
//------------------------------------------------------------------
void tlacitka() { // zobrazeni klavesnice
  //------------------------------------------------------------------
  // vypocet a doplneni promennych
  ts = (ttfs - ((ptls + 1) * m)) / ptls; // sirka tlacitka - vypoctena
  y = ttfv - (ptlv * m + ptlv * tv); // vypocet prvni rady tlacitek
  //------------------------------------------------------------------
  // nastav promenne
  textPole = ""; // vycisti pole pro dalsi zpracovani
  textPole_i = 0; // vycisti index pole pro dalsi zpracovani
  //------------------------------------------------------------------
  // nastaveni pro zobrazeni
  tft.setTextColor(barvaPisma); // nastaveni barvy pisma
  tft.fillScreen(barvaPozadi); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakresli tlacitka
  for (pocitadloV = 1; pocitadloV <= ptlv; pocitadloV++) { // podminka pro kresleni tlacitek do vysky
    for (pocitadloS = 1; pocitadloS <= ptls; pocitadloS++) { // podminka pro kresleni tlacitek do sirky
      pozice = ((pocitadloV - 1) * ptls) + pocitadloS - 1; // vypocet umisteni pole
      tft.fillRoundRect((pocitadloS * m) + ((pocitadloS - 1) * ts), y, ts, tv, ob, barvaObrys); // naktesli obrys
      tft.fillRoundRect((pocitadloS * m) + ((pocitadloS - 1) * ts) + 1, y + 1, ts - 2, tv - 2, ob, barvaT[pozice]); // nakresli vypln
      tft.drawCentreString(textT [pozice], (pocitadloS * m) + (pocitadloS * ts) - (ts / 2), y + (tv / 2) - 10, 4); // nakresli text
      bx [pozice] = (pocitadloS * m) + ((pocitadloS - 1) * ts); // vypln promennou pro dotyk
      by [pozice] = y; //vypln promennou pro dotyk
    }
    y = y + (m + tv); // vypocti novy radek
  }
  //------------------------------------------------------------------
  // pole pro zobrazeni stisknutych hodnot
  tft.drawRoundRect(poleX, poleY, poleD, poleV, obPole, barvaObrys); // naktesli obrys
}
  //------------------------------------------------------------------
  void klavesnice() {
  //------------------------------------------------------------------
  // klavesnice promenne - nutno zadat
  cisloKlavesnice = 0; // nastavte cislo klavesnice
  ttfs = 240; // sirka vykresleni tlacitek (displeje)
  ttfv = 320; // vyska vykresleni tlacitek spodni hrana (displeje)
  ptls = 3; // pocet tlacitek do sirky
  ptlv = 4; // počet tlacitek do vysky
  ob = 0; // oblouk rohu tlacitka
  m = 2; // mezera mezi tlacitky
  tv = 55; // vyska tlacitka
  poleX = 60; // pozice pole pro zobrazeni hodnot
  poleY = 30; // pozice pole pro zobrazeni hodnot
  poleD = 120; // delka pole pro zobrazeni hodnot
  poleV = 40; // pozice pole pro zobrazeni hodnot
  obPole = 0; // oblouk rohu pole pro zobrazeni hodnot
  TEXT_MAX = 6; // maximalni pocet znaku pole
  char* textTlacitka[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "End", "0", "OK"}; // text tlacitek
  int barvaTlacitka[] = {TFT_LIGHTGREY, TFT_LIGHTGREY, TFT_LIGHTGREY, // barva jednotlivych tlacitek
                         TFT_LIGHTGREY, TFT_LIGHTGREY, TFT_LIGHTGREY,
                         TFT_LIGHTGREY, TFT_LIGHTGREY, TFT_LIGHTGREY,
                         TFT_RED, TFT_LIGHTGREY, TFT_GREEN
                        };
  barvaPisma = TFT_BLACK; // barva pisma a pozadi
  barvaPozadi = TFT_WHITE; // barva pozadi
  barvaObrys = TFT_BLACK; // barva obrysu
  //------------------------------------------------------------------
  // vypocet a doplneni promennych
  int max_i = ptls * ptlv;
  int i;
  for (i = 0; i < max_i; i++) { // vyplneni textu tlacitek do globalni promenne
    textT[i] = textTlacitka[i];
  }
  for (i = 0; i < max_i; i++) { // vyplneni barvy tlacitek do globalni promenne
    barvaT[i] = barvaTlacitka[i];
  }
  //------------------------------------------------------------------
  // zobraz klavesnici
  tlacitka();
}
/***************************** KLAVESNICE ******************************

Sketch pro vytvoreni klavesnice, doplneni a ukladani hodnot pro dalsi zpracovani.

JEDNA KLAVESNICE
1) vyplnte prommene void klavesnice()
2) upravte void pole() podle toho co maji tlacitka vykonavat
3) upravte hodnotu #define MAX_POCET_TLACITEK ..

VICE KLAVESNIC
1) vyplnte prommene void klavesnice(), pro kazdou dalsi vytvorte void klavesnice1, 2, ...
2) nastavte promennou byte cisloKlavesnice 1, 2, ...
3) v casti void dotyk zmente pole(); na:

switch (cisloKlavesnice) {
case 0:
pole(); // pro klavesnici 0
break;
case 1; // pro klavesnici 1
pole1();
break;
case 2; // pro klavesnici 2 atd.
pole2();
break;
}

4) pro kazdou klavesnici vytvorte void pole1, 2, ...
nebo upravte konec bloku funkce podle zobrazene stranky
5) upravte hodnotu #define MAX_POCET_TLACITEK ..

Pro dalsi pouziti je urcena promenna textPole

*********** Preji prijemne uzivani bez nesrozumitelnych knihoven **********/

Program není dlouhý, ale když ho teď čtu, vůbec ty výpočty nechápu. Proto žádný smysluplný komentář. Myslím že není důležitý, prostě to funguje jak má, bez zbytečných překvapení. Často se k této klávesnici vracím.

Kreslíme obrázky

Nakreslit kulatá tlačítka se šipkou, sluníčko, měsíček není problém. Ale barevnou ikonu prostě nenakreslíte a když se o to pokusíte, stejně to nebude ono. Rád displeje obohacuji o ikony, které zobrazují stavy a současně jsou uloženy přímo v paměti Arduiona. Ono zobrazovat obrázky z karty SD, nebo jiné externí paměti, je totiž příšerně pomalé a práce s displejem pozbývá na radosti. Jestli nemáte zkušenosti se struct, toto bude složitější disciplína.

Pokud budete kreslit obrázky, začněte tím, že uložíte obrázek ve formátu BMP o 24 bit barevné hloubce a velikosti, kterou budete zobrazovat. V knihovně displeje ve složce Tools, otevřete program ImageConverter565.exe. Otevřete soubor, případně v poli Array Name změňte název. Ostatní pole nechte jak jsou. Stiskněte Save, a uložte kamkoli jinam než je adresář programu. Tím by příprava mohla skončit. Jinak ještě doporučuji otevřít soubor v textovém editoru a obsah souboru překopírovat do nového, který uložíte např. jako icons.h Tady je důležitá ta přípona. Každou další ikonu nakopírujte opět do tohoto souboru. Jenom až budete kopírovat, nechte #include <avr/pgmspace.h> pouze jednou. Doporučuji kopírovat i Hlavičku, pomůže Vám to při hledání a změně ikon.

A teď už vlastní program. Připomínám že používáme Arduino IDE. Do záhlaví programu si vložte #include "icons.h" a můžete i #include <avr/pgmspace.h>, nezapomeňte to ale vymazat ze souboru icons.h. Pak v nabídce Projekt vyberte Přidat soubor a potvrďte výběr, odklikněte případnou hlášku, zavřete a znovu otevřete program. Teď budete mít soubor v samostatné záložce. Pak stačí nahrát a zobrazit na displeji. Další obrázky už můžete vkládat přímo do záložky icons.h.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// cast pro zobrazeni ikon
#include "icons.h" // soubor s ikonami
#include <avr/pgmspace.h> // knihovna pro zpracovani obrazku (ikon)
#define BUFF_SIZE 20 // nastaveni velikosti bufferu pro zpracovani ikon
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime ikonu
  drawIcon(warning, 96, 136, 48, 48); // zobraz ikonu pozor
}
//------------------------------------------------------------------
void loop() {
  // hlavni smycku nechame prazdnou
}
//------------------------------------------------------------------
// funkce pro kresleni ikony
void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, int8_t height) {
  uint16_t  pix_buffer[BUFF_SIZE];
  tft.setAddrWindow(x, y, x + width - 1, y + height - 1);
  uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE;
  // kresleni obrazku
  for (int i = 0; i < nb; i++) {
    for (int j = 0; j < BUFF_SIZE; j++) {
      pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]);
    }
    tft.pushColors(pix_buffer, BUFF_SIZE);
  }
  uint16_t np = ((uint16_t)height * width) % BUFF_SIZE;
  if (np) {
    for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]);
    tft.pushColors(pix_buffer, np);
  }
}

Soubor icons.h ke stažení zde.

S obrázky v paměti FLASH pracujte opatrně. Kreslíme pár tlačítek, nic neděláme a stále se pohybujeme nad 50% paměti Flash. Obrázek je co bod to int, tedy 48x48 bodů = 2 304 bodů = 4 608 byt v paměti FLASH. UNO má celkem 32 256 byt. To ubývá opravdu rychle. Proto moje projekty s displejem často končí na Arduino MEGA.

Závěr:

Na Arduinu se mi líbí, že žádná cesta není špatně. Jenom některé z nich jsou kostrbatější. Programovat tlačítka můžete jak se Vám zachce. Počítání je dobré, když se předpokládá, že se displej za provozu bude otáčet. Osobně používám variantu struct, občas v kombinaci s výpočty a když kreslím textové klávesnice, tak variantu klávesnice. Struct má výhodu, že ušetříte spoustu místa a kód je přehledný.

Příště se podíváme na zobrazování teplot. Že je to triviální. Takto uchopený program pro čtení teplot nikde nenajdete.

JB

jaroslav.bohac@arduinotech.cz

Přidat komentář

Zvýrazněné položky jsou povinné.


TOP produkty

Arduino DUE

Arduino DUE
696 Kč s DPH

Arduinotech GSM shield

Arduinotech GSM shield
877 Kč s DPH

Kontakt

Ing. Petr Foltýn
Kunčice pod Ondřejníkem 814, 73913
TOPlist