Aiuto con charArray

Buongiorno a tutti.
Ho realizzato uno sketch che gira perfettamente su Arduino Uno e che sfrutta un HMI Nextion ed una libreria non originale per il suo controllo (Libreria Nextion - uso questa perchè è più semplice per quel che devo fare).

Il problema è che, come dice l'IDE:

Lo sketch usa 25.650 byte (79%) dello spazio disponibile per i programmi. Il massimo è 32.256 byte.
Le variabili globali usano 1.340 byte (65%) di memoria dinamica, lasciando altri 708 byte liberi per le variabili locali. Il massimo è 2.048 byte.

Poichè l'HMI ha un controllo a stringhe, vorrei evitare di incappare in blocchi o frammentazioni della ram che portino a blocchi del sistema nel lungo periodo.

Attualmente le stringhe fisse le ho spostate in flash con la funzione F(), ma vorrei impiegare il più possibile le charArray solo che mi trovo bloccato quando devo estrapolare alcuni valori dalle stringhe in arrivo.

Esempio:

  //----- Inserimento Dati RTC -----
  if (message.substring(0, 4) == F("70 H"))
  {
    Ore = (message.substring(4, 6)).toInt();
    Minuti = (message.substring(6, 8)).toInt();
    Giorno = (message.substring(9, 10)).toInt();

    setTime(Ore, Minuti, Secondi, GiornoSync, 4, 2015);
    RTC.set(now());
  }

In questo caso quando ricevo una stringa che inizia con 70 H devo poter estrapolare i valori di Ore, Minuti e Giorno dalla stringa stessa (la stringa intera è: 70 H235905 dove 23 sono le ore, 59 sono i minuti e 05 è il giorno della settimana).

Come faccio ad estrapolare due valori consecutivi dall'array anzichè solo quello dell'index tra parentesi quadre?

Per le stringhe classiche del C, ovvero array/vettori di char, usa le funzioni strxxx() della libreria standard.
Per il confronto ad esempio usa strcmp() string compare. Ancora meglio strncmp() dove dici quanti caratteri confrontare.
Per copiare da array ad array, strcpy(), la lunghezza di una stringa strlen()
Poi essendo questo tipo di stringhe degli array, puoi accedere ad un elemento alla volta con le quadre.
Per la conversione, invece di usare funzioni tipo atoi() che richiedono il vettore finisca con NULL (ovvero '\0' ovvero 0) puoi fare tu il calcolo leggendo semplicemente i due char di ogni numero e i numeri come ascii sono dal valore '0'=48 al '9'=57 quindi togli 48 ed hai il valore della singola cifra.

char buf[21];
message.toCharArray(buf,20);
if(strncmp(buf,"70 H",4)==0)    // if (message.substring(0, 4) == F("70 H"))
{ // esempio: "70 H235905"
  //  indice:  0123456789
  ore=(buf[4]-48)*10+buf[5]-48;    // '2' ovvero ascii 50-48=2   2*10+'3'-48
}

Grazie per l'aiuto... corro subito a studiare!
Per quanto riguarda invece l'estrazione dei valori sconosciuti, come ad esempio il valore di ore, minuti e giorno dell'esempio come posso fare non potendo fare una comparazione perchè non so a priori il valore?

Per la conversione, invece di usare funzioni tipo atoi() che richiedono il vettore finisca con NULL (ovvero '\0' ovvero 0) puoi fare tu il calcolo leggendo semplicemente i due char di ogni numero e i numeri come ascii sono dal valore '0'=48 al '9'=57 quindi togli 48 ed hai il valore della singola cifra.

No ma sono stordito... me lo avevi anche scritto prima ma non l'ho letto. :frowning:
Scusami.

No, è che ho scritto il post in due momenti diversi, visto che era lungo e sono andato a prendere i vari link.

Allora.
Ho sostituito tutto come mi è stato suggerito ma ho notato due peggioramenti:

  • L’uso di ram è aumentato (mentre la flash è diminuita): flash dal 79% al 73% e RAM dal 65% al 66%
  • Lo sketch è diventato instabile, ma non mi spiego il motivo…

Allego il file principale, magari ho sbagliato qualcosa…

OpenGARDEN_8HD_2.ino (16.5 KB)

L'instabilità è difficile da trovare.

Per quanto riguarda la SRAM libera... ti inganna quel calcolo fatto dal IDE.
NON devi pensare che l'ammontare di memoria dinamica sia ANCHE quella che verrà usata quando il programma è in esecuzione. Quel calcolo tiene conto SOLO delle variabili globali.
Naturalmente ora hai un message che è un vettore da 20 caratteri fisso, quindi il compilatore tiene conto anche di quei 20. Con la libreria String quello non occupa subito 20 char ma dinamicamente poi occuperà memoria dinamica.

In esecuzione l'unica è stampare periodicamente quanta SRAM è libera usando la funzione freeRam()

int freeRam () {
 extern int __heap_start, *__brkval; 
 int v; 
 return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

1.Per sapere se non ha nulla dentro questo non mi pare il massimo:

if (strcmp(message, "") != 0)
    Serial.println(message);

Più semplice if( strlen(message) != 0)

2.Per l'instabilità questo mi lascia dubbi: myNextion.listen().toCharArray(message, 20);
Prova a farlo in due passaggi, logicamente sprechi memoria, ma è per capire se è quella a dare problemi.

String xxx=myNextion.listen();
xxx.toCharArray(message, 19);         // 1 char è per NULL !!!!

E ricorda che hai un array di 20 ma 1 char è sprecato/usato per finestringa '\0' ovvero NULL ovvero 0
Purtroppo la libreria che usi (non conosco quella originale) è piena zeppa di String. Vuole parametri String e ritorna String invece dei più semplici array di char.

  1. Credo che i sendCommand() accettino l'uso di F() visto che non richiede uno String

Per il punto 3, se uso F() non compila e mi restituisce questo errore:

OpenGARDEN_8HD_2.ino: In function 'void setup()':
OpenGARDEN_8HD_2.ino:233:65: error: no matching function for call to 'Nextion::sendCommand(const __FlashStringHelper*)'
OpenGARDEN_8HD_2.ino:233:65: note: candidate is:
In file included from OpenGARDEN_8HD_2.ino:37:0:
C:\Users\gualandd\Documents\Arduino\libraries\nextion-master/Nextion.h:90:8: note: void Nextion::sendCommand(const char*)
   void sendCommand(const char* cmd);
        ^
C:\Users\gualandd\Documents\Arduino\libraries\nextion-master/Nextion.h:90:8: note:   no known conversion for argument 1 from 'const __FlashStringHelper*' to 'const char*'
no matching function for call to 'Nextion::sendCommand(const __FlashStringHelper*)'

Per il resto grazie per il consiglio sul check della lunghezza di message.

Per l’instabilità ho visto che sia come era prima che come mi hai suggerito tu, lui legge correttamente solo il primo messaggio in arrivo e non i successivi, come se non vi fossero cambiamenti del contenuto di message. :o

[EDIT]: ho inserito memset(message, 0, sizeof(message)); dopo ogni elaborazione della stringa in arrivo e per il momento sembra piuttosto stabile.
Grazie per l’aiuto.