Task leOS, strano problema.

E cioè io creo il task e gli metto come intervallo il tempo di scrolling che voglio una riga e l'altra.
premo enter di invio e avvio il task.

fuori abbiamo le stringhe e il contatore:
char* testo[]={"riga1", "riga2", "riga3", "rirga4"}
int contatore = 0;

void stampaInfo()
{
lcd.setCursor(0,0);
lcd.print(testo[contatore ]);
lcd.setCursor(0,1);
lcd.print(testo[contatore +1]);
delay(1000); //questo è il delay che mi serve prima che il testo scorra verso sopra

//qui faccio un controllo sul contatore
if (contatore>NUM_RIGHE)
{
contatore=0;
}
else
{
contatore++;
}

lcd.clear()
}

Non so se intendi una cosa del genere.. ma a primo impatto forse può funzionare, purtroppo non riesco a provare ho scritto ste righe al volo..

Sì, esatto (togliendo ovviamente quel delay).

Uh è vero! I copia-incolla sono e saranno una rovina..:slight_smile:

Nik_90:

void stampaInfo()

{
lcd.setCursor(0,0);
lcd.print(testo[contatore ]);
lcd.setCursor(0,1);
lcd.print(testo[contatore +1]);
delay(1000); //questo è il delay che mi serve prima che il testo scorra verso sopra

//qui faccio un controllo sul contatore
if (contatore>NUM_RIGHE)
{
contatore=0;
}
else
{
contatore++;
}

lcd.clear()
}




Non so se intendi una cosa del genere.. ma a primo impatto forse può funzionare, purtroppo non riesco a provare ho scritto ste righe al volo..

Controlla bene, questo codice non è corretto.
Rivedi la condizione per azzerare il contatore e la scrittura della seconda riga. (possibilità di index out of bound)

Cosi come lo hai scritto tu esplode! :grin:

Boh forse stai vedendo qualcosa che io ancora non vedo, come ho detto ho scirtto quelle righe al volo quindi di sicuro qualche errore ce, per sicurezza comunque ho rifatto il tutto in C.
Cercando di essere il più fedele possibile a quello che avevo scritto io è uscito questo:

#include <stdio.h>
#define NUM_RIGHE 4

int main()
{
    int contatore = 0;
    char testo[] = "1234";
    int i = 1;
    while (i == 1)
    {
          
          printf("Contatore: %i \n\n\n\n", contatore);
          printf("Riga A: %c \n" , testo[contatore]);
          printf("Riga B: %c \n" , testo[contatore+1]);
          
          if(contatore >= (NUM_RIGHE-1)) //per far vedere 4 righe ho bisogno di 4 cicli
          {
                       contatore = 0;
                       }
                       
                       else
                       {
          contatore++;
          }
          getchar();
          }
    
    
    
    }

Questo riproduce lo scorrere del display di un testo di 4 righe.
L'unico errore che ho potuto notare ora rispetto allo sketch di prima è appunto la condizione di controllo del contatore che da:

if (contatore>NUM_RIGHE)

è passata a:

(contatore >= (NUM_RIGHE-1))

Ma questo almeno in C non provoca nessun errore se non il fatto di avere un paio di cicli in più per azzerare il contatore.

E' questo giusto? Con arduino mi provocherebbe un index out of bound no?
Vabè ripeto, domani che rientro potrò provare nel caso..:slight_smile:

Grazie

