accodamento String e char array

Ciao a tutti. Ho la necessità di accodare un String e un char array per poterli stampare sulla seriale per controllare a che punto è il programma e se legge tutto.
Il primo “accodamento” funziona, quando inserisco il secondo non vedo più nulla. potete darmi una mano?
allego file codice. l’errore si verifica quando decommento la riga 56-58.

AllarmeTemperatura_SIM900.ino (7.55 KB)

In primo luogo perché devi accodarle per scrivere su seriale? Non vasta fare due Serial.print? Credo che accetti anche oggetti String, i char* li accetta certamente. Inoltre il consiglio é sempre di ridurre al minimo (0) l'uso di String, che alla lunga creano problemi di memoria

ho provato con char *, ma continuo ad avere problemi. Finchè uso il codice sotto riportato ottengo a video ciò che voglio.

void setup() 
{   
    Serial.begin(9600);

    //Leggo dalla memoria e inizializzo le variabili
    readSetup();
    Serial.println(receiverNumber1);
    Serial.println(receiverNumber2);
    Serial.println(TargetTempMin);
    Serial.println(TargetTempMax);

    char *cTxt = "Numero telefono 1 = ";
    Serial.print(cTxt);
    Serial.println(receiverNumber1);
}

quando aggiungo questo non funziona più nulla

       cTxt = "Numero telefono 2 = ";
       Serial.print(cTxt);
       Serial.println(receiverNumber2);

... strano perché se provi questo codice d'esempio funziona correttamente ... ::)

void setup() {
  // put your setup code here, to run once:
  char* cTxt = "Testo 1 ";
  unsigned long numero = 12345678;

  Serial.begin(115200);
  
  Serial.print("Test 1: ");
  Serial.print(cTxt);
  Serial.println(numero);

  cTxt = "Nuovo testo inserito ";
  Serial.print("Test 2: ");
  Serial.print(cTxt);
  Serial.println(numero);

  cTxt = "Terzo testo ";
  Serial.print("Test 3: ");
  Serial.print(cTxt);
  Serial.println(numero);

}

void loop() {
  // put your main code here, to run repeatedly:

}

... e funziona anche se sostituisci la riga :

unsigned long numero = 12345678;

con la riga:

String numero = "12345678";

... del resto, non vedo perché non dovrebbe ::)

Guglielmo

c'è differenza tra i due modi di scrivere?

char *cTxt =
char* cTxt =

Patrick_M: c'è differenza tra i due modi di scrivere?

... da quando in 'C' lo spazio è significativo all'interno degli statements ? ? ? :o

Toglilo e compila uguale :D :D :D

Guglielmo

immaginavo ma volevo esserne sicuro :smiley: quando uno si abitua a scrivere in un modo …se lo vedi messo diverso ti viene un dubbio (a me) :slight_smile:

