perchè mi si è presentato il problema che avevo posto e non credo di aver trovato risposta.
Fondamentalmente a me serve che i Serial.print vengano tutti visualizzati sul monitor seriale ma mi servirebbe anche bloccarli DA RUNTIME, cioè senza dover ricompilare il programma.
Per dirla in altro modo : per default, la variabile LogDisabilitato = 0
se ad un certo punto del programma la variabile diventa 1, sul monitor seriale non deve più apparire nulla.
Quindi il cambio di stato deve avvenire "ondeflai" cioè da dentro void loop.
E' possibile in qualche modo questa cosa ?
Si certo. Puoi fare come ti ha suggerito @Datman oppure metti il seguente codice in un file header, o anche nel file .ino.
Se lo metti nel file header proteggilo da inclusione multipla.
namespace DBG {
bool enable;
void print(const char *s) {
if (enable)
Serial.print(s);
}
}
void setup() {
Serial.begin(115200); // deve essere sempre presente
DBG::enable = true;
DBG::print("test debug");
}
void loop() {
}
Certo che adesso devi trovare il modo per impostare lo stato della variabile DBG::enable da input seriale, oppure anche via un pin.
il mio progetto ha ben 24 schede e oltre 20mila righe di programma
la soluzione di datman è quella che mi risolverebbe tutto in una botta sola, utilizzando il "sostituisci"
Quella di maurotec è molto più tecnica e me la debbo studiare perchè non conosco il metodo usato.
Speravo in un Serial.end e un rinnovato Serial.begin oppure in qualcosa a me sconosciuto. ma a quanto pare non esiste
Il Serial.end blocca gli interrupt e quindi, naturalmente, nisba
Ma mi pare che sei su piattaforma ESP e li non so se blocca gli interrupt, ma non credo. Su AVR di sicuro non blocca gli interrupt, ma ovviamente non puoi comunicare via serial monitor dopo avere fatto Serial.end(). Tuttavia le varie print continuano ad essere eseguite anche dopo end().
Come avresti intenzione di abilitare o disabilitare il debug?
Se usi end() sei costretto a leggere lo stato di un pin e agire di conseguenza. Dopo l'abilitazione del debug dovrai pure fare un flush per pulire il buffer che conterrà qualcosa poiché le print le esegue comunque.
Ho provato il serial.end su esp32 ma si "frizza" tutto.
Quindi non ho altra scelta se non fare il sostituisci (che tra l'altro è il meno invasivo ma, di contro, il più rombiballe da attuare) e/o studiarmi bene gli altri suggerimenti.
L'abilitazione/disabilitazione la governo con una variabile che cambia a seconda di quanto ricevuto da un testo payload che prendo da una connessione periodica sul mio cloud.
Quindi ... meno smanetto sul codice meglio mi sento.
Come al solito, i pensieri su cose teoricamente facili si scontrano con la realtà che complica non poco la soluzione.
Ok, il mio è solo un suggerimento che poi chi intuisce lo sviluppa, se serve. Se serve stampare un numero si devono aggiungere tutte le altre funzioni print. Di contro il vantaggio non è da poco, perché basta scrivere:
DBG::print("var = ");
DBG::print(100.225, 3);
Che è uguale alla print consueta. Il vantaggio è che il prefisso DBG:: indica DEBUG ed è facile scorrendo il codice individuare questo prefisso.
Se di ciò che ho scritto ne hai capito poco ti conviene subito puntare alla soluzione di @Datman.
PS: Si deve usare quello che si è capaci di capire come funziona.
Il metodo end() con ESP32 fa quel che deve ovvero interrompe l'invio e la ricezione dalla seriale "disattivando" le funzioni di callback associate agli interrupt e facendo il detach dei pin associati.
Se poi si chiama di nuovo il metodo begin() la seriale riprende a funzionare.
Quindi basta mettere all'inizio del loop "DebugCheck" (nella quale ovviamente si imposta il criterio di attivazione e disattivazione del debug, nel mio caso un pulsante sul pin 10 con INPUT_PULLUP) e sostituire globalmente la stringa "Serial.print" con "SerialPrint".
Esempio:
Comunque la soluzione più elegante di tutte è un oggetto stream con un solo metodo: print()
Che passa a serial o ignora a seconda di un parametro globale (o un membro protetto, ma richiede un metodo di inizializzazione)
E poi una macro che scambia i nomi tra l'oggetto stream e l'oggetto serial
Se ne fa una libreria, che viene compilata a parte e quindi non è influenzata dalla macro...
Eh, 23k byte in più non sono pochi, ma considera che le macro in sé non occupano spazio, il fatto è che ogni chiamata alla funzione "macro" equivale a quella condizione e due print, e devo supporre che tu abbia centinaia di chiamate a Serial.print per cui quel piccolo overhead si moltiplica... E non so poi su quale MCU tu stia lavorando, ma questa cosa può ovviamente risultare anche abbastanza diversa tra i processori.
Ad esempio, un test con questo codice:
Compilato per una WeMos D1 R2 mi dà 235908 bytes con Serial.print() e 235956 bytes con la macro (ovviamente abilitando la macro e commentando la "Serial.print()"), ossia solo 48 byte in più. Compilando per una ESP32 mi dà 204434 byte senza macro, e 204482 byte con la macro, solo 48 byte.
Usando tutte e 4 le macro, il programma senza macro occupa 204586 byte (sempre ESP32) contro 204682 byte, 92 byte. Anche assumendo una distribuzione uniforme delle 4 macro (cosa che non è sicuramente), direi che per arrivare a 32k in più ci vogliono circa un migliaio di chiamate in totale.
Per cui se non vuoi/puoi sprecare bytes in un programma così esteso e con così tante chiamate alla Serial non so quali altre soluzioni sufficientemente "light" possano esserci, mi spiace.
Ma perché non usi uno schema di partizione che riserva più spazio per il firmware (quello di default sono circa 1.3Mbyte) e convivi felice e sereno con il Serial.println() & Co. ???