Mi sembra strano che non ti dia errore, visto che tu hai un array da 4 elementi e ad un certo punto chiedi di visualizzare il quinto... però te lo lascio con riserva.(forse semplicemente perchè in C gli array sono comunque puntatori e nel tuo caso andresti a puntare fuori dallo spazio assegnato, che in questo caso è vuoto, ma se ci fosse già stato allocato qualcos'altro potresti avere un risultato inatteso)

Cosi come hai modificato va bene e ti esclude dal modificare anche ala seconda riga da visualizzare.
Praticamente come hai fatto tu vedrai l'ultima riga da visualizzare sempre nella seconda riga del display, non avrai mai la condizione in cui l'ultima riga da visualizzare passa sulla prima riga del display e la seconda viene visualizzata vuota (che potrebbe essere graficamente più accattivante).

Per quanto riguarda la condizione , un semplice 'contatore = NUM_RIGHE-1' non ti piaceva ? :grin:
Essendo un ciclo incrementale unitario non avrai mai la possibilità di andare oltre.

niki77:
Praticamente come hai fatto tu vedrai l'ultima riga da visualizzare sempre nella seconda riga del display, non avrai mai la condizione in cui l'ultima riga da visualizzare passa sulla prima riga del display e la seconda viene visualizzata vuota (che potrebbe essere graficamente più accattivante).

O.o Hai ragione, questo non l'avevo notato! No io voglio la grafica accattivamente 8) anche questa cosa è da modificare, l'ultima riga da visualizzare deve spostarsi sulla prima riga del display.. Ci vorrebbe un'altra condizione nella srittura della seconda riga.. domani che torno vediamo che succede..

niki77:
Mi sembra strano che non ti dia errore, visto che tu hai un array da 4 elementi e ad un certo punto chiedi di visualizzare il quinto... però te lo lascio con riserva.(forse semplicemente perchè in C gli array sono comunque puntatori e nel tuo caso andresti a puntare fuori dallo spazio assegnato, che in questo caso è vuoto, ma se ci fosse già stato allocato qualcos'altro potresti avere un risultato inatteso)

hai azzeccato, nessun errore, ma vai a giocare con un area di memoria in cui potrebbe esserci qualsiasi cosa. è il principio degli attachi overflow; sfruttando errori simili vai a ignettare codice o modificare variabili (per esempio la password)

Il C e il C++ non effettuano alcun controllo, e i SO controllano solo che non esci dall'area di memoria assegnata al processo/tread.

Voto anch'io per
if (contatore == (NUM_RIGHE-1))

Tornando all'errore.

L'unico errore che ho potuto notare ora rispetto allo sketch di prima è appunto la condizione di controllo del contatore che da:

if (contatore>NUM_RIGHE)

è passata a:

(contatore >= (NUM_RIGHE-1))

Secondo me il primo dà errore per questo motivo: una stringa char è composta sempre da un elemento in più, il terminatore "\0".
Quindi quando contatore è uguale a NUM_RIGHE, si va a leggere il 5° elemento della stringa, cioè l'elemento testo[4], che è appunto \0. E non dà giustamente errore. Però lui ha provato il programma sul computer, e come dice giustamente lesto, lì c'è un SO che controlla che il programma "stia nel suo", ossia che non esca dalla memoria che deve usare. Quando appunto contatore è uguale NUM_RIGHE, viene ancora incrementato, andando ad assumere il valore di 5. Adesso punterebbe al 6° elemento, che è al di fuori dell'array. Ed il SO giustamente s'inca@@a, mentre se la stessa operazione l'avesse eseguita sul 328, l'indice sarebbe semplicemente uscito al di fuori della stringa, andando a pescare a caso nella SRAM del microcontrollore.

leo72:
....una stringa char è composta ...

A parte il fatto che non è una stringa ma un array di char , l'array di char non dovrebbe avere terminatore!

Uh, è vero. E' un array.

no, il SO non si incazza se sfori un array, ma se sfori in un area di memoria non dedicata al tuo programma (il SO ti da un bel blocco all'inizio, per evitare che tu gli rompa le balle spesso)

io credo che l'errore sia quì racchiuso:

printf("Riga A: %c \n" , testo[contatore]);
printf("Riga B: %c \n" , testo[contatore+1]);

abbiamo conatore che va da 0 a 3 (giusto), ma la riga B la andiamo a prendere dall'elemento conatatore+1, quindi di fatto usiamo il range da 1 a 4 (sbagliato)

ora, se ci va di culo e dalla locazione di memoria 4 in poi troviamo relativamente presto uno \0 visualizziamo garbage. Ora, è poco probabile trovare uno \0 lì per caso, considerando che abbiamo un range di 256 valori (probabilità di 1/256). quindi probabilmente in un atmega sfondi la ram e chissà cosa succede.

Su un PC, oltre ad avere un sacco di ram in più (non parlo della ram totale, ma di quella assegnata al programma), hai anche il controllo del SO, quindi se nella ram assegnata non trovi lo \0 ci pensa il SO a mandarti in crash.

@niki77 & leo: gli array di char sono dette stringhe, da non confondere con le String che invece sono un oggetto. per riprova, esiste una libreria ansi C, la string.h, che lavora sugli array di char.
e no, gli array di char SONO terminati a \0. Anche la classe Stringa al suo interni usa un array di char terminato con \0. solo che non te lo fa vedere.

Si, mi sa che ha ragione lesto...
O meglio, non lo so, ma ho scritto due righe di codice che danno un risultato interessante...

#include <stdio.h>

int main()
{
    char testo[] = "1234";
	char testo1[] = "1234";

	char * ptr = testo;
	char * ptr1 = testo1;

	ptr+=4;

	*ptr = 'A';

	printf("testo: %s \n", testo);

	ptr1+=5;

	*ptr1 = 'A';

    printf("testo1: %s \n", testo1);

	getchar();


}

il risultato a schermo è il seguente :

testo: 1234A> "
testo1: 1234

Questo non mi garantisce che il compilatore riservi in coda a testo e testo1 un \0 , ma mi garantisce che printf e surrogati quando si chiede la rappresentazione stringa di un char[] la ritiene terminata con il \0
Nel primo esempio avendo fatto una manovra catso modificando a mano l'indirizzo del puntatore ho praticamente sovrascritto il teorico \0 facendo si che richiedendo poi la visualizzazione a schermo di quella variabile in formato stringa , essa non si sia limitata a 1234 come da dichiarazione, e nemmeno ad 1234A , ma bensi si sia spinta fino a trovare nuovamente un \0

:roll_eyes:
P.S. sto cominciando a nutrire dubbi sull'utilità di questi esperimenti :stuck_out_tongue_closed_eyes:

RI P.S. ora ho la certezza che dichiarando un char[] in quella maniera viene riservato il \0 in coda:

int main()
{
    char testo[] = "1234";

	printf("testo: %s \n", testo);
	printf("length: %u \n", sizeof(testo));

	getchar();


}

Per l'utilità dei test ho ancora dubbi ... :disappointed_relieved:

quando usi " " il compilatore aggiunge sempre /0 riservando il giusto spazio.

ciò non avviene con lo ' ', che però non salva una stringa ma un carattere solo (se ci metti più caratteri CREDO che li sommi)

quindi il test 1 potevi farlo anche:

char testo3[4];
char prova4 = 'p'; //se siamo fortunati prova4 si trova nella ram subito dopo test3, quindi possiamo verificare l'overflow!

println("%c\n", prova4 );

testo3[0] = '1';
testo3[1] = '2';
testo3[2] = '3';
testo3[3] = '4';
//andiamo un pò nel regno dell'overflow
testo3[4] = '0';

println("%c\n", prova4 ); //venghino siori e siore, prova4 modificata senza trucco e senza inganno!

testo3[10] = '\0';//assicuriamoci di non andare in overflow di ram va.. forziamo il tappo a 10 caratteri

println("%s", testo3); //quì stampa 1234 e del garbage! se la ram èp stata assegnata contigua, il primo carattere di garbage è prova4!

il secondo test invece non ha senso; sizeof(testo) ti ritorna il numero di byte usati dal PUNTATORE testo, non la dimensione della stringa / array; in c non esiste alcun metodo per conoscere la dimensione di un array, a meno che te stesso non ne tenga conto o con un contatore, o con un carattere di tappo (tipo \0)

Sono un pò perplesso dal discorso del sizeof, anche se ha estremamente senso quello che dici, che diamine di tipo di dato è per occupare 5byte??????
Non è che 1byte è il tipo e 4 byte l'indirizzo?

devo rimangiarmi ciò che ho detto su sizeof:

When sizeof is applied to the name of an array, the result is the size in bytes of the whole array. (This is one of the few exceptions to the rule that the name of an array is converted to a pointer to the first element of the array.) The following program uses sizeof to determine the size of a declared array, avoiding a buffer overflow when copying characters

se ripenso alle centinaia di righe di codice inutili... =(

é si, del resto bastava aggiungere elementi alla char[] per vedere che il valore aumentava !!!

	printf("testo: %s \n", testo);
	printf("length: %u \n", sizeof(testo));
	printf("length of ptr: %u \n", sizeof(&testo));

ritorna:

testo: 12345678
length: 9
length of ptr: 4

il puntatore è 4 byte , infatti ora mi torna!!!

SO TROPPO IL MIGLIORE!!! XD

1

Contraccambio (+1) per premiare lo spirito di sano confronto che si è instaurato!