|
话不多说,继续分享,先上用法:1. reset 系统或上电,连接热点 wifiepd ,打开浏览器,输入网址192.168.4.1,做这步之前把黑白图片先保存好,分辨率120*249 比分辨率小一点(2.13寸),竖版图片,24位 bmp图片 :
打开浏览器后如下图 ,点击选择文件,点击确定。
,屏幕会自动刷新,然后图片就上去了。断电就一直显示你需要的图片。上电会重新开始。
再说缺点,这个对图片有要求,只能黑白,彩色的会显示不好(也不是不能用哈,)。也没有判断横竖屏,而且图片需要手动修改, 没有抖动算法,对线条图支持的好一点。灰度基本不能看了。
ps,屏幕是hink E0213A04,E029A1也可以了, 威锋的屏好像只能全局刷新,不好用,没改适配代码,原理应该一样的。
上代码吧,代码也是借鉴别人的,自己不是专业编程,对某些部分看的也不是太懂。希望有高手继续改良分享。注意红色部分,如果换屏需要修改,还有个隐藏功能,看大家能从代码看出来么,哈哈哈
- //接线定义
- // mapping from Waveshare 2.9inch e-Paper to Wemos D1 mini
- // BUSY -> D2(4), RST -> D4(2), DC -> D3(0), CS -> D8(15), CLK -> D5(14), DIN -> D7(13), GND -> GND, 3.3V -> 3.3V
- // mapping example for AVR, UNO, NANO etc.
- // BUSY -> 7, RST -> 9, DC -> 8, C S-> 10, CLK -> 13, DIN -> 11
- // include library, include base class, make path known
- //epd resolotion 122*250(2.13) ,296x128(2.9)
- #define EPDX 122
- #define EPDY 250
- #include <ESP8266WebServer.h>
- #include <ESP8266WiFi.h>
- #include <WiFiClient.h>
- #include <ESP8266HTTPClient.h>
- #include <FS.h>
- #include <GxEPD.h>
- // select the display class to use, only one
- //#include <GxGDEH029A1/GxGDEH029A1.h> // 2.9" b/w
- #include <GxGDE0213B1/GxGDE0213B1.h> // 2.13" b/w
- #include <GxIO/GxIO_SPI/GxIO_SPI.h>
- #include <GxIO/GxIO.h>
- // FreeFonts from Adafruit_GFX
- #include <Fonts/FreeMonoBold9pt7b.h>
- #include <Fonts/FreeMonoBold18pt7b.h>
- const char mainPageString[] PROGMEM = "<!DOCTYPE html>\r\n\
- <html>\r\n\
- <head>\r\n\
- <meta http-equiv='Content-type' content='text/html; charset=utf-8'>\r\n\
- <title>ESP Monitor</title>\r\n\
- </head>\r\n\
- <body>\r\n\
- <img src='/logo.bmp' width='128' height='296' />\r\n\
- <form method='POST' action='/' enctype='multipart/form-data'>\r\n\
- <input type='file' name='update' id='update'><input type='submit' value='提交'></form>\r\n\
- 文件格式必须为bmp,24位,竖版,屏幕为2.9寸E029A1,分辨率296*128\r\n\ 屏幕为2.13寸E0213,分辨率250*122\r\n\
- </body>\r\n\
- </html>";
- GxIO_Class io(SPI, /*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2); // arbitrary selection of D3(=0), D4(=2), selected for default of GxEPD_Class
- GxEPD_Class display(io /*RST=D4*/ /*BUSY=D2*/); // default selection of D4(=2), D2(=4)
- #if defined(_GxGDE0213B1_H_) || defined(_GxGDEH029A1_H_) || defined(_GxGDEW042T2_H_)
- const uint32_t partial_update_period_s = 2;
- const uint32_t full_update_period_s = 1 * 60 * 60;
- #endif
- unsigned char pic[4736]={0};
- // 设置mode 按钮
- const int MODE_PIN = 5; // 可以是0,但是屏幕刷新前要改回output状态
- ESP8266WebServer server(80);
- File fsUploadFile;
- #define BUFFPIXEL 20
- bool b_setup=false; // 判断是否为设置模式
- bool b_wifistatus=false;
- //========================================
- // These read 16- and 32-bit types from the SD card file.
- // BMP data is stored little-endian, Arduino is little-endian too.
- // May need to reverse subscript order if porting elsewhere.
- uint16_t read16(File f) {
- uint16_t result;
- ((uint8_t *)&result)[0] = f.read(); // LSB
- ((uint8_t *)&result)[1] = f.read(); // MSB
- return result;
- }
- uint32_t read32(File f) {
- uint32_t result;
- ((uint8_t *)&result)[0] = f.read(); // LSB
- ((uint8_t *)&result)[1] = f.read();
- ((uint8_t *)&result)[2] = f.read();
- ((uint8_t *)&result)[3] = f.read(); // MSB
- return result;
- }
- void bmpDraw(char *filename, uint8_t x, uint8_t y) {
- File bmpFile;
- int bmpWidth, bmpHeight; // W+H in pixels
- uint8_t bmpDepth; // Bit depth (currently must be 24)
- uint32_t bmpImageoffset; // Start of image data in file
- uint32_t rowSize; // Not always = bmpWidth; may have padding
- uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
- uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
- boolean goodBmp = false; // Set to true on valid header parse
- boolean flip = true; // BMP is stored bottom-to-top
- int w, h, row, col;
- uint8_t r, g, b;
- uint32_t pos = 0, startTime = millis();
- int j=0;
- // epd resolotion
- if((x >= EPDX) || (y >= EPDY)) return;
- Serial.println();
- Serial.print("Loading image '");
- Serial.print(filename);
- Serial.println('\'');
- bmpFile = SPIFFS.open(filename,"r");
- // Open requested file on SD card
- if (!bmpFile) {
- Serial.print("File not found");
- return;
- }
- // Parse BMP header
- if(read16(bmpFile) == 0x4D42) { // BMP signature
- Serial.print("File size: "); Serial.println(read32(bmpFile));
- (void)read32(bmpFile); // Read & ignore creator bytes
- bmpImageoffset = read32(bmpFile); // Start of image data
- Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC);
- // Read DIB header
- Serial.print("Header size: "); Serial.println(read32(bmpFile));
- bmpWidth = read32(bmpFile);
- bmpHeight = read32(bmpFile);
- if(read16(bmpFile) == 1) { // # planes -- must be '1'
- bmpDepth = read16(bmpFile); // bits per pixel
- Serial.print("Bit Depth: "); Serial.println(bmpDepth);
- if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
- goodBmp = true; // Supported BMP format -- proceed!
- Serial.print("Image size: ");
- Serial.print(bmpWidth);
- Serial.print('x');
- Serial.println(bmpHeight);
- // BMP rows are padded (if needed) to 4-byte boundary
- rowSize = (bmpWidth * 3 + 3) & ~3;
- // If bmpHeight is negative, image is in top-down order.
- // This is not canon but has been observed in the wild.
- if(bmpHeight < 0) {
- bmpHeight = -bmpHeight;
- flip = false;
- }
- // Crop area to be loaded
- w = bmpWidth;
- h = bmpHeight;
- //Serial.print("bmpHeight:") ; Serial.print(h);
- //if((x+w-1) >= 296) w = 296 - x;
- //if((y+h-1) >= 128) h = 128 - y;
- //Serial.print("bmpHeight:") ; Serial.print(h);
- for (row=0; row<h; row++) { // For each scanline...
- String strs="";
- // Seek to start of scan line. It might seem labor-
- // intensive to be doing this on every line, but this
- // method covers a lot of gritty details like cropping
- // and scanline padding. Also, the seek only takes
- // place if the file position actually needs to change
- // (avoids a lot of cluster math in SD library).
- if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
- pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
- else // Bitmap is stored top-to-bottom
- pos = bmpImageoffset + row * rowSize;
- if(bmpFile.position() != pos) { // Need seek?
- bmpFile.seek(pos,SeekSet);
- buffidx = sizeof(sdbuffer); // Force buffer reload
- }
- for (col=0; col<w; col++) { // For each pixel...
- // Time to read more pixel data?
- if (buffidx >= sizeof(sdbuffer)) { // Indeed
- bmpFile.read(sdbuffer, sizeof(sdbuffer));
- buffidx = 0; // Set index to beginning
- }
- // Convert pixel from BMP to TFT format, push to display
- b = sdbuffer[buffidx++];
- g = sdbuffer[buffidx++];
- r = sdbuffer[buffidx++];
- if (b==g and b==r and r==g and b>=200)
- {
- strs+="0";
- }
- else
- strs+="1";
- } // end pixel
- //Serial.println(strs);
- //const char *strt = strs.c_str();
- unsigned char rt = 0;
- for (int i=0; i< strs.length(); i++) // for every character in the string strlen(s) returns the length of a char array
- {
- rt = rt << 1;
- rt = rt | (strs & 1);
- if( i % 8 ==7)
- {
- pic[j]=rt;
- rt=0;
- j++;
- }
- }
- } // end scanline
- full_clear();
- Serial.println("ready update!") ; //Serial.print(w) ; Serial.print(" x ") ; Serial.println(h) ;
- display.drawBitmap(0, 0, (const uint8_t *)pic, w, h, GxEPD_BLACK);
- //display.updateWindow(row, col,w,h, true);
- display.update();
- Serial.print("Loaded in ");
- Serial.print(millis() - startTime);
- Serial.println(" ms");
- } // end goodBmp
- }
- }
- bmpFile.close();
- if(!goodBmp) Serial.println("BMP format not recognized.");
- }
- //======================
- //======================
- //format bytes
- String formatBytes(size_t bytes){
- if (bytes < 1024){
- return String(bytes)+"B";
- } else if(bytes < (1024 * 1024)){
- return String(bytes/1024.0)+"KB";
- } else if(bytes < (1024 * 1024 * 1024)){
- return String(bytes/1024.0/1024.0)+"MB";
- } else {
- return String(bytes/1024.0/1024.0/1024.0)+"GB";
- }
- }
- //文件格式转换
- String getContentType(String filename){
- if(server.hasArg("download")) return "application/octet-stream";
- else if(filename.endsWith(".htm")) return "text/html";
- else if(filename.endsWith(".html")) return "text/html";
- else if(filename.endsWith(".css")) return "text/css";
- else if(filename.endsWith(".js")) return "application/javascript";
- else if(filename.endsWith(".png")) return "image/png";
- else if(filename.endsWith(".gif")) return "image/gif";
- else if(filename.endsWith(".jpg")) return "image/jpeg";
- else if(filename.endsWith(".ico")) return "image/x-icon";
- else if(filename.endsWith(".xml")) return "text/xml";
- else if(filename.endsWith(".pdf")) return "application/x-pdf";
- else if(filename.endsWith(".zip")) return "application/x-zip";
- else if(filename.endsWith(".gz")) return "application/x-gzip";
- return "text/plain";
- }
- //读取spiffs中的文件
- bool handleFileRead(String path){
- Serial.println("handleFileRead: " + path);
- if(path.endsWith("/")) path += "index.htm";
- String contentType = getContentType(path);
- String pathWithGz = path + ".gz";
- if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
- if(SPIFFS.exists(pathWithGz))
- path += ".gz";
- File file = SPIFFS.open(path, "r");
- size_t sent = server.streamFile(file, contentType);
- file.close();
- return true;
- }
- return false;
- }
- //上传文件到spiffs中
- void handleFileUpload(){
- if(server.uri() != "/") return;
- HTTPUpload& upload = server.upload();
- if(upload.status == UPLOAD_FILE_START){
- String filename = upload.filename;
- if(!filename.startsWith("/")) filename = "/"+filename;
- Serial.print("handleFileUpload Name: "); Serial.println(filename);
- SPIFFS.rename("/logo.bmp","/last.bmp");
- fsUploadFile = SPIFFS.open("/logo.bmp", "w");
- filename = String();
- } else if(upload.status == UPLOAD_FILE_WRITE){
- //Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize);
- if(fsUploadFile)
- fsUploadFile.write(upload.buf, upload.currentSize);
- } else if(upload.status == UPLOAD_FILE_END){
- if(fsUploadFile)
- fsUploadFile.close();
- Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
- //上传完立即显示图片
- //full_clear();
- bmpDraw("/logo.bmp", 0, 0);
- //休眠最长时间直到按下reset
- Serial.print("deepsleep until reset");
- ESP.deepSleep(0);
- }
- }
- void handleRoot()
- {
- server.send(200, "text/html", mainPageString);
- server.client().stop();
- }
- void uplaodFinish() {
- server.send(200, "text/html", mainPageString);
- }
- void setup(void){
- Serial.begin(115200);
- Serial.print("\n");
- // Serial.setDebugOutput(true);
- display.init(); // disable diagnostic output on Serial
- display.setTextColor(GxEPD_BLACK);
- //display.setRotation(1);
- SPIFFS.begin();
- {
- Dir dir = SPIFFS.openDir("/");
- while (dir.next()) {
- String fileName = dir.fileName();
- size_t fileSize = dir.fileSize();
- Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
- }
- Serial.printf("\n");
- }
- full_clear();
- //WIFI INIT
- WiFi.disconnect();
- //WiFi.mode(WIFI_STA);
- String ssid="wifiepd";
- WiFi.softAP(ssid.c_str());
- Serial.print("Open http://192.168.4.1");
- Serial.println(" to see the file browser");
- showbrand();
- //SERVER INIT
- server.on("/", HTTP_GET, handleRoot);
- //把上传的数据保存到spiffs
- server.on("/", HTTP_POST,[](){uplaodFinish();}, handleFileUpload);
- //访问的url没有在找spiffs中找到回复404
- //访问的url没有在找spiffs中找到回复404
- server.onNotFound([](){
- if(!handleFileRead(server.uri()))
- server.send(404, "text/plain", "FileNotFound");
- });
- server.begin();
- Serial.println("HTTP server started");
- pinMode(MODE_PIN,INPUT_PULLUP);
- bool mod_val = digitalRead(MODE_PIN);
- delay(3000);
- if (mod_val == LOW )
- {
- bmpDraw("/last.bmp", 0, 0);
- //休眠最长时间直到按下reset
- Serial.print("deepsleep until reset");
- ESP.deepSleep(0);
- }
- }
- void loop(void){
- server.handleClient();
- }
- void showbrand()
- {
- //display.drawBitmap(60, 0, ewm, 254, 122, GxEPD_BLACK);
- display.setTextColor(GxEPD_BLACK);
- display.setFont(&FreeMonoBold18pt7b);
- display.setCursor(10, 0);
- display.println();
- //display.println("0123456789:;<=>?");
- display.println(" WIFI");
- display.println(" PIC");
- display.println();
- display.setFont(&FreeMonoBold9pt7b);
- display.println("WIFI:");
- display.println("wifiepd");
- display.println();
- display.println("open 192.168.4.1 update pic!");
- //display.updateWindow(0, 0, 250, 122, true);
- display.update();
- }
- void stopWiFiAndSleep() {
- //WiFi.disconnect();
- //WiFi.mode(WIFI_OFF);
- //Serial.println("WIFI sleep");
- wifi_set_sleep_type(LIGHT_SLEEP_T);
- //WiFi.forcelseepBegin();
- delay(1);
- }
- void full_clear()
- {
- display.fillScreen(GxEPD_WHITE);
- display.update();
- delay(200);
- }
[color=#336699 !important]复制代码
|
|