ESP8266 + 2.8“TFT + Touch panel = základ pro malý HMI

TFTTouch2_webMeteostanice pro Jirky bude obsahovat grafický TFT displej pro zobrazování měřených hodnot a pro snadnější ovládání jsem navrhl i použití dotykového panelu. Jak já, tak Jirka jsme objednali z Číny vzorky – Jirka měl větší štěstí a panel mu přišel, zatímco já musel objednávat znovu. Pro urychlení vývoje mi ale Jirka svůj panel poslal, takže jsem mohl začít s rozhýbáním základních metod, které jsou nutné pro dosažení cíle. Vzhledem k omezenému počtu I/O pinů na ESP8266 jsme vybrali panel s SPI rozhraním jak pro TFT část, tak pro touch kontrolér. Toto rozhodnutí sice umožnilo připojení k ESP, ale současně vytvořilo některá úskalí, o kterých se více rozepíši v článku…

Že je možné displej takto k ESP připojit jsem věděl na základě pokusů odsud http://nailbuster.com/?page_id=341 takže něco do začátku jsem přece jen měl, ale po zapojení a odzkoušení jsem zjistil tragicky špatný výkon celé sestavy. Z důvodu maximálního kmitočtu hodin pro XPT2046 2MHz celé vykreslování probíhalo neuvěřitelně pomalu. Navíc jsem věděl o optimalizovaných Adafruit knihovnách, které mají větší výkon odsud http://www.instructables.com/id/Arduino-analogue-ring-meter-on-colour-TFT-display/, takže přišel čas na optimalizace. Původní Adafruit knihovna byla nahrazena knihovnou optimalizovanou, ovladač displeje s řadičem ILI9340 byl nahrazený optimalizovaným ovladačem s podporou transakcí, 16-ti bitovým přístupem na SPI (ani už si nepamatuji všechny změny, které jsem udělal…) a ovladač XPT2046 byl přepracovaný na transakce na SPI s omezením kmitočtu hodin na 2MHz.

Pro účely testování jsem původní dva příklady (kalibrace a jednoduchý Paint program) spojil do jednoho a přepracoval jej tak, aby byla možná aktualizace přes OTA. Výsledek vypadá takto:

TFTTouch_web

Čtení dotykového panelu probíhá na 2MHz a vykreslování pak na maximálním kmitočtu, kterého jsem byl schopen dosáhnout. Vše se zdá pracuje správně, ale jedna chyba se přece projevuje – občas se objeví rušení na vstupech touch řadiče a ten detekuje špatné souřadnice, ale tato situace se dá vyřešit digitální filtrací čtených informací. Vlastně jsem zjistil, že se dotykový panel zdaleka nemusí číst tak často a zbytečně ztrácím výkon, který můžu využít pro vykreslování…

Na závěr, jako obvykle, uvedu použité prostředí:

  • OS Linux Ubuntu Gnome
  • Arduino IDE 1.6.7
  • ESP8266 Core 2.1.0
  • V projektu je aktualizovaná knihovna WiFiConfig v poslední verzi s Captive portálem a ošetřeným přesměrováním, současně je použit HTML5 validátor pro zadávání NETBIOS/DNS jména zařízení a dále je doplněna možnost uživatelských parametrů při konfiguraci.

Těsně před odkazem na soubor ještě jedna informace – pro generování souboru pro stažení jsem zkusil použít funkci „Archivuj projekt“ v IDE, takže pokud archív obsahuje chyby, tak mi to napište do komentářů, abych je mohl odstranit.

 

Esphmi-160306c
Esphmi-160306c
esphmi-160306c.zip
27.8 KiB
305 Downloads
Details

