Pages: 1 ... 17 18 [19] 20 21 ... 31   Go Down
Author Topic: leOS - un semplice OS per schedulare piccoli task  (Read 40596 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

È una buona idea far fare tutto il lavoro a delle funzioni richiamate con leOS e lasciare il loop() vuoto se non serve eseguire in continuazione il codice o è meglio lasciare la parte principale in loop() e mettere un delay alla fine?
I task dovrebbero essere compiti semplici, che occupano poco tempo CPU, in modo da non rallentare l'esecuzione delle altre funzioni basate su interrupt. Se il tuo caso ricade in questo esempio, puoi anche inserire tutto in task e lasciare il loop vuoto. Se hai un compito che invece è molto gravoso, conviene inserirlo nel loop (e qui puoi rallentarne l'esecuzione con un delay).

Usare un analogRead() e poi stampare un valore su un display con LiquidCrystal non dovrebbe essere troppo gravoso?
Logged

0
Online Online
Faraday Member
**
Karma: 49
Posts: 6017
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

e' gravoso  smiley
Logged

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

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

l'analog read è gravosa (0.2millisecondi circa), stampare su LCD ancora di più.

0.2millisecondi vuol dire che dopo 5000 letture il tuo timer della millis() sballa di 1 secondo

Non tanto il fatto di stamparci sopra, se comunica in i2c sono 100Kbit/s, o 400Kbit/s se modifichi le libreria e il modulo supporta la fastI2c, però il vero problema è che l'esse umano non vede più velociemente di circa 20/50millisecondi, se poi parliamo di leggere arriviamo al secondo e rotto smiley

nel tuo caso sarebbe da attivare a livello di registri l'interrupt per il completamento della lettura analogica. All'interrupt del leos fai partire la lettura analogica (che lavora in parallelo, quindi non "spreca" cpu), al completamento viene lanciato un interrupt che mette il valore letto in una variaile volatile.

poi un altro task nel leos ogni secondo prende la variabile volatile e la stampa sull'LCD.

Il tempo impiegato dell'I2C, ma ancor meglio dalla SPI (fino a 5Mbit/s se ricordo bene, ma dipende dal modulo), è inifluente. Quello della seriale invece influisce, ma la Serial lavora per interrupt quindi in pratica lo sbattimento di cui sopra è già fatto, devi solo fare attenzione a non riempire il buffer seriale più in fretta di quanto esso non riesca a svuotasi
Logged

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

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

Potrebbe usare il looper, schedula i compiti ma non ha un sistema bloccante degli interrupt come il leOS.
Logged


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

Grosse novità in arrivo....  smiley-wink
Logged


0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

l'analog read è gravosa (0.2millisecondi circa), stampare su LCD ancora di più.

0.2millisecondi vuol dire che dopo 5000 letture il tuo timer della millis() sballa di 1 secondo

Non tanto il fatto di stamparci sopra, se comunica in i2c sono 100Kbit/s, o 400Kbit/s se modifichi le libreria e il modulo supporta la fastI2c, però il vero problema è che l'esse umano non vede più velociemente di circa 20/50millisecondi, se poi parliamo di leggere arriviamo al secondo e rotto smiley

nel tuo caso sarebbe da attivare a livello di registri l'interrupt per il completamento della lettura analogica. All'interrupt del leos fai partire la lettura analogica (che lavora in parallelo, quindi non "spreca" cpu), al completamento viene lanciato un interrupt che mette il valore letto in una variaile volatile.

poi un altro task nel leos ogni secondo prende la variabile volatile e la stampa sull'LCD.

Il tempo impiegato dell'I2C, ma ancor meglio dalla SPI (fino a 5Mbit/s se ricordo bene, ma dipende dal modulo), è inifluente. Quello della seriale invece influisce, ma la Serial lavora per interrupt quindi in pratica lo sbattimento di cui sopra è già fatto, devi solo fare attenzione a non riempire il buffer seriale più in fretta di quanto esso non riesca a svuotasi

grazie lesto, ma se io metto il task con un intervallo di 1 secondo il display verrà aggiornato ogni secondo (e il valore da scrivere potrebbe rimanere uguale), quindi non penso ci siano problemi di aggiornamento troppo rapido da non riuscire a leggere.
il problema che tu dici è che se per scrivere sul display serve un certo tempo, la successiva ripetizione del task non verrà eseguita esattamente dopo l'intervallo dichiarato?