allora aggiungo.... ma non è che la seconda parte (l'aggiunta) viene fatta nel loop per caso :) ... ... però dipende da cosa vuol dire "non funziona più nulla"

Ho fatto le modifiche come suggerito e adattato alle mie esigenze. ora funziona sia così

char* cTxt = "Numero telefono 1 = ";
    Serial.print(cTxt);
    Serial.println(receiverNumber1);

    cTxt = "Numero telefono 2 = ";
    Serial.print(cTxt);
    Serial.println(receiverNumber2);

    cTxt = "Temperatura massima = ";
    Serial.print(cTxt);
    Serial.println(TargetTempMax);

    cTxt = "Temperatura minima = ";
    Serial.print(cTxt);
    Serial.println(TargetTempMin);

che così

Serial.print("Numero telefono 1 = ");
    Serial.println(receiverNumber1);

    Serial.print("Numero telefono 2 = ");
    Serial.println(receiverNumber2);

    Serial.print("Temperatura minima = ");
    Serial.println(TargetTempMin);

    Serial.print("Temperatura minima = ");
    Serial.println(TargetTempMax);

anche se sospetto che il compilatore qualche volta sbagli a far qualcosa... avrò provato 1000 volte l'ultima soluzione, ma non funzionava.

Specifico che le variabili che stampo con println sono così dichiarate:

char    receiverNumber1[11] = "0000000000"; 
char    receiverNumber2[11] = "0000000000"; 
char    TargetTempMin[3] = "00";
char    TargetTempMax[3] = "00";

può essere questo un problema?

La dichiarazione è corretta anche se l'inizializzazione con tutti gli zeri (carattere) è superflua anzi no perchè la usi come test se è presente in numero di telefono, in realtà occorrerebbe vedere come assegni alle stringhe il valore di temperatura e numeri di telefono, perché il programma allegato al primo post non credo sia più quello in uso. A parte cose veramente particolari tenderei ad escludere bug nel compilatore. Altra cosa se le stringhe ti servno solo per stamparle sulla seriale usa la funziione F() per tutte le stringhe fisse

Serial.print(F("Temperatura minima = "));

Risparmi memoria mettendo le stringhe nell'area programmi.

Ri-allego il codice che sto usando che non è molto differente dal primo. le variabili le valorizzo in questo modo: leggo da eeprom e converto da char a string e da string a char in quanto non ho trovato un modo per lavorare solo con char.

void readSetup()
{   
    ReadEEPROM(1,10).toCharArray(receiverNumber1,sizeof(receiverNumber1));

    ReadEEPROM(15,10).toCharArray(receiverNumber2,sizeof(receiverNumber2));

    ReadEEPROM(35,2).toCharArray(TargetTempMax,sizeof(TargetTempMax));

    ReadEEPROM(30,2).toCharArray(TargetTempMin,sizeof(TargetTempMin));
}

String ReadEEPROM(int iIxStart, int iLen)
{
    char    cResult[iLen];
    int iStart  =   iIxStart;
    int iStop   =   iIxStart +  iLen    -   1;  
    for (int j = 0;j

stefano_8805: ... anche se sospetto che il compilatore qualche volta sbagli a far qualcosa ...

:D :D :D ... ma non ci pensare nemmeno, per queste cose l'affidabilità del compilatore è fuori discussione!

Due sono i casi, qualche errore logico nel codice che sfugge alla vista (99% dei casi) o, in rari casi, piccoli casini che fa l'IDE di Arduino, ma sono veramente casi specifici che coinvolgono assieme sorgenti suddivisi in varie parti, #include, prototipi di funzioni e piccol altre cose.

Guglielmo

secondo me il problema è che quasi mai hai postato il programma completo e quindi non si capisce dove poteva esserci un problema ;)

p.s. nell'ultimo codice int x = 0 e x++ a cosa servono?

codice completo allegato.
x = 0 e x++ mi servono per ciclare cresult in modo da memorizzare su ogni posizione i singoli caratteri che leggo dalla eeprom

AllarmeTemperatura_SIM900.ino (8.44 KB)

>stefano_8805:studiati bene l’allegato documento (… con particolare attenzione all’attributo EEMEM), vedrai che ti semplifichi la vita ed eviti di incasinarti con le String per quella banale funzione … :wink:

Guglielmo

P.S.: Nota che la libreria AVR libc dove di trova avr/eeprom.h è sempre inclusa automaticamente dal IDE …

EEPROM.pdf (181 KB)

stefano_8805: codice completo allegato. x = 0 e x++ mi servono per ciclare cresult in modo da memorizzare su ogni posizione i singoli caratteri che leggo dalla eeprom

si hai ragione mi era sfuggito cResult[x] = :)

gpb01 grazie mille della guida... la provo così vedo di eliminare un po' di codice superfluo. Visto che ci siamo vorrei capire se fattibile e se ha senso sostituire l'uso di string (che ho capito essere problematiche) con array of char. In particolare li ho usati su questa funzione che ha lo scopo di restituire il testo da spedire con la funzione sms.sendsms della libreria SMS

String txtFeedback(String command)
{
    command.toLowerCase();
    //Serial.println(command);
    String stxtmsg = "";
    if (command.startsWith(cntReadReceiverNumber1) || command.startsWith(cntSetReceiverNumber1))
    {
        stxtmsg.concat("Numero di telefono per allarme 1 = ");
        stxtmsg.concat(receiverNumber1);
    }
    else if (command.startsWith(cntReadReceiverNumber2) || command.startsWith(cntSetReceiverNumber2))
    {
        stxtmsg.concat("Numero di telefono per allarme 2 = ");
        stxtmsg.concat(receiverNumber2);
    }
}

e qui, nella parte di codice che spedisce messaggio di allarme. Specifico che il blocco const_cast(sTextSms.c_str()) l'ho rubato in giro in quanto usando la stringa convertita in char con la funzione String.To CharArray() risultava vuota.

                        String sTextSms = "ATTENZIONE. Temperatura rilevata ";  
            sTextSms.concat(dTemperatura);
            sTextSms.concat("C");
            Serial.println(sTextSms);
            digitalWrite(A3,1);
            digitalWrite(A5,1);
            Serial.println(sTextSms);
            if (String(receiverNumber1) != "0000000000")
            {
                sms.SendSMS(receiverNumber1, const_cast(sTextSms.c_str()));
            }
            if (String(receiverNumber2) != "0000000000")
            {
                sms.SendSMS(receiverNumber2, const_cast(sTextSms.c_str()));
            }

Va modificata una cosa: tu NON puoi restituire un array di char, tu puoi riempire un array di char, e magari restituire se lo hai fatto o meno. L'array deve esistere perché globale o perché passato come parametro alla funzione. Quanto alla parte "fattibile", quindi si, tranne per quanto sopra detto. Per " ha senso" anche, e molto. Soltanto devi conoscere la massima lunghezza sel sms, o genericamente della stringa (array di char=stringa), e l'array deve essere dimensionato di almeno tale lunghezza

Premetto che ho fatto per anni programmatore in Delphi, e quando una funzione doveva modificare più variabili, passavo la variabile come parametro della funzione. Avevo cercato se anche Arduino, e quindi C, lo permetteva, ma non avevo trovato ciò che cercavo.

Siccome sono SMS la lunghezza massima è 160, anche se in realtà sto sotto i 100 caratteri di media.

avevo provato a convertire questo blocco, ma senza successo.

String sTextSms = "ATTENZIONE. Temperatura rilevata ";  
sTextSms.concat(dTemperatura);
sTextSms.concat("C");
Serial.println(sTextSms);

Per fare ciò che facevi in delphi con il C puoi passare alla funzione le variabili per riferimento (operatore & e relativo puntatore *). Per la concatenazione della stringa invece devi studiarti le funzioni standard del c strncpy, strncat. Definisci un char array della dimensione massima dell'sms, se globale prima di ogni invio ne azzeri il contenuto (Ad esempio riempiendo l'array di char con il carattere terminatore (zero) con la funzione memset ) e poi con le funzioni indicate in precedenza ci metti le varie stringhe e poi lo spedisci senza necessità di quel blocco di codice che effettua la conversione