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 .
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.
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.