non ho usato looper perchè mi serve che il task venga eseguito ogni secondo, altrimenti dovrei fare un calcolo diverso tenendo conto del tempo passato dall'inizio del task al successivo inizio con millis(), ma con leos è meno complicato.
a proposito, se metto un intervallo di 1 secondo il task successivo inizierà 1 secondo dopo l'inizio del precedente o dopo un secondo dalla fine del precedente?

potrei fare calcolare il valore al task senza stamparlo sul display ma solo salvandolo in una variabile come ha detto lesto, ma poi anziche fare un altro task per scrivere sul display, mettere in loop() la scrittura sul display leggendo la variabile e alla fine di loop() mettere un delay?
Logged

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

Dopo aver letto ieri di come funziona lo scheduler sull'Arduino DUE, che è basato su uno specifico timer interno al micro (sysTick), stavo pensando se c'era modo di poter replicare la cosa in qualche modo anche sull'Arduino UNO/Leonardo e sugli altri microcontrollori che normalmente uso.

Alla fine è nato leOS2!
Che cos'ha di differente il leOS2 rispetto al leOS? Una cosa tanto semplice quanto "ganza". Esso usa il WatchDog Timer (WDT) al posto di un timer del microcontrollore!

Che cos'è il WDT? E' un timer utilizzato come contatore dal WatchDog, il circuito che normalmente viene utilizzato per resettare il microcontrollore nel caso il codice si blocchi durante l'esecuzione in loop infiniti oppure in eterna attesa di dati che non arrivano mai. Se il tempo prefissato come "campanello d'allarme" termina prima che il contatore sia stato resettato, il WatchDog viene attivato ed esso resetta il micro. Per far ciò il contatore viene incrementato da un oscillatore  interno separato a 128 kHz tramite un prescaler che divide la frequenza in modo da avere diversi tempi di reset, da 16 ms in su.

Il WDT può essere utilizzato sia per resettare il microcontrollore sia per generare un semplice resetinterrupt. Quest'ultimo caso è quello che ci interessa: creando una ISR (Interrupt Service Routine) che intercetta il reset, possiamo gestire lo scheduler dei processi da eseguire in automatico senza utilizzare timer del microcontrollore, evitando quindi che il nostro sketch vada in conflitto con altre librerie che anch'esse usano lo stesso timer.

Il prezzo da pagare è la risoluzione degli intervalli: essi devono essere di 16 ms o multipli di esso per via del fatto che un "tick" non può essere più corto di 16 ms:
Fosc/Prescalermax -> 128.000 Hz / 2.048 = 62,5 Hz
1/62,5 = 0,016 s -> 16 ms
I metodi addTask() e modifyTask del leOS sono stati rivisti in modo che essi accettino il nuovo parametro in input. Se non si vuole fare a mano la conversione fra ms e tick (basta una semplice divisione per 16, comunque), si può usare il nuovo metodo convertMs(), che trasforma appunto i ms in tick. Ecco un esempio:
Code:
myOS.addTask(funzione, myOS.convertMs(1000));
Questa riga aggiunge la funzione "funzione" allo scheduler impostando un intervallo di 62 tick (1000/16=62,5->62).

In aggiunta a tutti i metodi del leOS, ho introdotto anche il metodo reset(). Siccome il WatchDog è spesso utilizzato per resettare un microcontrollore, se si vanno ad usare i metodi standard della libreria WDT.h per gestire il WatchDog si altera il funzionamento del leOS2 sia prima che dopo il reset. Per questo motivo, basta richiamare:
Code:
myOS.reset();
in qualunque punto del codice per resettare il microcontrollore senza

Atmel ha strutturato i suoi micro in modo che il circuito del WatchDog ed i registri che lo gestiscono siano uguali per quasi tutti i microcontrollori Atmega ed Attiny per cui la libreria può, in teoria, funzionare sulla maggior parte dei chip supportati dall'IDE e dai core disponibili senza uso di #define varie (esempio: Atmega88/168/328, Atmega644/1284, Atmega2560, Attiny84, Attiny85 ecc...). L'unico chip supportato dall'IDE che non è supportato dalla libreria è l'Atmega8 perché questo microcontrollore non ha la possibilità di sollevare un interrupt all'overflow del contatore del WatchDog ma solo un segnale di reset.

Ribadisco un concetto, chiarendolo meglio.
Il leOS2 non è preciso come il leOS né può gestire intervalli al millisecondo. La risoluzione è 16 ms, quindi 16 ms, 32 ms, 128 ms, 256 ms, 1024 ms sono valori precisi. 500 ms sono arrotondati a 496 (500/16=31,25->31 e 31*16=496).
Però il vantaggio è quello di poter ora utilizzare tutte le librerie che usano lo stesso timer impegnato dal precedente leOS.

