Pages: [1] 2   Go Down
Author Topic: Task leOS, strano problema.  (Read 1374 times)
0 Members and 1 Guest are viewing this topic.
Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti, sto utilizzando la libreria leOS per eseguire questo semplice task ogni x secondi (ancora devo decidere).
La funzione è questa:

Code:
void printInfo()
{
for(int i=0; i<4; i++)
{
lcd.setCursor(0,0);
lcd.print(i);
Serial.println(i);
delay(1000);
}   
}

Il problema è che non segue il delay di 1 secondo, è normale che leOS non possa fare questo?

Infatti da seriale si vede velocemente che scorrono le cifre..

Consigli?

Grazie
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23142
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non può perché il delay è una funzione che ferma l'esecuzione del codice per il numero di ms specificato. Per funzionare usa leggere i millisecondi da millis, ma questa funzione è basata su un contatore che viene incrementato da un interrupt agganciato all'overflow del timer 0.
Il leOS usa uno schedulatore inserito in un altro timer e viene richiamato all'interno di un interrupt. All'interno di un interrupt, vengono bloccati tutti gli altri interrupt, per cui il delay non funzionerà e la tua funzione congelerà il microcontrollore.
E poi perché devi mettere un'attesa di 1 secondo all'interno di una funzione? Stai usando male il leOS. Spiega cose devi fare che troviamo la soluzione più adatta.
Logged


Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non può perché il delay è una funzione che ferma l'esecuzione del codice per il numero di ms specificato. Per funzionare usa leggere i millisecondi da millis, ma questa funzione è basata su un contatore che viene incrementato da un interrupt agganciato all'overflow del timer 0.
Il leOS usa uno schedulatore inserito in un altro timer e viene richiamato all'interno di un interrupt. All'interno di un interrupt, vengono bloccati tutti gli altri interrupt, per cui il delay non funzionerà e la tua funzione congelerà il microcontrollore.
E poi perché devi mettere un'attesa di 1 secondo all'interno di una funzione? Stai usando male il leOS. Spiega cose devi fare che troviamo la soluzione più adatta.

Ok, ora mi è chiaro perchè il delay non funziona.
Cerco di riassumere un po la situzione anche se non ho il codice sotto mano ora.

Nel loop ho due principali funzioni
Code:
leggiPulsanti();
navigaMenu();

leggiPulsanti mi restituisce un'intero.
navigaMenu è utilizzata dalla libreria menubeckend.

Navigo senza problemi nel menu, ho utilizzato 4 tasti totali (destra, sinistra, enter ed esc) e riesco tranquillamente ad accedere a menu e sottomenu e, nel caso utilizzare un menu(aumentare/diminuire setting ed altro)...
Il problema ora mi è sorto nel menu chiamato "info".

(Non ho detto che sto utilizzando un display 16x2 gestito tramite liquidcrystal.h)

In questo menu io vorrei che una volta avuto accesso, del testo scorresse, in modo verticale.

Ecco la fonte del problema, il testo che scorre in verticale, io ho pensato di risovlerlo così:

Code:
void stampaInfo()
{
char* testo[]={"riga1", "riga2", "riga3", "rirga4"}

for(int i=0; i<4; i++)
{
lcd.setCursor(0,0);
lcd.print(testo[i]);
lcd.setCursor(0,1);
lcd.print(testo[i+1]);

delay(1000); //questo è il delay che mi serve prima che il testo scorra verso sopra
lcd.clear()
}
}

Ora, questo è il codice che viene eseguito se io entro nel menu info, il problema sta proprio nel delay che ferma il codice e non mi permette di poter controllare la pressione eventuale del tasto ESC (che mi permetterebbe di uscire dal menu info e andare al menu principale).
(In realta premendo ripentutamente il tasto ESC alla fine ci riesco anche, ma è poco user friendly xD )

Ho pensato subito a leOS!:) E le soluzioni (da me pensate all'inzio) erano 2:

Implemento leOS ogni tot ms per leggere i tasti e tolgo quella funzione dal loop(): Sarebbe l'ideale ma siccome per ora la funzione che legge i tasti mi restiutisce un'intero non mi andava di modificarla.

Ho pensato allora di fare il contrario(il mio problema): Al setup inizializzo il tastk di leOS per la stampa del testo e lo metto in pausa(non lo avvio subito).
Quando premo enter per entrare nel menu info attivo il task..
A questo punto lui doveva farmi la funzione con il delay che genere il problema
(nel frattempo la lettura dei pulsanti è sempre attiva)..
..e quindi se premo ESC torno al menu principale e rimetto in pausa il tastk leOS visto che non mi serve..

Da qui il problema, leOS non può fare il delay..

Spero di aver spiegato + o - bene ma purtroppo senza codice davanti è difficile..:/

Grazie!
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23142
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

O sono io duro oppure il problema è troppo semplice.
Vediamo se ho capito: tu vuoi far eseguire al leOS un task con un intervallo di 1 secondo.
Soluzione: myOS.addTask(stampaInfo, 1000);
Devi semplicemente aggiungere il task con l'intervallo desiderato. Sarà poi lo scheduler a richiamarlo 1 volta al secondo, non serve mettere un delay di 1 secondo nel task.

Era questo?
Logged


Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mmm no, il delay che io metto serve per dare il tempo all'utente di leggere la scritta che scorre, visto che nel modo che l'ho strutturata dovrebbe funzionare così:

Code:
Le stringe che abbiamo: "Riga1" , "Riga2" , "Riga3" , "Riga 4"

quindi parte la funzione e scrive sul display 16x2:

Riga1
Riga2
delay(quello che provoca il danno xD )
Riga2
Riga3
delay(quello che provoca il danno xD )
Riga3
Riga4
Il delay quindi che sta nel ciclo for invece serve per dare quei (es: 600 ms) di tempo a chi legge le info prima che il testo scorra verso sopra.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23142
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora fai semplicemente un task differente. Invece del for, usa un incremento del contatore e ad ogni chiamata del task visualizzi una riga differente, ed hai risolto.
Logged


Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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;

Code:
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..
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23142
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sì, esatto (togliendo ovviamente quel delay).
Logged


Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Uh è vero! I copia-incolla sono e saranno una rovina..smiley
Logged

MC
Offline Offline
God Member
*****
Karma: 14
Posts: 917
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Code:
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!  smiley-mr-green
« Last Edit: October 25, 2012, 05:04:31 am by niki77 » Logged

Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:

#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:
Code:
if (contatore>NUM_RIGHE)
è passata a:
Code:
(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..smiley

Grazie
Logged

MC
Offline Offline
God Member
*****
Karma: 14
Posts: 917
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?  smiley-mr-green
Essendo un ciclo incrementale unitario non avrai mai la possibilità di andare oltre.
Logged

Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

Montalbano Jonico
Offline Offline
Sr. Member
****
Karma: 1
Posts: 287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-cool 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..
Logged

0
Online Online
Shannon Member
****
Karma: 136
Posts: 10525
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23142
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Tornando all'errore.
Quote
L'unico errore che ho potuto notare ora rispetto allo sketch di prima è appunto la condizione di controllo del contatore che da:
Code:
if (contatore>NUM_RIGHE)
è passata a:
Code:
(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.
Logged


Pages: [1] 2   Go Up
Jump to: