Arduino - Esp8266 12E读取SD卡文件

时间:2017-07-19 12:59:35

标签: sd-card esp8266 arduino-esp8266

我想在JSON中执行ESP8266 12E文件( 15.2KB [(15,601字节)大小)读取和写入。我正在使用

  1. Arduino SDK
  2. ESP8266 12E
  3. SD卡
  4. 我可以:

    1. 使用HTTPClient
    2. 编写文件
    3. 阅读文件并使用以下代码在Serial监视器上打印:

      server.on("/read", []() {
      myFile = SD.open("commands.txt");
      
      byte thisByte;      
      if (myFile) {
          while (myFile.available()) {
              thisByte = myFile.read();
              Serial.write(thisByte);
          }
      }
      
      myFile.close();
      server.send(200, "text/html", "File read Success.");
      });
      
    4. 我跑了/read 30到40次,效果不错,没有任何错误或ESP的WDT软复位。

      我不能:

      1. String变量中读取文件。代码是

        server.on("/read", []() {
        myFile = SD.open("commands.txt");
        
        String line = "";               
        if (myFile) {
            while (myFile.available()) {                
                line = myFile.readString();             
            }
        }
        
        Serial.println(line);
        
        myFile.close();
        server.send(200, "text/html", "File read Success.");
        });
        
      2. 在某些/read 和/或 /write然后/read ESP重置后

        Soft WDT reset
        
        ctx: cont 
        sp: 3fff0da0 end: 3fff10d0 offset: 01b0
        
        
        3fff0f50:  00004e00 3fff0fb0 3fff0fb0 402095c3  
        3fff0f60:  3fff0054 00004b73 3fff810f 4020a758  
        3fff0f70:  00000001 3ffe9320 3fff0fd4 40206c54  
        3fff0f80:  00000001 3ffe9320 3fff0074 4020a789  
        3fff0f90:  00000001 3ffe9320 3fff0fd4 402092b9  
        3fff0fa0:  00000001 3ffe9320 3ffefbac 4020245e  
        3fff0fb0:  00000000 00000000 00000000 402095c3  
        3fff0fc0:  6d6d6f63 73646e61 7478742e 40209600  
        3fff0fd0:  3fff2d3c 00000000 00000000 00000000  
        3fff0fe0:  3fff359c 00004dff 00004df1 4010068c  
        3fff0ff0:  00000000 00000001 3fff27dc 40206c4a  
        3fff1000:  3fff27dc 3ffef308 3fff27dc 40206c86  
        3fff1010:  00000000 00000000 00000000 40209770  
        3fff1020:  3fff27dc 3ffef308 3ffef2c8 40206d19  
        3fff1030:  3fff2d24 0000000f 00000005 40205b14  
        3fff1040:  00000000 00000000 00000000 0000000f  
        3fff1050:  00000001 3fff00a0 4020a114 3fff00b0  
        3fff1060:  00000000 00000000 3ffef2c8 3fff00a0  
        3fff1070:  00000001 3ffef2ec 3ffef2c8 40206f04  
        3fff1080:  3ffe8d68 00000000 00001388 3fff00b0  
        3fff1090:  00000000 3fff2c84 000003e8 3fff00a0  
        3fff10a0:  3fffdad0 00000000 3fff0098 40202367  
        3fff10b0:  3fffdad0 00000000 3fff0098 4020a160  
        3fff10c0:  feefeffe feefeffe 3fff00b0 4010070c  
        ets Jan  8 2013,rst cause:2, boot mode:(3,6)  
        load 0x4010f000, len 1384, room 16 
        

        我想将文件数据存储在String变量中,然后逐行处理。

        完整代码在这里:

        #include <Arduino.h>
        #include <SPI.h>
        #include <SD.h>
        #include <ESP8266WiFi.h>
        #include <ESP8266WiFiMulti.h>
        #include <ESP8266WebServer.h>
        #include <ESP8266HTTPClient.h>
        
        
        IPAddress ip(192, 168, 1, 81);         // choose IP address
        IPAddress subnet(255, 255, 255, 0);
        
        ESP8266WiFiMulti WiFiMulti;
        File myFile;
        
        ESP8266WebServer server(80);
        
        //06519942-652e-11e7-907b-a6006ad3dba0
        
        // SSID, PASSWORD
        const char *ssid = "06519942-652e-11e7-907b-a";
        const char *password = "password";
        
        void setup() {
        
            Serial.begin(115200);                      // so you can see debug messages automatically sent by ESP8266
            WiFi.mode(WIFI_AP);
            WiFi.softAPConfig(ip, ip, subnet);        // declared as: bool softAPConfig (IPAddress local_ip, IPAddress gateway, IPAddress subnet)
            WiFi.softAP(ssid, password, 7, 0, 1);  // network name, network password, wifi channel
        
            IPAddress myIP = WiFi.softAPIP();
            Serial.println();
            Serial.print("AP IP address: ");
            Serial.println(myIP);
            delay(1000);
        
            // Serial.setDebugOutput(true);
        
            Serial.print("Initializing SD card...");
            if (!SD.begin(16)) {
                Serial.println("initialization failed!");
                return;
            }
            Serial.println("initialization done.");
        
            Serial.println();
            Serial.println();
            Serial.println();
        
            for (uint8_t t = 4; t > 0; t--) {
                Serial.printf("[SETUP] WAIT %d...\n", t);
                Serial.flush();
                delay(1000);
            }
        
        
            WiFiMulti.addAP("SSID", "PASSWORD"); // Change it with yours
            delay(1000);
        
            server.on("/", []() {
                server.send(200, "text/html", "Welcome");
            });
        
            server.on("/read", []() {
                myFile = SD.open("commands.txt");
        
                byte thisByte;      
                if (myFile) {
                    while (myFile.available()) {
                        thisByte = myFile.read();               
                        Serial.write(thisByte);
                    }
                }
        
        
        
                myFile.close();
                server.send(200, "text/html", "File read Success.");
            });
        
            server.on("/write", []() {
                HTTPClient http;
        
                Serial.print("[HTTP] begin...\n");
        
                if (SD.exists("commands.txt")) {
                    SD.remove("commands.txt");
                    Serial.println("commands.txt removed.");
                }
        
                // configure server and url
                http.begin("http://controlxapi.azurewebsites.net/download");
        
                Serial.print("[HTTP] GET...\n");
        
                // start connection and send HTTP header
                int httpCode = http.GET();
        
                if (httpCode > 0) {
                    // HTTP header has been send and Server response header has been handled
                    Serial.printf("[HTTP] GET... code: %d\n", httpCode);
        
                    // file found at server
                    if (httpCode == HTTP_CODE_OK) {
        
                        Serial.println("Creating commands.txt...");
                        myFile = SD.open("commands.txt", FILE_WRITE);
        
                        // get lenght of document (is -1 when Server sends no Content-Length header)
                        int len = http.getSize();
                        Serial.println(len);
        
                        // create buffer for read
                        uint8_t buff[128] = { 0 };
        
                        // get tcp stream
                        WiFiClient * stream = http.getStreamPtr();
        
                        // read all data from server
                        while (http.connected() && (len > 0 || len == -1)) {
                            // get available data size
                            size_t size = stream->available();
        
                            if (size) {
                                // read up to 128 byte
                                int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
        
                                // write it to Serial
                                //Serial.write(buff, c);
                                myFile.write(buff, c);
        
                                if (len > 0) {
                                    len -= c;
                                }
                            }
                            delay(1);
                        }
                        stream->flush();
                        myFile.close();
                        Serial.println();
                        Serial.print("[HTTP] connection closed. File write end.\n");
        
                    }
                }
                else {
                    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
                }
        
                http.end();
                http.~HTTPClient();
                server.send(200, "text/html", "File write Success.");
            });
        
            //Start the server
            server.begin();
            Serial.println("HTTP server(local) started");
        }
        
        void loop() {
            server.handleClient();
            //delay(100);
            if (WiFiMulti.run() != WL_CONNECTED) {
                Serial.print(".");
                delay(1000);
            }
            else {
        
            }
        }
        

1 个答案:

答案 0 :(得分:0)

问题的根源在于

String line = "";

请不要使用String类来获得可靠的性能。 原因-这会刺穿您的堆并导致内存泄漏->崩溃并重置

用于阅读以html,js,bmp等形式发送到浏览器的方法:

 const char* path = "\myfolder\myfile.html";

 FILE_SYSTEM can be either SD, SPIFFS, LittleFS

 File dataFile = FILE_SYSTEM.open(path, "r");
  ... do all sorts of checking if needed
 // e.g. contentType = F("text/html"); -> determined by a function analysing the  
 file extension 

 if (server.streamFile(dataFile, contentType) != dataFile.size()) {
}       // sends the file tothe browser

仅用于下载到PC机

 contentType = F("application/octet-stream")

Avr开发技巧。摆脱String类并坚持使用c-char数组。刚开始时辛苦,但最后却付出了。