Attendo repliche, consigli, segnalazioni di bug, suggerimenti e critiche  smiley-wink


* watchdog_timer_block.png (30.19 KB, 461x307 - viewed 24 times.)
* leOS2-2.0.2.zip (22.8 KB - downloaded 10 times.)
« Last Edit: November 12, 2012, 06:41:27 am by leo72 » Logged


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

a proposito, se metto un intervallo di 1 secondo il task successivo inizierà 1 secondo dopo l'inizio del precedente o dopo un secondo dalla fine del precedente?
1 secondo dopo la fine del precedente.
Sia il contatore su cui è basato lo scheduler che lo scheduler stesso sono contenuti nella ISR di gestione dell'interrupt sull'overflow del timer per cui quando viene eseguito un task il contatore non viene incrementato.
Logged


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

bellissima l'idea del watchdog, ma così non si resetta anche il codice del loop? oppure intercettando la ISR fai in modo che non si resetta?
Logged

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

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bellissima l'idea del watchdog, ma così non si resetta anche il codice del loop? oppure intercettando la ISR fai in modo che non si resetta?

Leggi qui:

http://www.embedds.com/using-watchdog-timer-in-your-projects/

Comunque se non resetti il wdt non viene resettato "il codice del loop", ma l'intero micro. E' come il pulsante di reset quando winsozz si pianta... ;-)
Logged

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

bellissima l'idea del watchdog, ma così non si resetta anche il codice del loop? oppure intercettando la ISR fai in modo che non si resetta?
Colpa di un mio refuso  smiley-wink
Quote
Il WDT può essere utilizzato sia per resettare il microcontrollore sia per generare un semplice reset interrupt. Quest'ultimo caso è quello che ci interessa: creando una ISR (Internet Service Routine) che intercetta il reset, possiamo gestire lo scheduler dei processi da eseguire in automatico senza utilizzare timer del microcontrollore, evitando quindi che il nostro sketch vada in conflitto con altre librerie che anch'esse usano lo stesso timer.
Si può attivare un reset, un interrupt od entrambi. Se attivo solo un interrupt, intercettando la ISR posso svolgere i miei compiti. Nella ISR ho messo proprio il contatore dei tick e lo schedulatore che gestisce i task. Purtroppo si ha una risoluzione di soli 16 ms ma, come vantaggio, non si impegnano timer aggiuntivi.
Inoltre il codice (se non si usa la funzione convertMs) risulta anche più snello di quello generato usando il leOS versione 1. Il che è un altro vantaggio.

A titolo informativo, ho parzialmente utilizzato la libreria Avr WDT.h: parzialmente perché essa parte dal presupposto di impostare il WDT per generare sempre e solo un reset, quindi per ora il suo utilizzo si limita allo sfruttamento di alcune macro per la gestione dei bit del registro di configurazione del WDT, mentre il setup del WDT lo faccio a mano. Prevedo col tempo di eliminarla completamente: l'ho usata per ora perché il leOS2 l'ho terminato praticamente stanotte e gli ultimi test li ho condotti stamani, prima di pubblicarla.
Logged


0
Online Online
Faraday Member
**
Karma: 49
Posts: 6017
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ti daranno il nobel per la gestione dei timer ?
Complimenti come al solito.
Sui miei amati 8A ci sono errori di compilazione oppure non si accorge del problema ma poi non funge ?
Logged

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo ha scritto:

 L'unico chip supportato dall'IDE che non è supportato dalla libreria è l'Atmega8 perché questo microcontrollore non ha la possibilità di sollevare un interrupt all'overflow del contatore del WatchDog ma solo un segnale di reset.
Logged

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

@Testato:
grazie dei complimenti  smiley-wink
Alla tua domanda ha risposto tuxduino. Purtroppo l'Atmega8 è l'unico chip che ha soltanto un circuito di reset collegato al WDT per cui l'errore è voluto, per bloccare la compilazione.
Logged


Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 115
Posts: 7258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quest'ultimo caso è quello che ci interessa: creando una ISR (Internet Service Routine) che intercetta il reset, possiamo gestire lo scheduler dei processi da eseguire in automatico senza utilizzare timer del microcontrollore, evitando quindi che il nostro sketch vada in conflitto con altre librerie che anch'esse usano lo stesso timer.

Interrupt Service Routine, non Internet.  smiley-mr-green
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Pages: 1 ... 17 18 [19] 20 21 ... 31   Go Up
Jump to: