Go Down

Topic: millis() mi manda in crash. Va bene il leOS? (Read 2286 times) previous topic - next topic

BaBBuino

Feb 28, 2013, 01:33 am Last Edit: Feb 28, 2013, 01:36 am by BaBBuino Reason: 1
Spero che mi rispoda direttamente Leo.

Ho un 644 con display grafico KS0108 che funziona benissimo. Uso una funzione delay per aggiornare la lettura ogni 100 mSec, quindi sono 10 FPS al sec.

Volendo rendere un pò più elegante il programma ho usato il solito sistema con millis()

int time;       //variabile contatore

Setup()
time = milisec();   //collego la mia variabile al tempo che trascorre

Loop() {
if (time +100 < millis())        //parte se sono passati 100 msec
{
  Disegna;
  Tira;
  Allunga;
  Molla;
  quellochetipare;
  time=millisec();      ///Esco aggiornando il timer
  } // Fine Loop

Mbè... dopo un pò che il programma parte, si congela tutto, specie se interagisco con un ingresso esterno (ho collegato un encoder, e se spippolo si congela ancora prima).

Con il delay(), per quanto sia brutto da usare, l'aggeggio funziona.

Avevo letto distrattamente sul sito di Leo della sua libreria leOS... Sara mica la volta buona che mi industrio per usarla...?


leo72

Quello che hai messo non è codice valido per cui non so dirti quale può essere l'errore logico che ti blocca il programma.
Il leOS puoi usarlo, sempre che l'aggiornamento del display fatto da un task non occupi troppo tempo computazionale né utilizzi timer o interrupt.

BaBBuino

#2
Feb 28, 2013, 01:56 am Last Edit: Feb 28, 2013, 11:15 am by leo72 Reason: 1
Grazie leo! Ho letto come funziona e devo farti i complimenti; sembra quasi un sistema Multitasking come lo scheduler del vecchio Windows95.

Il tuo sistema è anni luce rispetto all'uso del millis e ne approfitterò per apprenderne l'uso.

Una domanda: Si possono nidificare le funzioni della libreria?

Es:

Code: [Select]
void setup() {
 myOS.begin();
 myOS.addTask(Ammazzati(), 100 );
}  // Fine setup


void Ammazzati()
{
 myOS.addTask(Resuscita(), 100);
....
}

void Resuscita()
{
  myOS.addTask(Sparati(), 1000);
...
{

BaBBuino

Dimenticavo: il mio aggeggio USA gli interrupt 0 e 1 ai quali sono collegati i pin dell'encoder.

E poi uso la Libreria GLCD (quella presente anche sul Playground) che non so se usi qualche timer...

astrobeed

Ti va in blocco perché usi un int per la variabile tempo.

Code: [Select]

int time;       //variabile contatore

Setup()
time = milisec();   //collego la mia variabile al tempo che trascorre


millis() ritorna un "long int" e la variabile tempo deve essere un "long int", se usi un int perdi i 16 bit superiori del valore e dopo 6.5 secondi non sei più in grado di memorizzare il corretto tempo trascorso.

leo72


Grazie leo! Ho letto come funziona e devo farti i complimenti; sembra quasi un sistema Multitasking come lo scheduler del vecchio Windows95.

Forse quello di Win3.1, in cui un task prendeva il controllo del sistema, e se non lo restituiva bloccava l'intero SO  :smiley-yell:

Quote

Il tuo sistema è anni luce rispetto all'uso del millis e ne approfitterò per apprenderne l'uso.

Non esagerare  :smiley-sweat: :smiley-sweat:
E' però comodo per fare piccole cosucce, quel tipo di cosucce che spesso rompono le scatole perché devi farle in punti in cui dovresti modificare blocchi di codice per farle.

Quote

Una domanda: Si possono nidificare le funzioni della libreria?

No.
Siccome è uno scheduler molto primitivo e siccome è stato scritto per non appesantire il sistema, non salva lo stato della CPU prima di richiamare un task e non lo ripristina dopo la fine della sua esecuzione. Se metti l'inserimento di un task all'interno di un altro task, dopo pochi cicli hai riempito lo scheduler di task creati.
Ciò che vuoi fare lo puoi fare usando la definizione del tipo di task, ad esempio puoi creare Ammazzati come task ONETIME, cioè che sia eseguito solo una volta.

leo72


Dimenticavo: il mio aggeggio USA gli interrupt 0 e 1 ai quali sono collegati i pin dell'encoder.

Gli interrupt vengono segnalati al micro, che ne esegue poi il codice relativo in ordine di importanza e non appena "può farlo".
Nel senso che se sta eseguendo un task del leOS, ed arriva un interrupt dall'encoder, viene registrato in un registro l'elevamento dell'interrupt. Appena il task termina, il micro esegue la ISR corrispondente all'interrupt arrivato. Mentre esegue questa ISR, non esegue nessun altro interrupt, neanche quelli generati dal leOS, perché gli interrupt sono atomici.

Questo comportamento non si applica del tutto al leOS2, che usa un modo differente per gestire i task, che vengono definiti di tipo non atomico, quindi interrompibili.

Quote

E poi uso la Libreria GLCD (quella presente anche sul Playground) che non so se usi qualche timer...

Link?

astrobeed


Siccome è uno scheduler molto primitivo e siccome è stato scritto per non appesantire il sistema,


A quando il LeOs 2.0 Plus ?  :smiley-mr-green:

leo72



Siccome è uno scheduler molto primitivo e siccome è stato scritto per non appesantire il sistema,


A quando il LeOs 2.0 Plus ?  :smiley-mr-green:


Ci ho pensato, e tanto.
Quello che mi ferma sono le seguenti 2 cose:
1) per fare uno scheduler di tipo preemptive (non mi piacciono quelli cooperativi) devo creare tutto un meccanismo di semafori e salvataggio dello stack per saltare da un task all'altro che vado a snaturare lo spirito con cui era nato il leOS: semplicità d'uso (ad oggi, lo includi come una lib e lo usi senza dover conoscere la programmazione ad oggetti tipica invece dei sistemi più complessi in circolazione) e leggerezza (l'ho usato su Tiny85 e 84 nonché su 168/328 ma anche su chip più capienti come il 644/1284).
2) ci sono un sacco di alternative in circolazione: avr-os, celina, Nil OS, ChibiOS/RT, FreeRTOS, SCoop, FemtoOS, per citare solo quelli opensource compatibili con l'Arduino che mi vengono in mente. A che pro farne un altro?

astrobeed


leo72



A che pro farne un altro?


Per la gloria ?


I love you  :*

psss... non dirlo a nessuno... ma avevo già iniziato a pensare a come fare da un paio di giorni...  ;)

BaBBuino


Ti va in blocco perché usi un int per la variabile tempo.

Code: [Select]

int time;       //variabile contatore

Setup()
time = milisec();   //collego la mia variabile al tempo che trascorre


millis() ritorna un "long int" e la variabile tempo deve essere un "long int", se usi un int perdi i 16 bit superiori del valore e dopo 6.5 secondi non sei più in grado di memorizzare il corretto tempo trascorso.



Grazie Astro, ho capito perfettamente il problema!

BaBBuino

Leo gli interrup non sono strettamente necessari per leggere l'encoder, li leverò.

La libreria GLCD è questa qua: http://playground.arduino.cc/Code/GLCDks0108

e anche qua tutto il Wiki: http://code.google.com/p/glcd-arduino/

Probabilmente, sicuramente avrò problemi nell'applicare la tua libreria. Sappi che ti potrò scocciare ancora per suggerimenti vari...

leo72

La lib l'ho guardata velocissimamente ma non mi pare, per quel poco che ho visto, che usi interrupt.
Non so se inserendo una chiamata ad essa dentro ad un task del leOS si rallenti molto il sistema, dovresti fare delle prove.

BaBBuino

Fantastico! Sono andato sul sito di Leo per rileggermi le evoluzioni di leOS, e pare sia stato Hackerato...

Mi rimanda a questo sito: http://www.mydisley.com/traf.php, poi mi chiede di accettare un plug-in ed infine mi sono preso il virus della Polizia! (vogliono che paghi 100e di multa per essere entrato in un sito proibito, se no il PC riimane bloccato...)

Grazie Leo! :D

Go Up