problemi caricamento progetto

Salve caricando un programma mi appare a fondo pagina la seguente dicitura:
Lo sketch usa 14820 byte su 32256.
Le variabili globali usano 1551 byte di memoria dinamica.
Poca memoria disponibile, potrebbero presentarsi problemi di stabilità.

Vorrei sapere, siccome è la prima volta che mi succede, come posso risolvere e se è un problema.

Grazie mille.
Saluti Andrea

è un problema? Dipende. Puoi risolvere? Dipende.
L'IDE può verificare solo la memoria statica per le variabili globali, se fai largo uso di variabili locali o dinamiche può essere un problema di difficile risoluzione.
La soluzione ricade in una vera e propria filosofica di programmazione, la filosofia del risparmio di memoria. Cerca di usare la memoria minima indispensabile, se ti serve un byte di memoria non usare un int ma un char, se ti serve un array da 10 elementi non allocare spazio per 100 valori. Se hai una variabile che rimane costante per tutto lo sketch usa una define (esempio per dichiarare i pin).
Ti consiglierei la lettura di questo articolo.

...se ti serve un byte di memoria non usare un int ma un char...

Perché non usare il byte?

Perché come peso sono identiche e in C vengono percepite in modo identico, non vi è neanche la differenza come tra unsigned int e int.
Io comunque uso principalmente il set di AVR IO quindi uint8_t e sviluppando prevalentemente per applicazioni di basso livello non parlo mai di interi o long ma di uin16_t e uint32_t o ancora meglio matrici di uint8_t.
Chiamiamolo come vogliamo l'importante è usare meno memoria possibile.

Perché non usare il byte?

perché int è signed come char, byte è unsigned.

RobertoBochet:
Perché come peso sono identiche e in C vengono percepite in modo identico,

Che byte e char hanno lo stesso peso è vero, però sono percepite in modo differente in C visto che byte è un alias per unsigned char, se dentro un char metti 255 nei calcoli vale -1 e non 255 e la cosa fa molta differenza.
Un errore tipico dei programmi, sopratutto da parte dei principianti, è proprio usare char al posto di unsigned char, o viceversa, per dei valori numeri per poi trovarsi con risulti bizzarri nei calcoli.

Allora chiedo scusa, ho sempre trattato i char nella loro semplice forma di carattere o al massimo binaria, non ricordavo che il compilatore lo trattasse con segno. Ripeto, tendo ad usare le forme intx_t proprio per non commettere errori e/o equivoci sul peso delle variabili.

Edit:
Astro, correggimi se sbaglio, ho cercato in giro ed effettivamente sono molte le dichiarazioni dove viene specificato che il char non ha una definizione di default nel C, ed è il compilatore che definisce il suo intervallo di default. Sono persone poco attente o effettivamente il C non definisce se char è signed o unsigned.

