Ottimizzare codice

Ciao a tutti,

sto osservando gli esempi delle varie librerie di Arduino e mi sono imbattuto nella libreria multichannel gas sensor http://wiki.seeedstudio.com/Grove-Multichannel_Gas_Sensor/

la quale propone questo codice per rilevare/stampare dati:

float c;

  c = gas.measure_NH3();
  Serial.print("The concentration of NH3 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");
  

  c = gas.measure_CO();
  Serial.print("The concentration of CO is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");
  
  c = gas.measure_NO2();
  Serial.print("The concentration of NO2 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

  c = gas.measure_C3H8();
  Serial.print("The concentration of C3H8 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

  c = gas.measure_C4H10();
  Serial.print("The concentration of C4H10 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

  c = gas.measure_CH4();
  Serial.print("The concentration of CH4 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

  c = gas.measure_H2();
  Serial.print("The concentration of H2 is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

  c = gas.measure_C2H5OH();
  Serial.print("The concentration of C2H5OH is ");
  if (c >= 0) Serial.print(c);
  else Serial.print("invalid");
  Serial.println(" ppm");

secondo voi è possibile riscrivere ciò in forma più compatta risparmiando di conseguenza memoria?

Risposta breve sì
Risposta lunga: fai un ciclo, pre-stampi le parti fisse, con uno switch selezioni le parti variabili, finito

ciao...poi nella Serial.print() che contengono le stringhe potresti usare la F() in modo da spostare l'occupazione di memoria nella flash.
quindi, per esempio, la:

Serial.print("The concentration of NH3 is ");

dovrebbe divenire:

Serial.print(F("The concentration of NH3 is "));

Grazie mille per le risposte...

sto facendo ora dei test con sprintf, ma sicuramente sto sbagliando qualcosa, sto provando su un semplice sensore di temperatura/umidità dht11

questo codice:

  Serial.println(dht.readTemperature());
  Serial.println( dht.readHumidity());

mi permette di ottenere

20.00
35.00

di conseguenza io ho ipotizzato una stringa come segue:

  sprintf(umid_temp,  "Temperatura:%02.2f °C -- Umidità: %03.2f %",dht.readTemperature(), dht.readHumidity());

ma questa viene restituita cosi

Temperatura:  ? °C -- Umidità:   ?

dove sto sbagliando? :roll_eyes:

sprintf() & Co. su Arduino non supportano i float.

In ogni caso, sprintf() è una funzione molto complessa, che probabilmente farebbe aumentare l’uso di RAM e flash del tuo sketch, invece di diminuirla.

A parte cambiare tutte le .print e .println che non usino variabili usando la macro F(), come già suggerito vedo che molte parti del codice sono più o meno ripetute. Mi pare infatti che lo schema base sia:
Scrivo "the concentration of "
Scrivo la formula di una sostanza variabile
Scrivo "is" e vado a capo
Creo un float con lo stesso nome sempre
Al quale do il valore di una funzione variabile
Se il float é >=0 lo scrivo
Se no scrivo il messaggio di errore, che é costante.

Di conseguenza penserei comodo l'utilizzo di una for() che raduni le parti comuni e nella quale, con una switch case, inserisca quelle variabili.
Prova a scrivere e vediamo se é una castroneria

una cosina del tipo

for (byte i=0; i<6;stampa(i++));

.
.
.

void stampa(byte index){
// a seconda dell'indice stampa different letture e scritte
float c;
Serial.print(F("La concentrazione di "));

Switch (index){
case 0:
Serial.print(F("NH3"));
c = gas.measure_NH3();

break;
case 1:
Serial.print(F("CH4 (metano)"));
c = gas.measure_CH4();
break;
default:
Serial.print(F(" Sconosciuto"));
c=0;
break;
.... proseguire con gli altri gas
}


Serial.print(F(" e': ")); // controllare corretto uso apostrofo
  if (c >= 0) 
Serial.print(c);
  else 
Serial.print(F("valore non valido"));

  Serial.println(F(" ppm"));

}

Scritta qui al volo senza ne compilarla ne provarla, serve solo da ispirazione

Infinite grazie, risolto cosi:

void loop()
{
  
for (byte i=0; i<8;stampa(i++));
delay(2000);

}

void stampa(byte index){

float c;
Serial.print(F("Concentrazione di "));

switch(index){
  
case 0:
Serial.print(F("NH3 (ammoniaca)"));
c = gas.measure_NH3();
break;



case 1:
Serial.print(F("CO (monossido di carbonio)"));
c = gas.measure_CO();
break;


case 2:
Serial.print(F("NO2 (diossido di azoto)"));
c = gas.measure_NO2();
break;


case 3:
Serial.print(F("C3H8 (propano)"));
c = gas.measure_C3H8();
break;

case 4:
Serial.print(F("C4H10 (butano)"));
c = gas.measure_C4H10();
break;

case 5:
Serial.print(F("CH4 (metano)"));
c = gas.measure_CH4();
break;


case 6:
Serial.print(F("H2 (idrogeno)"));
c = gas.measure_H2();
break;


case 7:
Serial.print(F("C2H5OH (etanolo)"));
c = gas.measure_C2H5OH();
break;


default:
Serial.print(F(" Sconosciuto"));
c=0;
break;

}


Serial.print(F(": ")); 
  if (c >= 0) 
Serial.print(c);
  else 
Serial.print(F("valore non valido"));

  Serial.println(F(" ppm"));


}

Grazie
fa piacere vedere che le idee lanciate vengono raccolte e fatte crescere

Era il minimo condividere la soluzione finale...
ora però ho lo stesso dilemma sulle informazioni dell'orario modulo RTC, le quali vengono stampate in seriale, in bluetooth e su sd

 DateTime now = RTC.now(); 
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    bt.print(now.year(), DEC);
    bt.print('/');
    bt.print(now.month(), DEC);
    bt.print('/');
    bt.print(now.day(), DEC);
    bt.print(' ');
    bt.print(now.hour(), DEC);
    bt.print(':');
    bt.print(now.minute(), DEC);
    bt.print(':');
    bt.print(now.second(), DEC);
    bt.println();
    datafile.print(now.year(), DEC);
    datafile.print('/');
    datafile.print(now.month(), DEC);
    datafile.print('/');
    datafile.print(now.day(), DEC);
    datafile.print(' ');
    datafile.print(now.hour(), DEC);
    datafile.print(':');
    datafile.print(now.minute(), DEC);
    datafile.print(':');
    datafile.print(now.second(), DEC);
    datafile.print(" ; ");

esiste un metodo migliore?

Forse due cicli innestati. Passando un puntatore a stream dal primo al secondo

Comunque tra un codice ottimizzato ma incomprensibile e uno non ottimizzato e comprensibile, io preferisco il secondo.

PaoloP:
Comunque tra un codice ottimizzato ma incomprensibile e uno non ottimizzato e comprensibile, io preferisco il secondo.

anche io, il problema è che quando inizia a comparire la scritta rosso/arancione che avvisa che la memoria è al limite (e di mezzo può esserci instabilità) non è mai troppo piacevole :grin:

maggiori dettagli, ram, flash, programma, variabili?

Standardoil:
maggiori dettagli, ram, flash, programma, variabili?

Questo è l'output che ho dall'IDE

Lo sketch usa 20520 byte (63%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 1540 byte (75%) di memoria dinamica, lasciando altri 508 byte liberi per le variabili locali. Il massimo è 2048 byte.
Poca memoria disponibile, potrebbero presentarsi problemi di stabilità

ma poi i problemi di stabilità li hai realmente?
perché se hai scritto codice ben rientrante e che usa poche variabili locali potrebbe bastare così
il problema 63% dello spazio per i programmi è un non problema, i programmi sono statici, anche se ci stessero per un byte ci sono stati, non sono come i bambini in gita scolastica, non si muovono dentro nell'autobus, non aumentano di spazio occupato, se ci sono stati ci sono stati
per le variabili invece il discorso è differente:
la variabili globali, quelle dichiarate prima della loop per intenderci, ecco quelle sono "statiche", mi si passi la parola anche se in C static è cosa differente
anche loro non si muovono e non "ingrassano"
differente per le variabili locali, dichiarate dentro una funzione o dentro un "blocco" tipicamente dentro un for
quelle NON sono contate, perché nascono occupando memoria e muoiono liberando memoria assieme alle loro funzioni, e magari tra le globali e le locali sfori
ci sono varie maniere per misurare la memoria libera durante l'esecuzione del programma, ma io non le conosco
magari alcuni più esperti di me ce le insegnano
comunque se posti il programma sappiamo farci un'idea

75% non è così critico.

Standardoil:
perché se hai scritto codice ben rientrante e che usa poche variabili locali potrebbe bastare così

Sottovaluti il potere delle “String”… :wink:

Ma le String sono il lato nero....
Ho sbagliato a usarle una volta, e ne porto ancora i segni
Anno' quello era il nerbo di bue...

"Use the String, max95, use the String ... and come to the dark side ..."