ESP32 eInk T5 2.13 on MicroPython
-
Hello,
I bought this one last week, but the seller didnt send me examples or documentation about.
I would like to use with MicroPython to display geolocation data.
Could anyone please share with me libraries or details which am I able to develop things with?I tried use some code from internet like:
https://www.good-display.com/product/375.html
https://github.com/mcauser/micropython-waveshare-epaper/issues/5
Here is following photos about the board.
Merry Christmas!
-
Unfortunatelly, I could not work with the example:
https://github.com/Xinyuan-LilyGO/T5-Ink-Screen-SeriesLibraries conflicts, and another issues happening during the tests
-
@fdaher Remember this example was made on C++
-
After search on Lilygo Github repo, I tried run the "Hello word" and I got this output on Serial Monitor.
I'm using the controller:
#include <GxDEPG0213BN/GxDEPG0213BN.h>[ 4947][E][esp32-hal-cpu.c:107] addApbChangeCallback(): duplicate func=400DABC8 arg=3FFBDD08
[ 5248][W][sd_diskio.cpp:104] sdWait(): Wait Failed
[ 5248][E][sd_diskio.cpp:126] sdSelectCard(): Select Failed
[ 5248][W][sd_diskio.cpp:510] ff_sd_initialize(): GO_IDLE_STATE failed
[ 5253][E][sd_diskio.cpp:795] sdcard_mount(): f_mount failed: (3) The physical drive cannot work
[ 5562][W][sd_diskio.cpp:104] sdWait(): Wait Failed
[ 5562][E][sd_diskio.cpp:126] sdSelectCard(): Select Failed
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.Core 1 register dump:
PC : 0x400d3330 PS : 0x00060030 A0 : 0x800d33ad A1 : 0x3ffb26a0
A2 : 0x3ffc2fb8 A3 : 0x0000001a A4 : 0x00000040 A5 : 0x00000000
A6 : 0x00000001 A7 : 0x80000001 A8 : 0x00000017 A9 : 0xffffffff
A10 : 0x0000ffff A11 : 0x3ffb27ec A12 : 0x00000000 A13 : 0x00000000
A14 : 0xf913be73 A15 : 0x3f500000 SAR : 0x0000001a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000018 LBEG : 0x4008a7a9 LEND : 0x4008a7b9 LCOUNT : 0xfffffffeBacktrace:0x400d332d:0x3ffb26a00x400d33aa:0x3ffb26c0 0x400d3039:0x3ffb26e0 0x400d30f8:0x3ffb2700 0x400d317f:0x3ffb2720 0x401481d1:0x3ffb2740 0x401481f6:0x3ffb2760 0x400db625:0x3ffb2780 0x400d2b49:0x3ffb27a0 0x400dbea2:0x3ffb2820
ELF file SHA256: 0000000000000000
My code:
/* LilyGo Ink Screen Series Test - Created by Lewis he */ // According to the board, cancel the corresponding macro definition #define LILYGO_T5_V213 // #define LILYGO_T5_V22 // #define LILYGO_T5_V24 // #define LILYGO_T5_V28 // #define LILYGO_T5_V102 // #define LILYGO_T5_V266 // #define LILYGO_EPD_DISPLAY //T-Display 1.02 inch epaper //Depend https://github.com/adafruit/Adafruit_NeoPixel // #define LILYGO_EPD_DISPLAY_154 #include <boards.h> #include <GxEPD.h> #include <SD.h> #include <FS.h> //GDEQ0213B74 // #include <GxGDGDEW0102T4/GxGDGDEW0102T4.h> //1.02" b/w // #include <GxGDEW0154Z04/GxGDEW0154Z04.h> // 1.54" b/w/r 200x200 // #include <GxGDEW0154Z17/GxGDEW0154Z17.h> // 1.54" b/w/r 152x152 // #include <GxGDEH0154D67/GxGDEH0154D67.h> // 1.54" b/w // #include <GxDEPG0150BN/GxDEPG0150BN.h> // 1.51" b/w form DKE GROUP // #include <GxDEPG0266BN/GxDEPG0266BN.h> // 2.66" b/w form DKE GROUP // #include <GxDEPG0290R/GxDEPG0290R.h> // 2.9" b/w/r form DKE GROUP // #include <GxDEPG0290B/GxDEPG0290B.h> // 2.9" b/w form DKE GROUP // #include <GxGDEW029Z10/GxGDEW029Z10.h> // 2.9" b/w/r form GoodDisplay // #include <GxGDEW0213Z16/GxGDEW0213Z16.h> // 2.13" b/w/r form GoodDisplay // #include <GxGDE0213B1/GxGDE0213B1.h> // 2.13" b/w old panel , form GoodDisplay // #include <GxGDEH0213B72/GxGDEH0213B72.h> // 2.13" b/w old panel , form GoodDisplay // #include <GxGDEH0213B73/GxGDEH0213B73.h> // 2.13" b/w old panel , form GoodDisplay // #include <GxGDEM0213B74/GxGDEM0213B74.h> // 2.13" b/w form GoodDisplay 4-color // #include <GxGDEW0213M21/GxGDEW0213M21.h> // 2.13" b/w Ultra wide temperature , form GoodDisplay #include <GxDEPG0213BN/GxDEPG0213BN.h> // 2.13" b/w form DKE GROUP // #include <GxGDEW027W3/GxGDEW027W3.h> // 2.7" b/w form GoodDisplay // #include <GxGDEW027C44/GxGDEW027C44.h> // 2.7" b/w/r form GoodDisplay // #include <GxGDEH029A1/GxGDEH029A1.h> // 2.9" b/w form GoodDisplay // #include <GxDEPG0750BN/GxDEPG0750BN.h> // 7.5" b/w form DKE GROUP #include GxEPD_BitmapExamples // FreeFonts from Adafruit_GFX #include <Fonts/FreeMonoBold9pt7b.h> #include <Fonts/FreeMonoBold12pt7b.h> #include <Fonts/FreeMonoBold18pt7b.h> #include <Fonts/FreeMonoBold24pt7b.h> #include <GxIO/GxIO_SPI/GxIO_SPI.h> #include <GxIO/GxIO.h> #include <WiFi.h> GxIO_Class io(SPI, EPD_CS, EPD_DC, EPD_RSET); GxEPD_Class display(io, EPD_RSET, EPD_BUSY); #if defined(_HAS_SDCARD_) && !defined(_USE_SHARED_SPI_BUS_) SPIClass SDSPI(VSPI); #endif #if defined(_GxGDEW0213Z16_H_) || defined(_GxGDEW029Z10_H_) || defined(_GxGDEW027C44_H_) ||defined(_GxGDEW0154Z17_H_) || defined(_GxGDEW0154Z04_H_) || defined(_GxDEPG0290R_H_) #define _HAS_COLOR_ #endif #if defined(LILYGO_EPD_DISPLAY) Adafruit_NeoPixel strip(RGB_STRIP_COUNT, RGB_STRIP_PIN, NEO_GRBW + NEO_KHZ800); #endif /*LILYGO_EPD_DISPLAY_102*/ void showFont(const char name[], const GFXfont *f); void drawCornerTest(void); bool setupSDCard(void) { #if defined(_HAS_SDCARD_) && !defined(_USE_SHARED_SPI_BUS_) SDSPI.begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI); return SD.begin(SDCARD_CS, SDSPI); #elif defined(_HAS_SDCARD_) return SD.begin(SDCARD_CS); #endif return false; } void testSpeaker() { #if defined(_HAS_SPEAKER_) #ifdef _HAS_PWR_CTRL_ pinMode(SPK_POWER_EN, OUTPUT); digitalWrite(SPK_POWER_EN, HIGH); #endif ledcSetup(LEDC_CHANNEL_0, 1000, 8); ledcAttachPin(SPERKER_PIN, LEDC_CHANNEL_0); int i = 3; while (i--) { ledcWriteTone(LEDC_CHANNEL_0, 1000); delay(200); ledcWriteTone(LEDC_CHANNEL_0, 0); } #ifdef _HAS_PWR_CTRL_ pinMode(SPK_POWER_EN, INPUT); #endif ledcDetachPin(SPERKER_PIN); #endif } void testWiFi() { WiFi.mode(WIFI_STA); WiFi.disconnect(); // WiFi.scanNetworks will return the number of networks found int n = WiFi.scanNetworks(); Serial.println("scan done"); if (n == 0) { Serial.println("no networks found"); } else { Serial.print(n); Serial.println(" networks found"); for (int i = 0; i < n; ++i) { // Print SSID and RSSI for each network found Serial.print(i + 1); Serial.print(": "); Serial.print(WiFi.SSID(i)); Serial.print(" ("); Serial.print(WiFi.RSSI(i)); Serial.print(")"); Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*"); delay(10); } } Serial.println(""); } void setup() { bool rlst = false; Serial.begin(115200); Serial.println(); Serial.println("setup"); #if defined(LILYGO_EPD_DISPLAY) pinMode(EPD_POWER_ENABLE, OUTPUT); digitalWrite(EPD_POWER_ENABLE, HIGH); delay(50); // strip test strip.begin(); strip.show(); strip.setBrightness(200); int i = 0; while (i < 5) { uint32_t color[] = {0xFF0000, 0x00FF00, 0x0000FF, 0x000000}; strip.setPixelColor(0, color[i]); strip.show(); delay(1000); i++; } strip.setPixelColor(0, 0); strip.show(); #endif /*LILYGO_EPD_DISPLAY*/ #if defined(LILYGO_EPD_DISPLAY_102) pinMode(EPD_POWER_ENABLE, OUTPUT); digitalWrite(EPD_POWER_ENABLE, HIGH); #endif /*LILYGO_EPD_DISPLAY_102*/ #if defined(LILYGO_T5_V102) pinMode(POWER_ENABLE, OUTPUT); digitalWrite(POWER_ENABLE, HIGH); #endif /*LILYGO_T5_V102*/ SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI); display.init(); display.setTextColor(GxEPD_BLACK); testSpeaker(); testWiFi(); rlst = setupSDCard(); display.setRotation(0); display.fillScreen(GxEPD_WHITE); #if defined(_HAS_COLOR_) display.drawExampleBitmap(BitmapExample1, 0, 0, GxEPD_WIDTH, GxEPD_HEIGHT, GxEPD_RED); #else display.drawExampleBitmap(BitmapExample1, 0, 0, GxEPD_WIDTH, GxEPD_HEIGHT, GxEPD_BLACK); #endif #if defined(_HAS_SDCARD_) display.setRotation(1); #if defined(LILYGO_T5_V102) display.setCursor(5, display.height() - 15); #else display.setCursor(20, display.height() - 15); #endif String sizeString = "SD:" + String(SD.cardSize() / 1024.0 / 1024.0 / 1024.0) + "G"; display.println(rlst ? sizeString : "SD:N/A"); int16_t x1, x2; uint16_t w, h; String str = GxEPD_BitmapExamplesQ; str = str.substring(2, str.lastIndexOf("/")); display.getTextBounds(str, 0, 0, &x1, &x2, &w, &h); display.setCursor(display.width() - w - 5, display.height() - 15); display.println(str); #endif display.update(); delay(1000); } void loop() { drawCornerTest(); int i = 0; while (i < 4) { display.setRotation(i); showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b); //showFont("FreeMonoBold18pt7b", &FreeMonoBold18pt7b); //showFont("FreeMonoBold24pt7b", &FreeMonoBold24pt7b); i++; } display.fillScreen(GxEPD_WHITE); display.update(); display.powerDown(); esp_sleep_enable_ext1_wakeup(((uint64_t)(((uint64_t)1) << BUTTON_1)), ESP_EXT1_WAKEUP_ALL_LOW); esp_deep_sleep_start(); } void showFont(const char name[], const GFXfont *f) { display.fillScreen(GxEPD_WHITE); display.setTextColor(GxEPD_BLACK); display.setFont(f); display.setCursor(0, 0); display.println(); display.println(name); display.println(" !\"#$%&'()*+,-./"); display.println("0123456789:;<=>?"); display.println("@ABCDEFGHIJKLMNO"); display.println("PQRSTUVWXYZ[\]^_"); display.println("`abcdefghijklmno"); display.println("pqrstuvwxyz{|}~ "); display.update(); delay(5000); } void drawCornerTest() { display.drawCornerTest(); delay(5000); uint8_t rotation = display.getRotation(); for (uint16_t r = 0; r < 4; r++) { display.setRotation(r); display.fillScreen(GxEPD_WHITE); display.fillRect(0, 0, 8, 8, GxEPD_BLACK); display.fillRect(display.width() - 18, 0, 16, 16, GxEPD_BLACK); display.fillRect(display.width() - 25, display.height() - 25, 24, 24, GxEPD_BLACK); display.fillRect(0, display.height() - 33, 32, 32, GxEPD_BLACK); display.update(); delay(5000); } display.setRotation(rotation); // restore }
-
Demo Lib from github:
from micropython import const from machine import SPI, Pin from time import sleep_ms import ustruct # Display resolution EPD_WIDTH = const(250) EPD_HEIGHT = const(122) # datasheet says 250x122 (increased to 128 to be multiples of 8) # Display commands DRIVER_OUTPUT_CONTROL = const(0x01) # Gate Driving Voltage Control 0x03 # Source Driving voltage Control 0x04 BOOSTER_SOFT_START_CONTROL = const(0x0C) # not in datasheet #GATE_SCAN_START_POSITION = const(0x0F) # not in datasheet DEEP_SLEEP_MODE = const(0x10) DATA_ENTRY_MODE_SETTING = const(0x11) #SW_RESET = const(0x12) #TEMPERATURE_SENSOR_CONTROL = const(0x1A) MASTER_ACTIVATION = const(0x20) #DISPLAY_UPDATE_CONTROL_1 = const(0x21) DISPLAY_UPDATE_CONTROL_2 = const(0x22) # Panel Break Detection 0x23 WRITE_RAM = const(0x24) WRITE_VCOM_REGISTER = const(0x2C) # Status Bit Read 0x2F WRITE_LUT_REGISTER = const(0x32) SET_DUMMY_LINE_PERIOD = const(0x3A) SET_GATE_TIME = const(0x3B) #BORDER_WAVEFORM_CONTROL = const(0x3C) SET_RAM_X_ADDRESS_START_END_POSITION = const(0x44) SET_RAM_Y_ADDRESS_START_END_POSITION = const(0x45) SET_RAM_X_ADDRESS_COUNTER = const(0x4E) SET_RAM_Y_ADDRESS_COUNTER = const(0x4F) TERMINATE_FRAME_READ_WRITE = const(0xFF) # not in datasheet, aka NOOP class EPD: def __init__(self): self.spi = SPI(2, baudrate=20000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(17)) self.spi.init() dc = Pin(17) cs = Pin(5) rst = Pin(16) self.cs = cs self.dc = dc self.rst = rst #self.busy = busy self.cs.init(self.cs.OUT, value=1) self.dc.init(self.dc.OUT, value=0) self.rst.init(self.rst.OUT, value=0) self.width = EPD_WIDTH self.height = EPD_HEIGHT self.size = self.width * self.height // 8 self.buf = bytearray(self.size) LUT_FULL_UPDATE = bytearray(b'\x80\x60\x40\x00\x00\x00\x00\x10\x60\x20\x00\x00\x00\x00\x80\x60\x40\x00\x00\x00\x00\x10\x60\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00\x02\x09\x09\x00\x00\x02\x03\x03\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x41\xA8\x32\x30\x0A') LUT_PARTIAL_UPDATE = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x41\xA8\x32\x30\x0A') def clearBuffer(self): self._command(b'\x24') for i in range(0, len(self.buf)): self.buf[i] = 255 self._data(bytearray([self.buf[i]])) def displayBuffer(self, buf): self._command(b'\x24') for i in range(0, len(buf)): self._data(bytearray([buf[i]])) self._command(b'\x22') self._command(b'\xC7') self._command(b'\x20') self._command(bytearray([TERMINATE_FRAME_READ_WRITE])) self.wait_until_idle() def _command(self, command, data=None): self.cs(1) # according to LOLIN_EPD self.dc(0) self.cs(0) self.spi.write(command) self.cs(1) if data is not None: self._data(data) def _data(self, data): self.cs(1) # according to LOLIN_EPD self.dc(1) self.cs(0) self.spi.write(data) self.cs(1) def init(self): self.reset() self.wait_until_idle(); self._command(b'\x12'); # soft reset self.wait_until_idle(); self._command(b'\x74', b'\x54'); #set analog block control self._command(b'\x7E', b'\x3B'); #set digital block control self._command(b'\x01', b'\xF9\x00\x00'); #Driver output control self._command(b'\x11', b'\x01'); #data entry mode #set Ram-X address start/end position self._command(b'\x44', b'\x00\x0F'); #0x0C-->(15+1)*8=128 #set Ram-Y address start/end position self._command(b'\x45', b'\xF9\x00\x00\x00'); # 0xF9-->(249+1)=250 self._command(b'\x3C', b'\x03'); # BorderWavefrom self._command(b'\x2C', b'\x55'); # VCOM Voltage self._command(b'\x03', bytes([self.LUT_FULL_UPDATE[70]])); # ?? self._command(b'\x04') self._data(bytes([self.LUT_FULL_UPDATE[71]])); # ?? self._data(bytes([self.LUT_FULL_UPDATE[72]])); # ?? self._data(bytes([self.LUT_FULL_UPDATE[73]])); # ?? self._command(b'\x3A', bytes([self.LUT_FULL_UPDATE[74]])); # Dummy Line self._command(b'\x3B', bytes([self.LUT_FULL_UPDATE[75]])); # Gate time self.set_lut(self.LUT_FULL_UPDATE) self._command(b'\x4E', b'\x00'); # set RAM x address count to 0; self._command(b'\x4F', b'\xF9\x00'); # set RAM y address count to 0X127; self.wait_until_idle() def wait_until_idle(self): sleep_ms(1000) def reset(self): self.rst(1) sleep_ms(1) self.rst(0) sleep_ms(10) self.rst(1) def set_lut(self, lut): self._command(bytearray([WRITE_LUT_REGISTER]), lut) # put an image in the frame memory def set_frame_memory(self, image, x, y, w, h): # x point must be the multiple of 8 or the last 3 bits will be ignored x = x & 0xF8 w = w & 0xF8 if (x + w >= self.width): x_end = self.width - 1 else: x_end = x + w - 1 if (y + h >= self.height): y_end = self.height - 1 else: y_end = y + h - 1 self.set_memory_area(x, y, x_end, y_end) self.set_memory_pointer(x, y) self._command(bytearray([WRITE_RAM]), image) # replace the frame memory with the specified color def clear_frame_memory(self, color): self.set_memory_area(0, 0, self.width - 1, self.height - 1) self.set_memory_pointer(0, 0) self._command(bytearray([WRITE_RAM])) # send the color data for i in range(0, (self.width * self.height)//8): self._data(bytearray([color])) # draw the current frame memory and switch to the next memory area def display_frame(self): self._command(bytearray([DISPLAY_UPDATE_CONTROL_2]), b'\xC7') self._command(bytearray([MASTER_ACTIVATION])) self._command(bytearray([TERMINATE_FRAME_READ_WRITE])) self.wait_until_idle() # specify the memory area for data R/W def set_memory_area(self, x_start, y_start, x_end, y_end): self._command(bytearray([SET_RAM_X_ADDRESS_START_END_POSITION])) # x point must be the multiple of 8 or the last 3 bits will be ignored self._data(bytearray([(x_start >> 3) & 0xFF])) self._data(bytearray([(x_end >> 3) & 0xFF])) self._command(bytearray([SET_RAM_Y_ADDRESS_START_END_POSITION]), ustruct.pack("<HH", y_start, y_end)) # specify the start point for data R/W def set_memory_pointer(self, x, y): self._command(bytearray([SET_RAM_X_ADDRESS_COUNTER])) # x point must be the multiple of 8 or the last 3 bits will be ignored self._data(bytearray([(x >> 3) & 0xFF])) self._command(bytearray([SET_RAM_Y_ADDRESS_COUNTER]), ustruct.pack("<H", y)) self.wait_until_idle() # to wake call reset() or init() def sleep(self): self._command(bytearray([DEEP_SLEEP_MODE])) self.wait_until_idle()
main.py (just for run):
import epaper2in13 e = epaper2in13.EPD() e.init() e.clearBuffer() import framebuf buf = bytearray(128 * 250 // 8) fb = framebuf.FrameBuffer(buf, 128, 250, framebuf.MONO_HLSB) black = 0 white = 1 fb.fill(white) #fb.text('Hello World',30,30,black) for i in range(1,50): fb.pixel(i,i,0) e.displayBuffer(buf)
-
Hello everyone,
I could run using Waveshare lib!!
Thank you so much!! -