35 komentářů u „ESP8266 + 2.8“TFT + Touch panel = základ pro malý HMI“

  1. Ahojte,

    narazil jsem na tuto stranku pri hledani odpovedi na muj problem, a tohle se mi zda uz byt oprapvdu tesne vedle. 🙂 Jsem naprosty amater, laik a nerad otravuju, nicmene i tak, bych se rad zeptal na jednu vec. Koupil jsem si stary Wemos D1 a k tomu mam displej od Cinana. http://www.aliexpress.com/item/2-8-inch-TFT-Touch-LCD-Screen-Display-Module-Forarduino-UNO-R3-HIGH-QUALITY-Free-Shipping/32272339922.html

    Displej jsem rozchodil na standardnim UNO bez problemu (tim samozrejme myslim po asi 6ti hodinach hledani 🙂 ), ale s WEMOS D1 mam problem. Nemohl by mi nekdo poradit, treba i ty, Pablo? Zda se mi, ze displej sam o sobe nema SPI rozhrani, nebo se mylim (rozhrani SPI je tam urcite pro SD kartu)? Jestli jsem to dobre pochopil, tak data si displej posila pres 8bitovou sbernici, jenze Wemos D1 nema zadny port/registr sdruzujici piny. Muj dotaz je, jestli je mozne tohle omezeni nejak obejit, nebo je to v pytli? Nebo jsem uplne mimo…?

    Jinak ta desticka Wemos D1 funguje jak fik, Wifi fakt krasne slape, ale ten displej k tomu, to by bylo dobry jak knedlo vepro.

    1. Ahoj. Ten displej má s největší pravděpodobností paralelní rozhraní. Technicky to řešitelný je, ale ne na Wemos D1, který nemá obsazené všechny vývody (a většina pinů ESP je zdvojená na konektoru Arduina),. Nouzově by to šlo vyřešit nějakým serial->paralel. převodníkem, třeba přes I2C PCF8574, nebo posuvným registrem, třeba HC595, ale rychlost bude žalostná a spíš se vyplatí investovat do SPI displeje.

  2. Ahoj, mám problém již při kompilaci … mi hlásí …
    esphmi:32: error: ‚Adafruit_GFX_Button‘ does not name a type

    ???

    Pomůže někdo ?

    Dík Marek

    1. Ahoj. Můj odhad je, že to je stará Adafruit knihovna, která ještě neměla třídu pro tlačítko… Mmnt, hledám řešení… Takže řešením je stáhnout knihovnu, která je odkazovaná v komentářích. Pak by překlad měl běžet bez potíží. Celý projekt je už dost starý – udělám aktualizaci, ale chvíli to zabere…
      Pavel

    1. No ale to je správně že. Displej se nainicializoval a nepřipojil se k žádné WiFi síti – je třeba se připojit k němu mobilem a připojit ho k domácí WiFi… Pak naběhne i OTA.

  3. Promiň, pokouším se, ale teď už píše trying connect …. a jinak nic i když jsem mu nastavil wifi síť …. pak se ještě objeví modrý kalibrační křížek … ale jinak na nic nereaguje … :

    1. Pokud se objeví kalibrační křížek, tak už se k WiFi připojil – ťukni na něj a měl by se objevit zase jinde (kalibrace dotykového panelu). Pokud nereaguje na dotyky, tak je problém v/s touch řadičem.

  4. No právě … V levo nahoře stále píše : Trying to connect …. pod tím je kalibrační křížek na který můžu ťukat jak chci a stále nic. Prostě ten touchscreen nemohu rozchodit … 🙁
    Zapojený to mám stejně jako Ty viz. odkazy …. 🙁 zkusím jeětě jiný displej, jdu pro něj do auta, ale pak už nevím … Marek

    1. No tak pak už jen klasika – osciloskop. Zkus prověřit, jestli chodí CS na Touch řadič a zbývající SPI signály. Pokud ano, tak si zkus napsat jednoduchý skript, který bude obsahovat jen obsluhu Touch řadiče – zavolej třeba begin a monitoruj isTouching – jakmile se dotkneš panelu, tak by mělo vyskočit přerušení. Nebo zkus vyčítat surová data pomocí getRaw – z toho všeho se dá usuzovat, v čem je problém. Do setup() napiš za wifi.begin(…) tohle tft.println("Connected.");, ať Tě nemate jen výpis, že se snaží připojit…

  5. Ahoj, bohužel nemám osciloskop, 🙁 pokusil jsem se napsat testovací skript, ale pořád nic ….. jsem v nějakém začarovaném kruhu …. už mě nic nenapadá …. Ale stejně díky za ochotu. Marek

  6. Tak jsem se pokusil o http://www.xpablo.cz/?wpfb_dl=27 ale nedaří se mi ani kompilace 🙁 [Arduino IDE 1.6.12]

    sketch/esphmi.ino.cpp.o:(.text.startup._GLOBAL__sub_I_nbns+0x8): undefined reference to Adafruit_ILI9340_AS8::Adafruit_ILI9340_AS8(signed char, signed char, signed char)'
    sketch/esphmi.ino.cpp.o:(.text.startup._GLOBAL__sub_I_nbns+0xc): undefined reference to
    XPT2046::XPT2046(unsigned char, unsigned char)‘
    sketch/esphmi.ino.cpp.o:(.text.startup._GLOBAL__sub_I_nbns+0x10): undefined reference to Adafruit_GFX_Button::Adafruit_GFX_Button()'
    sketch/esphmi.ino.cpp.o: In function
    __static_initialization_and_destruction_0′:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:29: undefined reference to Adafruit_ILI9340_AS8::Adafruit_ILI9340_AS8(signed char, signed char, signed char)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:30: undefined reference to
    XPT2046::XPT2046(unsigned char, unsigned char)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:30: undefined reference to Adafruit_GFX_Button::Adafruit_GFX_Button()'
    sketch/esphmi.ino.cpp.o:(.text._ZL14calibratePointttRtS_+0x8): undefined reference to
    Adafruit_ILI9340_AS8::drawFastHLine(short, short, short, unsigned short)‘
    sketch/esphmi.ino.cpp.o:(.text._ZL14calibratePointttRtS_+0xc): undefined reference to Adafruit_ILI9340_AS8::drawFastVLine(short, short, short, unsigned short)'
    sketch/esphmi.ino.cpp.o:(.text._ZL14calibratePointttRtS_+0x10): undefined reference to
    NBNS::poll()‘
    sketch/esphmi.ino.cpp.o:(.text._ZL14calibratePointttRtS_+0x18): undefined reference to XPT2046::getRaw(unsigned short&, unsigned short&, XPT2046::adc_ref_t, unsigned char) const'
    sketch/esphmi.ino.cpp.o: In function
    calibratePoint‘:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:61: undefined reference to Adafruit_ILI9340_AS8::drawFastHLine(short, short, short, unsigned short)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:64: undefined reference to
    Adafruit_ILI9340_AS8::drawFastVLine(short, short, short, unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:64: undefined reference to NBNS::poll()'
    sketch/esphmi.ino.cpp.o: In function
    XPT2046::isTouching() const‘:
    sketch/lib/XPT2046_T/XPT2046_T.h:26: undefined reference to XPT2046::getRaw(unsigned short&, unsigned short&, XPT2046::adc_ref_t, unsigned char) const'
    sketch/esphmi.ino.cpp.o: In function
    calibratePoint‘:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:69: undefined reference to Adafruit_ILI9340_AS8::drawFastHLine(short, short, short, unsigned short)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:69: undefined reference to
    Adafruit_ILI9340_AS8::drawFastVLine(short, short, short, unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:72: undefined reference to XPT2046::getCalibrationPoints(unsigned short&, unsigned short&, unsigned short&, unsigned short&)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:72: undefined reference to
    XPT2046::setCalibration(unsigned short, unsigned short, unsigned short, unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:73: undefined reference to Adafruit_GFX_AS8::setTextColor(unsigned short)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:73: undefined reference to
    Adafruit_GFX_AS8::setTextSize(unsigned char)‘
    sketch/esphmi.ino.cpp.o:(.text._Z9calibratev+0x2c): undefined reference to XPT2046::getCalibrationPoints(unsigned short&, unsigned short&, unsigned short&, unsigned short&)'
    sketch/esphmi.ino.cpp.o: In function
    calibrate()‘:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:78: undefined reference to XPT2046::setCalibration(unsigned short, unsigned short, unsigned short, unsigned short)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:79: undefined reference to
    Adafruit_GFX_AS8::setTextColor(unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:80: undefined reference to Adafruit_GFX_AS8::setTextSize(unsigned char)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:82: undefined reference to
    Adafruit_GFX_AS8::setTextSize(unsigned char)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:90: undefined reference to WiFiDeviceName'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:92: undefined reference to
    Adafruit_GFX_AS8::width()‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:92: undefined reference to Adafruit_GFX_AS8::height()'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:93: undefined reference to
    XPT2046::begin(unsigned short, unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:93: undefined reference to Adafruit_ILI9340_AS8::begin()'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:93: undefined reference to
    Adafruit_ILI9340_AS8::fillScreen(unsigned short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:94: undefined reference to WiFiConfig::begin(int, unsigned char, void (*)(wificonfigstate_t))'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:94: undefined reference to
    NBNS::begin(char const*)‘
    sketch/esphmi.ino.cpp.o:(.text.setup+0x54): undefined reference to Adafruit_GFX_Button::initButton(Adafruit_GFX_AS8*, short, short, unsigned char, unsigned char, unsigned short, unsigned short, unsigned short, char*, unsigned char)'
    sketch/esphmi.ino.cpp.o:(.text.setup+0x58): undefined reference to
    Adafruit_GFX_Button::drawButton(unsigned char)‘
    sketch/esphmi.ino.cpp.o:(.text.setup+0x88): undefined reference to Adafruit_GFX_AS8::width()'
    sketch/esphmi.ino.cpp.o:(.text.setup+0x92): undefined reference to
    Adafruit_GFX_AS8::height()‘
    sketch/esphmi.ino.cpp.o:(.text.setup+0xa1): undefined reference to XPT2046::begin(unsigned short, unsigned short)'
    sketch/esphmi.ino.cpp.o:(.text.setup+0xa9): undefined reference to
    Adafruit_ILI9340_AS8::begin()‘
    sketch/esphmi.ino.cpp.o:(.text.setup+0xb3): undefined reference to Adafruit_ILI9340_AS8::fillScreen(unsigned short)'
    sketch/esphmi.ino.cpp.o:(.text.setup+0xbe): undefined reference to
    Adafruit_GFX_AS8::setTextColor(unsigned short)‘
    sketch/esphmi.ino.cpp.o: In function setup':
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:99: undefined reference to
    WiFiConfig::begin(int, unsigned char, void (*)(wificonfigstate_t))‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:102: undefined reference to NBNS::begin(char const*)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:118: undefined reference to
    Adafruit_GFX_Button::initButton(Adafruit_GFX_AS8*, short, short, unsigned char, unsigned char, unsigned short, unsigned short, unsigned short, char*, unsigned char)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:118: undefined reference to Adafruit_GFX_Button::drawButton(unsigned char)'
    sketch/esphmi.ino.cpp.o: In function
    function‘:
    /Users/jt/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/functional:2452: undefined reference to XPT2046::getPosition(unsigned short&, unsigned short&, XPT2046::adc_ref_t, unsigned char) const'
    sketch/esphmi.ino.cpp.o: In function
    setup‘:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:142: undefined reference to Adafruit_ILI9340_AS8::drawPixel(short, short, unsigned short)'
    sketch/esphmi.ino.cpp.o: In function
    function‘:
    /Users/jt/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/functional:2453: undefined reference to Adafruit_GFX_Button::contains(short, short)'
    sketch/esphmi.ino.cpp.o: In function
    setup‘:
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:142: undefined reference to Adafruit_GFX_Button::press(unsigned char)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:142: undefined reference to
    Adafruit_GFX_Button::justReleased()‘
    sketch/esphmi.ino.cpp.o: In function ~function':
    /Users/jt/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/functional:2174: undefined reference to
    Adafruit_GFX_Button::justPressed()‘
    sketch/esphmi.ino.cpp.o: In function setup':
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:148: undefined reference to
    NBNS::poll()‘
    sketch/esphmi.ino.cpp.o: In function loop':
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:149: undefined reference to
    XPT2046::getPosition(unsigned short&, unsigned short&, XPT2046::adc_ref_t, unsigned char) const‘
    sketch/esphmi.ino.cpp.o: In function XPT2046::isTouching() const':
    /Users/jt/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/bits/unique_ptr.h:67: undefined reference to
    Adafruit_ILI9340_AS8::drawPixel(short, short, unsigned short)‘
    sketch/esphmi.ino.cpp.o: In function loop':
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:168: undefined reference to
    Adafruit_GFX_Button::contains(short, short)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:168: undefined reference to Adafruit_GFX_Button::press(unsigned char)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:168: undefined reference to
    Adafruit_GFX_Button::justReleased()‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:171: undefined reference to Adafruit_ILI9340_AS8::fillScreen(unsigned short)'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:175: undefined reference to
    Adafruit_GFX_Button::drawButton(unsigned char)‘
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:178: undefined reference to Adafruit_GFX_Button::justPressed()'
    /Users/jt/Documents/Arduino-2/xpablo.cz/esphmi/esphmi.ino:178: undefined reference to
    Adafruit_GFX_Button::drawButton(unsigned char)‘
    collect2: error: ld returned 1 exit status
    exit status 1
    Error compiling for board NodeMCU 0.9 (ESP-12 Module).

    1. Vyřešeno: Přiližené knihovny z adresáře lib/ je třeba zkopírovat přímo do Arduino/libraries a adekvátně změnit příslušné #include nějak takto:

      #include „espnbns.h“
      #include „Adafruit_ILI9340_AS8.h“
      #include „Adafruit_GFX_AS8.h“
      #include „XPT2046_T.h“
      #include „WiFiConfig.h“ // WiFiConfig xpablo.cz

    1. Verzi vždycky uvádím v článku… Zítra odpoledne za mnou přijede Jirka, o kterém se občas zmiňuji v souvislosti s meteostanicí, právě pro displej, takže se na to kouknu a dám vědět.

  7. Zdravím všechny, super návod, díky. Měl bych ale dotaz, je nějaký způsob jak u displeje měnit jas/kontrast? Předpokládám použití foto resistoru, ale chybí mi to základní, jestli existují příkazy jak jas/kontrast displeji nastavit.

    Předem díky moc.
    Lukas

    1. Bohužel – kontrast by (snad) mohl jít nastavit zápisem do registru VCM control (0xc5 – doporučuji přečíst datasheet), ale jas by vyžadoval PWM výstup pro řízení podsvitu a na to už mi nevyšla GPIO noha. Jedinou možností, která mě napadá je, pokud není potřeba sériový port, použít vývod TXD, nebo RXD pro řízení intenzity podsvitu. Nejlépe asi předělat zapojení – GPIO5 použít jako řízení podsvícení a RXD použít pro T_IRQ… Ovšem to chce vyzkoušet!

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *