合宙ESP32C3点亮1.54寸墨水屏
本帖最后由 topdog 于 2022-8-18 07:23 编辑这款墨水屏型号是GDEP015OC1。
e ink outdoor display,Anti UV display,(Out of Stock)1.54 inch e-paper display anti-ultraviolet (e-paper-display.com)
GxEPD2库显示GDEP015OC1不再可用,这款亚马逊已经下架。
GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEP015OC1 no longer available
1,安装的库文件:
2,接线:
Eink ESP32C3
GND GND
VCC 3.3V
SCL GPIO2
SDA GPIO3
RES GPIO10
DC GPIO6
CS GPIO7
BUSY GPIO8
3,程序如下:
(1)显示库图片和文字。
// include library, include base class, make path known
#include <GxEPD.h>
// select the display class to use, only one
#include <GxGDEP015OC1/GxGDEP015OC1.h> // 1.54" b/w
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
// FreeFonts from Adafruit_GFX
#include <Fonts/FreeMonoBold9pt7b.h>
#include GxEPD_BitmapExamples
const int Eink_SCL =2;
const int Eink_SDA =3;
const int Eink_RES =10;
const int Eink_DC =6;
const int Eink_CS =7;
const int Eink_BUSY =8;
SPIClass EinkSPI(SPI);
GxIO_Class io(EinkSPI, /*CS=5*/ Eink_CS, /*DC=*/Eink_DC, /*RST=*/ Eink_RES); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ Eink_RES, /*BUSY=*/Eink_BUSY); // arbitrary selection of (16), 4
//#define DEMO_DELAY 3*60 // seconds
//#define DEMO_DELAY 1*60 // seconds
#define DEMO_DELAY 2
void setup(void)
{
Serial.begin(115200);
EinkSPI.begin(Eink_SCL ,-1, Eink_SDA, Eink_CS);
Serial.println();
Serial.println("setup");
display.init(115200); // enable diagnostic output on Serial
Serial.println("setup done");
}
void loop()
{
display.drawExampleBitmap(BitmapExample1, sizeof(BitmapExample1));
delay(DEMO_DELAY * 100);
display.drawPaged(showFontCallback);
display.powerDown();
delay(DEMO_DELAY * 100);
}
void showFontCallback()
{
const char* name = "FreeMonoBold9pt7b";
const GFXfont* f = &FreeMonoBold9pt7b;
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{|}~ ");
}
(2)显示下载的网络图片
// include library, include base class, make path known
#include <GxEPD.h>
// select the display class to use, only one
#include <GxGDEP015OC1/GxGDEP015OC1.h> // 1.54" b/w
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
const int Eink_SCL =2;
const int Eink_SDA =3;
const int Eink_RES =10;
const int Eink_DC =6;
const int Eink_CS =7;
const int Eink_BUSY =8;
SPIClass EinkSPI(SPI);
GxIO_Class io(EinkSPI, /*CS=5*/ Eink_CS, /*DC=*/Eink_DC, /*RST=*/ Eink_RES); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ Eink_RES, /*BUSY=*/Eink_BUSY); // arbitrary selection of (16), 4
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
const char* ssid = "你的WiFi";
const char* password = "你的password";
const int httpPort= 80;
const int httpsPort = 443;
const char* fp_api_github_com = "df b2 29 c6 a6 38 1a 59 9d c9 ad 92 2d 26 f5 3c 83 8f a5 87"; // as of 25.11.2020
const char* fp_github_com = "5f 3f 7a c2 56 9f 50 a4 66 76 47 c6 a1 8c a0 07 aa ed bb 8e"; // as of 25.11.2020
const char* fp_rawcontent = "8F 0E 79 24 71 C5 A7 D2 A7 46 76 30 C1 3C B7 2A 13 B0 01 B2"; // as of 29.7.2022
const char* certificate_rawcontent =
"-----BEGIN CERTIFICATE-----\n"
"MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD"
"QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS"
"U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC"
"AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a"
"qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn"
"g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW"
"raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB"
"Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r"
"eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB"
"/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU"
"A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG"
"CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG"
"GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh"
"Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV"
"HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH"
"bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB"
"MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB"
"AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z"
"ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h"
"qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC"
"EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6"
"ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E"
"A7sKPPcw7+uvTPyLNhBzPvOk\n"
"-----END CERTIFICATE-----\n";
const char* host_rawcontent = "raw.githubusercontent.com";
const char* path_rawcontent = "/ZinggJM/GxEPD2/master/extras/bitmaps/";
const char* path_prenticedavid = "/prenticedavid/MCUFRIEND_kbv/master/extras/bitmaps/";
const char* path_waveshare_c= "/waveshare/e-Paper/master/RaspberryPi_JetsonNano/c/pic/";
const char* path_waveshare_py = "/waveshare/e-Paper/master/RaspberryPi_JetsonNano/python/pic/";
void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color = true);
void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color = true,
const char* certificate = certificate_rawcontent);
void setup()
{
Serial.begin(115200);
EinkSPI.begin(Eink_SCL ,-1, Eink_SDA, Eink_CS);
Serial.println();
Serial.println("GxEPD_WiFi_Example");
display.init(115200);
if (!WiFi.getAutoConnect() || ( WiFi.getMode() != WIFI_STA) || ((WiFi.SSID() != ssid) && String(ssid) != "........"))
{
Serial.println();
Serial.print("WiFi.getAutoConnect()=");
Serial.println(WiFi.getAutoConnect());
Serial.print("WiFi.SSID()=");
Serial.println(WiFi.SSID());
WiFi.mode(WIFI_STA); // switch off AP
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
}
int ConnectTimeout = 30; // 15 seconds
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
Serial.print(WiFi.status());
if (--ConnectTimeout <= 0)
{
Serial.println();
Serial.println("WiFi connect timeout");
return;
}
}
Serial.println();
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
drawBitmaps_200x200();
drawBitmaps_other();
Serial.println("GxEPD_WiFi_Example done");
}
void loop(void)
{
}
void drawBitmaps_200x200()
{
int16_t x = (display.width() - 200) / 2;
int16_t y = (display.height() - 200) / 2;
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "logo200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "first200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "second200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "third200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fourth200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fifth200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "sixth200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "seventh200x200.bmp", fp_rawcontent, x, y);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "eighth200x200.bmp", fp_rawcontent, x, y);
delay(2000);
}
void drawBitmaps_other()
{
int16_t w2 = display.width() / 2;
int16_t h2 = display.height() / 2;
showBitmapFrom_HTTP("www.squix.org", "/blog/wunderground/", "chanceflurries.bmp", w2 - 50, h2 - 50, false);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_1.bmp", fp_rawcontent, w2 - 100, h2 - 160);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "marilyn_240x240x8.bmp", fp_rawcontent, w2 - 120, h2 - 120);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "miniwoof.bmp", fp_rawcontent, w2 - 60, h2 - 80);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "test.bmp", fp_rawcontent, w2 - 100, h2 - 100);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger.bmp", fp_rawcontent, w2 - 160, h2 - 120);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_178x160x4.bmp", fp_rawcontent, w2 - 89, h2 - 80);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_240x317x4.bmp", fp_rawcontent, w2 - 120, h2 - 160);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_320x200x24.bmp", fp_rawcontent, w2 - 160, h2 - 100);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger16T.bmp", fp_rawcontent, w2 - 160, h2 - 100);
delay(2000);
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "woof.bmp", fp_rawcontent, w2 - 100, h2 - 100);
delay(2000);
}
void drawBitmaps_test()
{
int16_t w2 = display.width() / 2;
int16_t h2 = display.height() / 2;
showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
delay(2000);
}
static const uint16_t input_buffer_pixels = 800; // may affect performance
static const uint16_t max_row_width = 1448; // for up to 6" display 1448x1072
static const uint16_t max_palette_pixels = 256; // for depth <= 8
uint8_t input_buffer; // up to depth 24
uint8_t output_row_mono_buffer; // buffer for at least one row of b/w bits
uint8_t output_row_color_buffer; // buffer for at least one row of color bits
uint8_t mono_palette_buffer; // palette buffer for depth <= 8 b/w
uint8_t color_palette_buffer; // palette buffer for depth <= 8 c/w
void drawBitmapFrom_HTTP_ToBuffer(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
{
WiFiClient client;
bool connection_ok = false;
bool valid = false; // valid format to be handled
bool flip = true; // bitmap is stored bottom-to-top
uint32_t startTime = millis();
if ((x >= display.width()) || (y >= display.height())) return;
display.fillScreen(GxEPD_WHITE);
Serial.print("connecting to "); Serial.println(host);
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
return;
}
Serial.print("requesting URL: ");
Serial.println(String("http://") + host + path + filename);
client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: GxEPD_WiFi_Example\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (client.connected())
{
String line = client.readStringUntil('\n');
if (!connection_ok)
{
connection_ok = line.startsWith("HTTP/1.1 200 OK");
if (connection_ok) Serial.println(line);
//if (!connection_ok) Serial.println(line);
}
if (!connection_ok) Serial.println(line);
//Serial.println(line);
if (line == "\r")
{
Serial.println("headers received");
break;
}
}
if (!connection_ok) return;
// Parse BMP header
if (read16(client) == 0x4D42) // BMP signature
{
int32_t fileSize = read32(client);
int32_t creatorBytes = read32(client);
int32_t imageOffset = read32(client); // Start of image data
int32_t headerSize = read32(client);
int32_t width= read32(client);
int32_t height = read32(client);
uint16_t planes = read16(client);
uint16_t depth = read16(client); // bits per pixel
int32_t format = read32(client);
int32_t bytes_read = 7 * 4 + 3 * 2; // read so far
(void) creatorBytes;
if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
{
Serial.print("File size: "); Serial.println(fileSize);
Serial.print("Image Offset: "); Serial.println(imageOffset);
Serial.print("Header size: "); Serial.println(headerSize);
Serial.print("Bit Depth: "); Serial.println(depth);
Serial.print("Image size: ");
Serial.print(width);
Serial.print('x');
Serial.println(height);
// BMP rows are padded (if needed) to 4-byte boundary
uint32_t rowSize = (width * depth / 8 + 3) & ~3;
if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
if (height < 0)
{
height = -height;
flip = false;
}
uint16_t w = width;
uint16_t h = height;
if ((x + w - 1) >= display.width())w = display.width()- x;
if ((y + h - 1) >= display.height()) h = display.height() - y;
valid = true;
uint8_t bitmask = 0xFF;
uint8_t bitshift = 8 - depth;
uint16_t red, green, blue;
bool whitish = false;
bool colored = false;
if (depth == 1) with_color = false;
if (depth <= 8)
{
if (depth < 8) bitmask >>= depth;
//bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
for (uint16_t pn = 0; pn < (1 << depth); pn++)
{
blue= client.read();
green = client.read();
red = client.read();
client.read();
bytes_read += 4;
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
if (0 == pn % 8) mono_palette_buffer = 0;
mono_palette_buffer |= whitish << pn % 8;
if (0 == pn % 8) color_palette_buffer = 0;
color_palette_buffer |= colored << pn % 8;
//Serial.print("0x00"); Serial.print(red, HEX); Serial.print(green, HEX); Serial.print(blue, HEX);
//Serial.print(" : "); Serial.print(whitish); Serial.print(", "); Serial.println(colored);
}
}
display.fillScreen(GxEPD_WHITE);
uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
//Serial.print("skip "); Serial.println(rowPosition - bytes_read);
bytes_read += skip(client, rowPosition - bytes_read);
for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
{
if (!connection_ok || !(client.connected() || client.available())) break;
delay(1); // yield() to avoid WDT
uint32_t in_remain = rowSize;
uint32_t in_idx = 0;
uint32_t in_bytes = 0;
uint8_t in_byte = 0; // for depth <= 8
uint8_t in_bits = 0; // for depth <= 8
uint16_t color = GxEPD_WHITE;
for (uint16_t col = 0; col < w; col++) // for each pixel
{
yield();
if (!connection_ok || !(client.connected() || client.available())) break;
// Time to read more pixel data?
if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
{
uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
uint32_t got = read8n(client, input_buffer, get);
while ((got < get) && connection_ok)
{
//Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
uint32_t gotmore = read8n(client, input_buffer + got, get - got);
got += gotmore;
connection_ok = gotmore > 0;
}
in_bytes = got;
in_remain -= got;
bytes_read += got;
}
if (!connection_ok)
{
Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
break;
}
switch (depth)
{
case 24:
blue = input_buffer;
green = input_buffer;
red = input_buffer;
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
break;
case 16:
{
uint8_t lsb = input_buffer;
uint8_t msb = input_buffer;
if (format == 0) // 555
{
blue= (lsb & 0x1F) << 3;
green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
red = (msb & 0x7C) << 1;
}
else // 565
{
blue= (lsb & 0x1F) << 3;
green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
red = (msb & 0xF8);
}
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
}
break;
case 1:
case 4:
case 8:
{
if (0 == in_bits)
{
in_byte = input_buffer;
in_bits = 8;
}
uint16_t pn = (in_byte >> bitshift) & bitmask;
whitish = mono_palette_buffer & (0x1 << pn % 8);
colored = color_palette_buffer & (0x1 << pn % 8);
in_byte <<= depth;
in_bits -= depth;
}
break;
}
if (whitish)
{
color = GxEPD_WHITE;
}
else if (colored && with_color)
{
color = GxEPD_RED;
}
else
{
color = GxEPD_BLACK;
}
uint16_t yrow = y + (flip ? h - row - 1 : row);
display.drawPixel(x + col, yrow, color);
} // end pixel
} // end line
}
Serial.print("bytes read "); Serial.println(bytes_read);
}
Serial.print("loaded in "); Serial.print(millis() - startTime); Serial.println(" ms");
if (!valid)
{
Serial.println("bitmap format not handled.");
}
}
void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
{
Serial.println(); Serial.print("downloading file \""); Serial.print(filename);Serial.println("\"");
drawBitmapFrom_HTTP_ToBuffer(host, path, filename, x, y, with_color);
display.update();
}
void drawBitmapFrom_HTTPS_ToBuffer(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
{
// Use WiFiClientSecure class to create TLS connection
#if USE_BearSSL
BearSSL::WiFiClientSecure client;
#else
WiFiClientSecure client;
#endif
bool connection_ok = false;
bool valid = false; // valid format to be handled
bool flip = true; // bitmap is stored bottom-to-top
uint32_t startTime = millis();
if ((x >= display.width()) || (y >= display.height())) return;
display.fillScreen(GxEPD_WHITE);
Serial.print("connecting to "); Serial.println(host);
#if defined (ESP8266)
client.setBufferSizes(4096, 4096); // doesn't help
if (fingerprint) client.setFingerprint(fingerprint);
#elif defined (ESP32)
if (certificate) client.setCACert(certificate);
#endif
if (!client.connect(host, httpsPort))
{
Serial.println("connection failed");
return;
}
Serial.print("requesting URL: ");
Serial.println(String("https://") + host + path + filename);
client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: GxEPD_WiFi_Example\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (client.connected())
{
String line = client.readStringUntil('\n');
if (!connection_ok)
{
connection_ok = line.startsWith("HTTP/1.1 200 OK");
if (connection_ok) Serial.println(line);
//if (!connection_ok) Serial.println(line);
}
if (!connection_ok) Serial.println(line);
//Serial.println(line);
if (line == "\r")
{
Serial.println("headers received");
break;
}
}
if (!connection_ok) return;
// Parse BMP header
if (read16(client) == 0x4D42) // BMP signature
{
int32_t fileSize = read32(client);
int32_t creatorBytes = read32(client);
int32_t imageOffset = read32(client); // Start of image data
int32_t headerSize = read32(client);
int32_t width= read32(client);
int32_t height = read32(client);
uint16_t planes = read16(client);
uint16_t depth = read16(client); // bits per pixel
int32_t format = read32(client);
int32_t bytes_read = 7 * 4 + 3 * 2; // read so far
(void) creatorBytes;
if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
{
Serial.print("File size: "); Serial.println(fileSize);
Serial.print("Image Offset: "); Serial.println(imageOffset);
Serial.print("Header size: "); Serial.println(headerSize);
Serial.print("Bit Depth: "); Serial.println(depth);
Serial.print("Image size: ");
Serial.print(width);
Serial.print('x');
Serial.println(height);
// BMP rows are padded (if needed) to 4-byte boundary
uint32_t rowSize = (width * depth / 8 + 3) & ~3;
if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
if (height < 0)
{
height = -height;
flip = false;
}
uint16_t w = width;
uint16_t h = height;
if ((x + w - 1) >= display.width())w = display.width()- x;
if ((y + h - 1) >= display.height()) h = display.height() - y;
valid = true;
uint8_t bitmask = 0xFF;
uint8_t bitshift = 8 - depth;
uint16_t red, green, blue;
bool whitish = false;
bool colored = false;
if (depth == 1) with_color = false;
if (depth <= 8)
{
if (depth < 8) bitmask >>= depth;
//bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
for (uint16_t pn = 0; pn < (1 << depth); pn++)
{
blue= client.read();
green = client.read();
red = client.read();
client.read();
bytes_read += 4;
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
if (0 == pn % 8) mono_palette_buffer = 0;
mono_palette_buffer |= whitish << pn % 8;
if (0 == pn % 8) color_palette_buffer = 0;
color_palette_buffer |= colored << pn % 8;
//Serial.print("0x00"); Serial.print(red, HEX); Serial.print(green, HEX); Serial.print(blue, HEX);
//Serial.print(" : "); Serial.print(whitish); Serial.print(", "); Serial.println(colored);
}
}
display.fillScreen(GxEPD_WHITE);
uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
//Serial.print("skip "); Serial.println(rowPosition - bytes_read);
bytes_read += skip(client, rowPosition - bytes_read);
for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
{
if (!connection_ok || !(client.connected() || client.available())) break;
delay(1); // yield() to avoid WDT
uint32_t in_remain = rowSize;
uint32_t in_idx = 0;
uint32_t in_bytes = 0;
uint8_t in_byte = 0; // for depth <= 8
uint8_t in_bits = 0; // for depth <= 8
uint16_t color = GxEPD_WHITE;
for (uint16_t col = 0; col < w; col++) // for each pixel
{
yield();
if (!connection_ok || !(client.connected() || client.available())) break;
// Time to read more pixel data?
if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
{
uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
uint32_t got = read8n(client, input_buffer, get);
while ((got < get) && connection_ok)
{
//Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
uint32_t gotmore = read8n(client, input_buffer + got, get - got);
got += gotmore;
connection_ok = gotmore > 0;
}
in_bytes = got;
in_remain -= got;
bytes_read += got;
}
if (!connection_ok)
{
Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
break;
}
switch (depth)
{
case 24:
blue = input_buffer;
green = input_buffer;
red = input_buffer;
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
break;
case 16:
{
uint8_t lsb = input_buffer;
uint8_t msb = input_buffer;
if (format == 0) // 555
{
blue= (lsb & 0x1F) << 3;
green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
red = (msb & 0x7C) << 1;
}
else // 565
{
blue= (lsb & 0x1F) << 3;
green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
red = (msb & 0xF8);
}
whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
}
break;
case 1:
case 4:
case 8:
{
if (0 == in_bits)
{
in_byte = input_buffer;
in_bits = 8;
}
uint16_t pn = (in_byte >> bitshift) & bitmask;
whitish = mono_palette_buffer & (0x1 << pn % 8);
colored = color_palette_buffer & (0x1 << pn % 8);
in_byte <<= depth;
in_bits -= depth;
}
break;
}
if (whitish)
{
color = GxEPD_WHITE;
}
else if (colored && with_color)
{
color = GxEPD_RED;
}
else
{
color = GxEPD_BLACK;
}
uint16_t yrow = y + (flip ? h - row - 1 : row);
display.drawPixel(x + col, yrow, color);
} // end pixel
} // end line
}
Serial.print("bytes read "); Serial.println(bytes_read);
}
Serial.print("loaded in "); Serial.print(millis() - startTime); Serial.println(" ms");
if (!valid)
{
Serial.println("bitmap format not handled.");
}
client.stop();
}
void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
{
Serial.println(); Serial.print("downloading file \""); Serial.print(filename);Serial.println("\"");
drawBitmapFrom_HTTPS_ToBuffer(host, path, filename, fingerprint, x, y, with_color, certificate);
display.update();
}
uint16_t read16(WiFiClient& client)
{
// BMP data is stored little-endian, same as Arduino.
uint16_t result;
((uint8_t *)&result) = client.read(); // LSB
((uint8_t *)&result) = client.read(); // MSB
return result;
}
int32_t read32(WiFiClient& client)
{
// BMP data is stored little-endian, same as Arduino.
int32_t result;
((uint8_t *)&result) = client.read(); // LSB
((uint8_t *)&result) = client.read();
((uint8_t *)&result) = client.read();
((uint8_t *)&result) = client.read(); // MSB
return result;
}
#if USE_BearSSL
uint32_t skip(BearSSL::WiFiClientSecure& client, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while (client.connected() && (remain > 0))
{
if (client.available())
{
int16_t v = client.read();
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
uint32_t read(BearSSL::WiFiClientSecure& client, uint8_t* buffer, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while (client.connected() && (remain > 0))
{
if (client.available())
{
int16_t v = client.read();
*buffer++ = uint8_t(v);
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
#endif
uint32_t skip(WiFiClient& client, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while ((client.connected() || client.available()) && (remain > 0))
{
if (client.available())
{
int16_t v = client.read();
(void) v;
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
uint32_t read8n(WiFiClient& client, uint8_t* buffer, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while ((client.connected() || client.available()) && (remain > 0))
{
if (client.available())
{
int16_t v = client.read();
*buffer++ = uint8_t(v);
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
你是我的神:lol liangfengxiao 发表于 2022-8-13 17:03
你是我的神
一起学习,一起进步。 请问,楼主可以使用GXEPD2点亮吗 我折腾了一下点亮不了 本帖最后由 topdog 于 2022-8-17 22:27 编辑
liangfengxiao 发表于 2022-8-17 11:31
请问,楼主可以使用GXEPD2点亮吗 我折腾了一下点亮不了
这款墨水屏型号是GDEP015OC1。
e ink outdoor display,Anti UV display,(Out of Stock)1.54 inch e-paper display anti-ultraviolet (e-paper-display.com)
GxEPD2库显示GDEP015OC1不再可用,这款亚马逊已经下架。
GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEP015OC1 no longer available
驱动:
/*
* Copyright (c) 2019, Mahyar Koshkouei
* Released under ISC License.
*
* Library to operate the GDEP015OC1 display.
*/
#ifndef MK_GDEP015OC1_H
#define MK_GDEP015OC1_H
/* User required definitions. */
#ifndef MK_GDEP_READ_BUSY_PIN
#error "MK_GDEP_READ_BUSY_PIN was not defined."
#endif
#ifndef MK_GDEP_RESET_DISPLAY
#error "MK_GDEP_SET_RESET_PIN was not defined."
#endif
#ifndef MK_GDEP_SET_DC_PIN
#error "MK_GDEP_SET_DC_PIN was not defined."
#endif
#ifndef MK_GDEP_SET_CS_PIN
#error "MK_GDEP_SET_CS_PIN was not defined."
#endif
#ifndef MK_GDEP_SET_SCLK_PIN
#error "MK_GDEP_SET_SCLK_PIN was not defined."
#endif
#ifndef MK_GDEP_SET_SDI_PIN
#error "MK_GDEP_SET_SDI_PIN was not defined."
#endif
#ifndef MK_GDEP_SEND_SPI_BYTE
#error "MK_GDEP_SEND_SPI_BYTE was not defined."
#endif
/* Display resolution */
#define GDEP015OC1_DISPLAY_WIDTH 200
#define GDEP015OC1_DISPLAY_HEIGHT 200
/* GDEP015OC1 commands */
#define DRIVER_OUTPUT_CONTROL 0x01
#define BOOSTER_SOFT_START_CONTROL 0x0C
#define GATE_SCAN_START_POSITION 0x0F
#define DEEP_SLEEP_MODE 0x10
#define DATA_ENTRY_MODE_SETTING 0x11
#define SW_RESET 0x12
#define TEMPERATURE_SENSOR_CONTROL 0x1A
#define MASTER_ACTIVATION 0x20
#define DISPLAY_UPDATE_CONTROL_1 0x21
#define DISPLAY_UPDATE_CONTROL_2 0x22
#define WRITE_RAM 0x24
#define WRITE_VCOM_REGISTER 0x2C
#define WRITE_LUT_REGISTER 0x32
#define SET_DUMMY_LINE_PERIOD 0x3A
#define SET_GATE_TIME 0x3B
#define BORDER_WAVEFORM_CONTROL 0x3C
#define SET_RAM_X_ADDRESS_START_END_POSITION 0x44
#define SET_RAM_Y_ADDRESS_START_END_POSITION 0x45
#define SET_RAM_X_ADDRESS_COUNTER 0x4E
#define SET_RAM_Y_ADDRESS_COUNTER 0x4F
#define TERMINATE_FRAME_READ_WRITE 0xFF
enum lut_selection_e {
LUT_NONE, /* Uses previously used LUT? */
LUT_FULL,
LUT_PARTIAL
};
const uint8_t lut_full_update[] =
{
0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22,
0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88,
0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51,
0x35, 0x51, 0x51, 0x19, 0x01, 0x00
};
const uint8_t lut_partial_update[] =
{
0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/**
* Transmits a given buffer over SPI.
*
* @param buf buffer to transmit
* @param len length of buffer
*/
void send_spi_buffer(const uint8_t *buf, const uint_fast8_t len)
{
// Select data transmission
MK_GDEP_SET_DC_PIN(1);
// Select display for SPI communication
MK_GDEP_SET_CS_PIN(0);
for(uint_fast8_t i = 0; i < len; i++)
MK_GDEP_SEND_SPI_BYTE(buf);
MK_GDEP_SET_CS_PIN(1);
}
/**
* Send command over SPI to the display.
*
* @param cmd Command to send.
*/
void send_disp_command(const uint8_t cmd)
{
// Select command transmission
MK_GDEP_SET_DC_PIN(0);
// Select display for SPI communication
MK_GDEP_SET_CS_PIN(0);
MK_GDEP_SEND_SPI_BYTE(cmd);
MK_GDEP_SET_CS_PIN(1);
}
/**
* Waits until the display is idle.
*/
inline void disp_wait_until_idle(void)
{
while(MK_GDEP_READ_BUSY_PIN);
}
/**
* Initialise the connected display.
*/
inline void init_display(const enum lut_selection_e lut)
{
MK_GDEP_RESET_DISPLAY();
send_disp_command(DRIVER_OUTPUT_CONTROL);
const uint8_t doc_data[] = {
0xC7, // Low 8 bits for display height
0x00, // High 8 bits
0x00
// 0b00000000
// UUUUU
// 0 GD: Selects gate layout of panel
// 0SM: Disable interleaved mode
// 0 TB: Scanning direction of gate driver
};
send_spi_buffer(doc_data, sizeof (doc_data));
send_disp_command(BOOSTER_SOFT_START_CONTROL);
const uint8_t bssc_data[] = {0xD7, 0xD6, 0x9D};
send_spi_buffer(bssc_data, sizeof (bssc_data));
send_disp_command(WRITE_VCOM_REGISTER);
const uint8_t wvr_data[] = {0xA8};
send_spi_buffer(wvr_data, sizeof (wvr_data));
send_disp_command(SET_DUMMY_LINE_PERIOD);
const uint8_t sdlp_data[] = {0x1A};
send_spi_buffer(sdlp_data, sizeof (sdlp_data));
send_disp_command(SET_GATE_TIME);
const uint8_t sgt_data[] = {0x08};
send_spi_buffer(sgt_data, sizeof (sgt_data));
send_disp_command(DATA_ENTRY_MODE_SETTING);
const uint8_t dems_data[] = {0x03};
send_spi_buffer(dems_data, sizeof (dems_data));
switch(lut)
{
case LUT_FULL:
send_disp_command(WRITE_LUT_REGISTER);
send_spi_buffer(lut_full_update, sizeof (lut_full_update));
break;
case LUT_PARTIAL:
send_disp_command(WRITE_LUT_REGISTER);
send_spi_buffer(lut_partial_update, sizeof(lut_partial_update));
break;
default:
break;
};
}
void disp_set_memory_area(const uint8_t x_start, const uint8_t y_start,
const uint8_t x_end, const uint8_t y_end)
{
send_disp_command(SET_RAM_X_ADDRESS_START_END_POSITION);
/* x point must be the multiple of 8 or the last 3 bits will be ignored */
uint8_t set_ramx_addr[] = {(x_start >> 3), (x_end >> 3)};
send_spi_buffer(set_ramx_addr, sizeof (set_ramx_addr));
send_disp_command(SET_RAM_Y_ADDRESS_START_END_POSITION);
uint8_t set_ramy_addr[] = {y_start, 0x00, y_end, 0x00};
send_spi_buffer(set_ramy_addr, sizeof (set_ramy_addr));
}
void set_memory_pointer(uint8_t x, uint8_t y)
{
send_disp_command(SET_RAM_X_ADDRESS_COUNTER);
/* x point must be the multiple of 8 or the last 3 bits will be ignored */
uint8_t set_ramx_addr_count[] = {x >> 3};
send_spi_buffer(set_ramx_addr_count, sizeof (set_ramx_addr_count));
send_disp_command(SET_RAM_Y_ADDRESS_COUNTER);
uint8_t set_ramy_addr_count[] = {y, 0x00};
send_spi_buffer(set_ramy_addr_count, sizeof (set_ramy_addr_count));
disp_wait_until_idle();
}
void disp_clear_frame_memory(const uint8_t color)
{
disp_set_memory_area(0, 0,
GDEP015OC1_DISPLAY_WIDTH - 1, GDEP015OC1_DISPLAY_HEIGHT - 1);
set_memory_pointer(0, 0);
send_disp_command(WRITE_RAM);
// Select data transmission
MK_GDEP_SET_DC_PIN(1);
// Select display for SPI communication
MK_GDEP_SET_CS_PIN(0);
/* send the colour data */
uint_fast16_t i = (GDEP015OC1_DISPLAY_WIDTH / 8) * GDEP015OC1_DISPLAY_HEIGHT;
do
{
MK_GDEP_SEND_SPI_BYTE(color);
}
while(--i);
MK_GDEP_SET_CS_PIN(1);
}
void disp_display_frame(void)
{
send_disp_command(DISPLAY_UPDATE_CONTROL_2);
const uint8_t duc2_data[] = {0xC4};
send_spi_buffer(duc2_data, sizeof (duc2_data));
send_disp_command(MASTER_ACTIVATION);
send_disp_command(TERMINATE_FRAME_READ_WRITE);
disp_wait_until_idle();
}
void disp_sleep(void)
{
send_disp_command(DEEP_SLEEP_MODE);
const uint8_t sleep_data[] = {0x01};
send_spi_buffer(sleep_data, sizeof (sleep_data));
}
void disp_set_block(const uint8_t x, const uint8_t y,
const uint8_t x_end, const uint8_t y_end,
const uint8_t pattern)
{
uint16_t pixels = (((x_end + 1) - x) * ((y_end + 1) - y));
disp_set_memory_area(x, y, x_end, y_end);
set_memory_pointer(x, y);
send_disp_command(WRITE_RAM);
// Select data transmission
MK_GDEP_SET_DC_PIN(1);
// Select display for SPI communication
MK_GDEP_SET_CS_PIN(0);
/* send the pattern data */
do
{
MK_GDEP_SEND_SPI_BYTE(pattern);
}
while(--pixels);
MK_GDEP_SET_CS_PIN(1);
}
void disp_write_image(const uint8_t x, const uint8_t y,
const uint8_t x_end, const uint8_t y_end,
const uint8_t *img, const uint_fast16_t len)
{
disp_set_memory_area(x, y, x_end, y_end);
set_memory_pointer(x, y);
send_disp_command(WRITE_RAM);
// Select data transmission
MK_GDEP_SET_DC_PIN(1);
// Select display for SPI communication
MK_GDEP_SET_CS_PIN(0);
/* send the pattern data */
for(uint_fast16_t i = 0; i < len; i++)
MK_GDEP_SEND_SPI_BYTE(img);
MK_GDEP_SET_CS_PIN(1);
}
#endif /* MK_GDEP015OC1_H */
页:
[1]