How to handle large web pages efficiently with W5100 and mega without an SD card ?

Hi,

I've been working on a webserver using a W5100, Ethernet.h, SD.h and a Mega2560 - thanks to the assistance of others in this forum it's now working quite nicely.

However I suspect it could be improved further in terms of speed of serving and ease of updating the html pages.

Specifically I have one webpage which is 36k in length and is served from an SD card using the following snippet of code

if (web_page == 1)
                        {
                          // send web page advanced.htm - contains version with diplay, and commands 36k in length
                          webFile = SD.open("advanced.htm");       // open web page file
                        }
                      
                        else {
                        // send web page index.htm - contains version whith with only display 6k in length
                          webFile = SD.open("index.htm");       // open web page file
                        }
                       
                        if (webFile) {
                            while(webFile.available()) {
                                client.write(webFile.read()); // send web page to client
                            }
                            webFile.close();
                        }

It takes several seconds to load the larger 36k adavnced page.

Ideally I'd like to hold both web pages in flash using progmem something like this

const char adv_html[] PROGMEM = R"rawliteral(
BIG HTML FILE  36k in length

)rawliteral";

Then have the server send these files as required to the client.

Not using a SD card may make the file transfer faster plus I can update both the HTML pages and mega code over the network at the same time - I've recently changed to optiboot8 and OTE boot loader.

I understand there's a 2k buffer limit which the original SD card version seems to over come.

Despite a lot of googling I'm yet to find an elegant way to serve large webpages from flash .

Any guidance or ideas gratefully accepted

Regards Tim

reduce the individual filesize.
spare blanks, spare tab stops, spare empty lines. You are on a 8 bit controller, so make your files as small as possible.
no need to name a page "advanced.htm" ... just name it a.htm
same might apply to variable sizes and/or id's
check your page against duplicated code (do you have a javascript?!?)
avoid inline styles, use CSS
split your "HTML" in separate files, for the javascript, the CSS, the plain HTML, ...

Thanks for the tips - I'll have a go at what you suggest but yes it's only an 8 bit processor so maybe I should consider porting the whole project over to a STM32 nucleo.
I have run other projects succesfully on a STM32F401 nucleo and this maybe another candidate !

However as a learning exercise I'd prefer to stick with the mega2560.

Regards Tim

Really not that difficult. Your original code is reading a single character from the SD card file and writing it to client, the same process should be able to be used for the char array in PROGMEM.

The only complication is if the total amount of memory used for data in PROGMEM exceeds 64K bytes, in which case you have to tell the compiler to store the data in the upper section of PROGMEM, to avoid displacing data that requires storage in the lower 64K bytes of PROGMEM.

//this is used to prevent displacing data that must be stored in the lower section of PROGMEM
#define PROGMEM_FAR __attribute__((section(".fini7")))

const char adv_html[] PROGMEM = R"rawliteral(
BIG HTML FILE  36k in length
this is some text
this is some more text
this is even more text
)rawliteral";

const char adv_html2[] PROGMEM_FAR = R"rawliteral(
BIG HTML FILE  36k in length
this is some text in far progmem
this is some more text in far progmem
this is even more text in far progmem
)rawliteral";

void setup() {
  Serial.begin(9600);
  Serial.println(F("\nstart"));

  //this code assumed no imbedded NULL characters
  for (size_t i = 0; i < strlen_P(adv_html); i++){
    Serial.write((char)pgm_read_byte(&adv_html[i]));
  }

  //get the address of the char array in FAR PROGMEM
  //  the compiler cannot calculate this properly, it must be done at run-time
  uint_farptr_t adv_html2_ptr = pgm_get_far_address(adv_html2);
  //get the length of the char array (assuming no imbedded NULL characters)
  size_t len = strlen_PF(adv_html2_ptr);
  for (size_t i = 0; i < len; i++){
    Serial.write((char)pgm_read_byte_far(adv_html2_ptr));
    adv_html2_ptr++;
  }
  
  Serial.println(F("\nend\n"));
}

void loop() {
}

Just remembered a problem you will have, there is a maximum array size of 32767 bytes, so you will need to split anything larger than that into two array, then send them sequentially.

1 Like

Ha - correct, just run into that error "size of variable ..... is too large".

Will do as you suggest - thanks again.

Hi David

A big thankyou for your help as I now have pages being served out of flash.
Looking at how you've done it makes it look so simple.

Interestingly the speed seems about the same, but it's good to have the webpages in the flash as it saves updating the SD card seperately.

In my quest for speed I think my next step will be to migrate the code (with all the associated drama) to a STM32 nucleo.

Regards Tim

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.