Ringrazio tutti per le risposte. Lo sketch sul quale sto lavorando apparentemente non è molto grande (passatemi i termini molto elementari), penso quindi ci sia qualcosa che dia fastidio. Provo a inserire lo sketch.

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // mac address
byte ip[] = { 192, 168,0, 70 }; // ip arduino internet in
EthernetServer server(80); //server port
String readString;
void setup()
{
Ethernet.begin(mac, ip);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
}
void loop(){
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
readString.concat(c); //memorizzo ogni carattere della stringa
//if HTTP request has ended
if (c == '\n' && currentLineIsBlank) {
if(readString.indexOf("on_1") > 0)digitalWrite(2,HIGH);
if(readString.indexOf("off_1") > 0)digitalWrite(2,LOW);
if(readString.indexOf("on_2") > 0)digitalWrite(3,HIGH);
if(readString.indexOf("off_2") > 0)digitalWrite(3,LOW);
if(readString.indexOf("on_3") > 0)digitalWrite(4,HIGH);
if(readString.indexOf("off_3") > 0)digitalWrite(4,LOW);
if(readString.indexOf("on_4") > 0)digitalWrite(5,HIGH);
if(readString.indexOf("off_4") > 0)digitalWrite(5,LOW);
if(readString.indexOf("on_5") > 0)digitalWrite(6,HIGH);
if(readString.indexOf("off_5") > 0)digitalWrite(6,LOW);
if(readString.indexOf("on_6") > 0)digitalWrite(7,HIGH);
if(readString.indexOf("off_6") > 0)digitalWrite(7,LOW);
if(readString.indexOf("on_7") > 0)digitalWrite(8,HIGH);
if(readString.indexOf("off_7") > 0)digitalWrite(8,LOW);
if(readString.indexOf("on_8") > 0)digitalWrite(9,HIGH);
if(readString.indexOf("off_8") > 0)digitalWrite(9,LOW);
// COSTRUZIONE PAGINA HTML
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
// inizializzo pagina (da togliere se uso ajax)
client.print("ANDREINO Controllo WEB");
client.print("

");
//inizai il body
client.print("STATO PIN 2 ");
if(digitalRead(2)==true) client.print("<input disabled="disabled" maxLength="50" size="12" value="ACCESO" STYLE="background-color:#00FF00"/>");
else client.print("<input disabled="disabled" maxLength="50" size="12" value="SPENTO" STYLE="background-color:#C0C0C0"/>");
client.print("

");
client.print("<input type="button" style="width:50px; height:30px" value="On" onclick=" location.href='/?on_1'">");
client.print("<input type="button" style="width:50px; height:30px" value="Off" onclick=" location.href='/?off_1'">");
client.print("

");
client.print("STATO PIN 3 ");
if(digitalRead(3)==true) client.print("<input disabled="disabled" maxLength="50" size="12" value="ON" STYLE="background-color:#00FF00"/>");
else client.print("<input disabled="disabled" maxLength="50" size="12" value="OFF" STYLE="background-color:#C0C0C0"/>");
client.print("

");
client.print("<input type="button" style="width:50px; height:30px" value="On" onclick=" location.href='/?on_2'">");
client.print("<input type="button" style="width:50px; height:30px" value="Off" onclick=" location.href='/?off_2'">");
client.print("

");
client.print("STATO PIN 4 ");
if(digitalRead(4)==true) client.print("<input disabled="disabled" maxLength="50" size="12" value="ON" STYLE="background-color:#00FF00"/>");
else client.print("<input disabled="disabled" maxLength="50" size="12" value="OFF" STYLE="background-color:#C0C0C0"/>");
client.print("

");
client.print("<input type="button" style="width:50px; height:30px" value="On" onclick=" location.href='/?on_3'">");
client.print("<input type="button" style="width:50px; height:30px" value="Off" onclick=" location.href='/?off_3'">");
client.print("

");
readString="";
delay(1);
client.flush();
client.stop();
}
}
}
}
}

Per il problema della memoria posso utilizzare solo 3 degli 8 pin. Grazie mille per l'attenzione.

Saluti Andrea

Tutte le volte che passi una stringa ad una funzione questa deve essere caricata nella ram, quindi negli sketch dove si parla di webserver è facile esaurire la memoria, puoi usare il costrutto F() per forzare il caricamento delle stringhe solo nella flash
esempio

F("<input type=\"button\" style=\"width:50px; height:30px\" value=\"Off\" onclick=\" location.href='/?off_3'\">")

Oppure un altro metodo molto usato e secondo me che permette la maggior espansione è sfruttare la SD per conservare le pagine html cosi da poterle caricare e scaricare dalla memoria.

RobertoBochet:
Tutte le volte che passi una stringa ad una funzione questa deve essere caricata nella ram, quindi negli sketch dove si parla di webserver è facile esaurire la memoria, puoi usare il costrutto F() per forzare il caricamento delle stringhe solo nella flash
esempio

F("<input type=\"button\" style=\"width:50px; height:30px\" value=\"Off\" onclick=\" location.href='/?off_3'\">")

Oppure un altro metodo molto usato e secondo me che permette la maggior espansione è sfruttare la SD per conservare le pagine html cosi da poterle caricare e scaricare dalla memoria.

Grazie mille RobertoBochet, per l'utilizzo della SD un passo alla volta. Quindi se ho ben capito il tuo suggerimento è quello di eliminare il client.print() e inserire F()? Un'altra domanda come faccio a copiare correttamente nei post il codice, penso di aver sbagliato a copiarlo in quel modo? Grazie ancora.

RobertoBochet:
Edit:
Astro, correggimi se sbaglio, ho cercato in giro ed effettivamente sono molte le dichiarazioni dove viene specificato che il char non ha una definizione di default nel C, ed è il compilatore che definisce il suo intervallo di default. Sono persone poco attente o effettivamente il C non definisce se char è signed o unsigned.

Il char è un tipo dato standard del C e perfettamente definito fin dalla prima versione del linguaggio, può essere interpretato in due modi, o come valore numerico a 8 bit con segno, range operativo da 127 a -128, oppure come singolo carattere ASCII, o altra codifica, facente parte di un array di caratteri, da cui il nome char.
Ovviamente è il compilatore che determina cosa contiene una variabile in base alla sua dichiarazione, i vari alias tipo uintx_t, intx_t (definiti in cstdint.h) sono nati per evitare confusioni e ambiguità per chi legge il codice e per il compilatore, sopratutto per via del fatto che a seconda del tipo di micro e della sua word un intero può essere sia 16, che 24, che 32, che 64 bit, pertanto definire semplicemente una variabile int può causare grossi problemi se si fa il porting del codice tra micro diversi e con diversa lunghezza della word, p.e. da un AVR a un ARM.

No il codice diventa

client.print(F("<input type=\"button\" style=\"width:50px; height:30px\" value=\"Off\" onclick=\" location.href='/?off_3'\">"));

F, come dire è una macro che esegue un particolare cast della stringa che gli viene passata, tutto questo a livello di preprocessore.

Astro, l'ho chiesto solo perché con una ricerca con google ho trovato molti che affermano che char diviene definito con precisione se viene preceduto da unsigned o signed e in caso contrario la scelta sta al compilatore.
Ok, buono a sapersi, purtroppo su internet ci sono troppe informazioni poco affidabili sparpagliate in giro.

RobertoBochet:
F, come dire è una macro che esegue un particolare cast della stringa che gli viene passata, tutto questo a livello di preprocessore.

F non fa nessun casting, è un modo semplice per usare PROGMEM (pgmspace.h) e porre il contenuto della stringa nella flash invece della ram.

Astro, l'ho chiesto solo perché con una ricerca con google ho trovato molti che affermano

Quei molti o sparano cavolate oppure usano compilatori cineseria :slight_smile:
In C/C++ i tipi dati sono rigorosamente definiti, se definisci un dato come char è sempre e comunque un numero con segno o una codifica caratteri, non sarà mai e poi mai un dato senza segno.
Sebbene esiste anche la possibilità di scrivere "signed char", utile per distinguere nel codice una variabile che contiene sicuramente dei numeri e non delle codifiche di caratteri, dal punto di vista del compilatore char e signed char sono la stessa cosa e vengono trattati allo stesso modo, che poi dal punto di vista delle eventuali warning cambia qualcosa a seconda del compilatore questo è un altro paio di maniche.

astrobeed:
F non fa nessun casting, è un modo semplice per usare PROGMEM (pgmspace.h) e porre il contenuto della stringa nella flash invece della ram.

Si ok, hai ragione, volevo solo dare un idea a spanne, se inizi a parlare di PROGMEM qui la gente inizia a dileguarsi!

RobertoBochet:
Si ok, hai ragione, volevo solo dare un idea a spanne, se inizi a parlare di PROGMEM qui la gente inizia a dileguarsi!

Grazie mille penso di aver risolto, ora proverò ad ampliare il codice per vedere il risultato. Alla prossima e spero in futuro di dare meno noie.