Pages: 1 ... 14 15 [16] 17 18 ... 31   Go Down
Author Topic: leOS - un semplice OS per schedulare piccoli task  (Read 30299 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21607
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Il weekday ?  smiley-yell
No!  smiley-twist

Quote
Bel lavoro  smiley

Grazie.  smiley-razz
Sono quel genere di cose che si fanno per passare il tempo....  smiley-sweat
Logged


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

Ho aggiornato il leOS alla versione 0.1.3.
Ho aggiunto un paio di sketch di esempio per mostrare le funzionalità di questo scheduler nonché ho aggiunto una nuova funzionalità: la possibilità di aggiungere un task in modalità "pausa", che non viene cioè eseguito immediatamente dopo l'aggiunta ma solo quando l'utente lo riattiva esplicitamente col metodo restartTask().
Questa funzionalità è a mio avviso molto utile per aggiungere ad esempio un task che possa manifestare immediatamente la sua attività, ad esempio pilotando un LED o un transistor. Ciò si può ottenere aggiungendo la parola chiave PAUSED ai parametri passati al metodo addTask. Esempio:
Code:
myOS.addTask(funzione, intervallo, PAUSED);
Per avviare il task basta dare:
Code:
myOS.restartTask(funzione);
quando lo si ritiene opportuno.

Ricordo che la sintassi di addTask è:
Code:
addTask(nomeFunzione, intervallo[, stato])
stato è opzionale e può assumere 3 valori predefiniti:
PAUSED: per aggiungere un task con esecuzione sospesa
SCHEDULED: opzione di default, aggiunge un task con esecuzione attiva
ONETIME: aggiunge un task attivo da eseguire solo 1 volta

Uno dei 2 nuovi sketch di esempio serve a mostrare la nuova funzionalità. L'altro mostra invece una cosa carina che può fare il leOS, ossia attivare/disattivare un task da un altro task.

N.B.:
Il leOS 0.1.3 è disponibile da adesso solo sul mio sito. Ho tolto il download dal 1° post del thread per avere un contatore globale dei download e perché spesso mi dimenticavo di aggiornare il pacchetto su uno dei 2 posti dov'era pubblicato (il forum o il mio sito).
Logged


Sicily
Offline Offline
Newbie
*
Karma: 0
Posts: 48
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Leo

complimenti per l'ottima libreria


leggendo un po tutto il thread e le info postate da te ho visto che usi il timer2 per far funzionare la tua libreria,

io ho fatto un test ho utilizzato l'esempio lesos2task con i tre led a questo ho aggiunto un task che dovrebbe colleagarsi ad un sensore colleato attraverso il protocollo i2c e inviare il risultato sulla serieale.

lo sketch si carica ma si blocca subito al primo ciclo

mi chieso se pure l'I2C si basa sul timer2
io possiedo un arduino mega e mi chiedevo se potevo far funzionare il leos con il timer4 e constatare il funzionamento

inoltre non sarebbe carico far scegliere all'utente quali timer far utilizzare?!

che dritta potresti darmi per risolvere il mio problema :-) :-P
di sicuro sbaglio qualcosa....

ti ringrazio in anticipo e complimenti per il lavoro ben fatto

saluti
Logged

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

Ciao Leo

complimenti per l'ottima libreria


leggendo un po tutto il thread e le info postate da te ho visto che usi il timer2 per far funzionare la tua libreria,
La libreria si basa su un timer del microcontrollore. Sull'Atmega328 uso il timer 2 perché è un timer ad 8 bit e mi risulta facile gestirlo dato che si manipola 1 registro contatore da 8 bit al posto di quelli a 16 bit del timer 1. Il timer 0, anch'esso ad 8 bit, è usato dall'Arduino per la funzione millis().
Su altri microcontrollori uso i timer che sono disponibili.

Quote
io ho fatto un test ho utilizzato l'esempio lesos2task con i tre led a questo ho aggiunto un task che dovrebbe colleagarsi ad un sensore colleato attraverso il protocollo i2c e inviare il risultato sulla serieale.

lo sketch si carica ma si blocca subito al primo ciclo

mi chieso se pure l'I2C si basa sul timer2
L'I2C sul 328 e sul Mega2560 è integrato nell'hardware ma è gestito da un'interfaccia software basata sugli interrupt. Se tenti di leggere o spedire dati via I2C da dentro ad un task, è normale che si blocchi tutto perché ogni task viene eseguito all'interno dell'ISR (Internet Service Routine) che viene attivata dall'overflow del contatore del timer ed ogni ISR è atomica, ossia non  può essere interrotta da un'altra ISR. Parlo però per ipotesi perché senza analizzare il codice non so esattamente cosa stai facendo.

Quote
io possiedo un arduino mega e mi chiedevo se potevo far funzionare il leos con il timer4 e constatare il funzionamento
Sul Mega2560 uso il timer 2. Hai qualche particolare necessità per dover usare il timer 4?

Quote
inoltre non sarebbe carico far scegliere all'utente quali timer far utilizzare?!
Carina come idea ma non so se hai dato un'occhiata al file leos.cpp, nella parte finale. La funzione setTimer() imposta i timer e, come vedi, non è proprio stato semplice trovare i valori giusti per impostare tutti i registri per impostare i timer  smiley-sweat
Spostare poi lo scheduler su un altro timer cambia poco, sempre un timer perdi.

Quote
che dritta potresti darmi per risolvere il mio problema :-) :-P
di sicuro sbaglio qualcosa....
Beh, intanto posta il codice per capire dove sta il problema  smiley-wink

Quote
ti ringrazio in anticipo e complimenti per il lavoro ben fatto

saluti

Grazie a te per l'interesse
Logged


Sicily
Offline Offline
Newbie
*
Karma: 0
Posts: 48
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao Leo


ecco il codice con cui stavo facendo i test

http://pastebin.com/7LX1dFDZ


thanks in anticipo
Logged

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

E' come pensavo. Hai messo l'uso dell'I2C all'interno di un task, è per questo che ti si blocca.
Anche la Serial non va bene gestirla in un task. In un task devono starci operazioni computazionalmente poco gravose o che utilizzino l'HW in maniera diretta.

Hai 2 strade:
1) rivedi il codice facendo in modo di lasciare al di fuori del 3° task tutto quello che utilizza interrupt, oppure
2) provi ad usare il looper: è uno schedulatore software. Puoi ovviamente intervallare l'esecuzione dei task anche se perdi in precisione assoluta nella loro esecuzione ma dentro ad un task puoi infilarci tutto quello che ti pare, dato che si tratta in pratica di una semplice funzione che richiama altre funzioni eseguita all'interno del loop principale.
Logged


Sicily
Offline Offline
Newbie
*
Karma: 0
Posts: 48
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

E' come pensavo. Hai messo l'uso dell'I2C all'interno di un task, è per questo che ti si blocca.
Anche la Serial non va bene gestirla in un task. In un task devono starci operazioni computazionalmente poco gravose o che utilizzino l'HW in maniera diretta.

non ci sarebbe un modo per gestire I2C(e la Serial) in maniera diretta?

Quote
Hai 2 strade:
1) rivedi il codice facendo in modo di lasciare al di fuori del 3° task tutto quello che utilizza interrupt, oppure
2) provi ad usare il looper: è uno schedulatore software. Puoi ovviamente intervallare l'esecuzione dei task anche se perdi in precisione assoluta nella loro esecuzione ma dentro ad un task puoi infilarci tutto quello che ti pare, dato che si tratta in pratica di una semplice funzione che richiama altre funzioni eseguita all'interno del loop principale.

le due soluzioni che giustamente hai sottolineato le ho provate entrambe ed ovviamente funzionano

se dovessi optare per il looper non ci sarebbe un modo anche utilizzando un RTc esterno per migliorare la precisione dell'esecuzione dei task?

scusami per tutte queste domande :-P

grazie per le delucidazioni
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10102
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

forse si può usare in maniera diretta, ma bisogna modificare pesantemente le librerie per renderle non bloccanti. E' un lavoro con cui mi sono cimentato, funziona ma sarebbe da riscrivere per essere fatto apposta e non un brutale hack, devi sostituire la libreria originale Wire e sottocartella utils con questo codice https://github.com/lestofante/arduinoSketch/tree/master/asincI2Ctest2_asinc, trovi anche un esempio di utilizzo.
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

non ci sarebbe un modo per gestire I2C(e la Serial) in maniera diretta?
Ti ha risposto lesto. Effettivamente ha modificato tempo fa la Wire per renderla non bloccante. Ma qui lascio a lui la parola perché non ho seguito il progetto.

Quote
se dovessi optare per il looper non ci sarebbe un modo anche utilizzando un RTc esterno per migliorare la precisione dell'esecuzione dei task?
Tutto dipende da cosa fa il tuo loop. Mi spiego: se programmi un intervallo di 500 ms tra un'esecuzione e l'altra, il task prende 50 ms ed il loop 100 ms, hai un tempo di esecuzione di 150 ms su un intervallo di 500 ms. Quindi sei a posto: il tuo task sarà sempre eseguito secondo quanto stabilito. Ma se mettiamo che tu abbia programmato un intervallo di 100 ms, allora il tuo task sarebbe eseguito sempre con 50 ms di ritardo. E' in questo che difetta il looper dal leOS.

Quote
scusami per tutte queste domande :-P

grazie per le delucidazioni
Figurati.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non per sminuire il lavoro di leo(nell'80% dei casi va più che bene smiley-grin ),ma se hai esigenze particolari ti direi di cercare "freertos arduino"..è un SO minimale realtime per arduino..e direi che puoi farci cose avanzate..
Logged

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

E' vero, ci sono tanti RTOS in circolazione che funzionano molto meglio del leOS... ma a che prezzo? Avete dato un'occhiata alla complessità del codice necessario per fare un semplice blink, ad esempio con freeRTOS?

Posto il codice di UNOBlink:
Code:
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
////    main.c
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#include <avr/io.h>

/* Scheduler include files. */
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <semphr.h>

/* serial interface include file. */
#include <lib_serial.h>

/* LCD (Freetronics 16x2) interface include file. */
#include <hd44780.h>


/*-----------------------------------------------------------*/
/* Create a handle for the serial port. */
xComPortHandle xSerialPort;

static void TaskBlinkRedLED(void *pvParameters); // Main Arduino Mega 2560, Freetronics EtherMega (Red) LED Blink

static void TaskBlinkGreenLED(void *pvParameters); // Main Arduino Uno 328p (Green) LED Blink
/*-----------------------------------------------------------*/

/* Main program loop */
int16_t main(void) __attribute__((OS_main));

int16_t main(void)
{

    // turn on the serial port for debugging or for other USART reasons.
xSerialPort = xSerialPortInitMinimal( 115200, portSERIAL_BUFFER, portSERIAL_BUFFER); //  serial port: WantedBaud, TxQueueLength, RxQueueLength (8n1)

avrSerialPrint_P(PSTR("\r\n\n\nHello World!\r\n")); // Ok, so we're alive...

    xTaskCreate(
TaskBlinkRedLED
,  (const signed portCHAR *)"RedLED" // Main Arduino Mega 2560, Freetronics EtherMega (Red) LED Blink
,  256 // Tested 9 free @ 208
,  NULL
,  3
,  NULL ); // */

    xTaskCreate(
TaskBlinkGreenLED
,  (const signed portCHAR *)"GreenLED" // Main Arduino Uno 328p (Green) LED Blink
,  256 // Tested 9 free @ 208
,  NULL
,  3
,  NULL ); // */


avrSerialPrintf_P(PSTR("\r\n\nFree Heap Size: %u\r\n"),xPortGetFreeHeapSize() ); // needs heap_1 or heap_2 for this function to succeed.

vTaskStartScheduler();

avrSerialPrint_P(PSTR("\r\n\n\nGoodbye... no space for idle task!\r\n")); // Doh, so we're dead...

}

/*-----------------------------------------------------------*/


static void TaskBlinkRedLED(void *pvParameters) // Main Red LED Flash
{
    (void) pvParameters;;
    portTickType xLastWakeTime;
/* The xLastWakeTime variable needs to be initialised with the current tick
count.  Note that this is the only time we access this variable.  From this
point on xLastWakeTime is managed automatically by the vTaskDelayUntil()
API function. */
xLastWakeTime = xTaskGetTickCount();

int8_t i;
uint8_t j;

lcd_Init();

DDRB |= _BV(DDB7);

    while(1)
    {

    PORTB |=  _BV(PORTB7);       // main (red IO_B7) LED on. EtherMega LED on
vTaskDelayUntil( &xLastWakeTime, ( 10 / portTICK_RATE_MS ) );

lcd_Locate (0, 0);
lcd_Printf_P(PSTR("HighWater @ %u"), uxTaskGetStackHighWaterMark(NULL));
lcd_Cursor (1);

#if _USE_FUEL
lcd_Locate (1, 0);
lcd_PutFuel (--i, 0);
if (i < 0) i = 6;
#endif

#if _USE_BAR
lcd_Locate (1, 2);
lcd_PutBar (j++, 14, 2);
#endif

PORTB &= ~_BV(PORTB7);       // main (red IO_B7) LED off. EtherMega LED off
vTaskDelayUntil( &xLastWakeTime, ( 40 / portTICK_RATE_MS ) );

// xSerialPrintf_P(PSTR("RedLED HighWater @ %u\r\n"), uxTaskGetStackHighWaterMark(NULL));
    }

}

/*-----------------------------------------------------------*/
static void TaskBlinkGreenLED(void *pvParameters) // Main Green LED Flash
{
    (void) pvParameters;;
    portTickType xLastWakeTime;
/* The xLastWakeTime variable needs to be initialised with the current tick
count.  Note that this is the only time we access this variable.  From this
point on xLastWakeTime is managed automatically by the vTaskDelayUntil()
API function. */
xLastWakeTime = xTaskGetTickCount();

DDRB |= _BV(DDB5);

    while(1)
    {
    PORTB |=  _BV(PORTB5);       // main (red PB5) LED on. Arduino LED on
vTaskDelayUntil( &xLastWakeTime, ( 100 / portTICK_RATE_MS ) );

PORTB &= ~_BV(PORTB5);       // main (red PB5) LED off. Arduino LED off
vTaskDelayUntil( &xLastWakeTime, ( 400 / portTICK_RATE_MS ) );

xSerialPrintf_P(PSTR("GreenLED HighWater @ %u\r\n"), uxTaskGetStackHighWaterMark(NULL));
    }
}
/*-----------------------------------------------------------*/


Questo è il codice di leOS_BlinkWithoutMillis:
Code:
//include the OS
#include "leOS.h"

leOS myOS; //create a new istance of the class leOS

//variables to control the LEDs
byte led1Status = 0;
const byte LED1 = 13;

//program setup
void setup() {
    myOS.begin(); //initialize the scheduler
    pinMode(LED1, OUTPUT);
   
    //add the tasks at the scheduler
    myOS.addTask(flashLed1, 1000);
}


//main loop
void loop() {
    //empty
}


//flashing task
void flashLed1() {
    led1Status^=1;
    digitalWrite(LED1, led1Status);
}

leOS è limitato ma è semplicissimo da usare.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

son d'accordo che non è facilissimo da implementare..anche se per la maggior parte dei casi basta un po' di copia e incolla..

dipende dalle tue necessità: se hai bisogno di avere tempi precisi con funzioni che usano interrupt,puoi o usare leOS + wire non bloccante(xò se tu volessi anche usare la seriale?),o RTOS..
altrimenti usi il looper,è semplice da usare,non ha problemi con interrupt,ma non garantisce tempi brevi..
« Last Edit: September 18, 2012, 12:43:22 pm by m_ri » Logged

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

In tanti anni che programmo ho imparato una cosa, che cioè il risultato ottimale è quello che ha il miglior rapporto prezzo/prestazioni.
Fare un codice semplicistico comporta un costo in termini di impegno di progettazione veramente minimo ma, per contro, hai prestazioni anch'esse minime. L'altra faccia della medaglia è un codice esageratamente ricercato, con un costo di progettazione molto elevato e prestazioni anch'esse al top. Alla fine, il risultato finale è identico: ognuno dei due programmi eseguirà il compito assegnato.

Vale la pena usare freeRTOS o FemtoOS per modificare un paio di porte in background? Non credo proprio. Vale la pena usare il leOS per gestire un multitasking preemptivo? Non credo proprio. Come dici giustamente tu, ognuno deve scegliere gli strumenti pensando al miglior rapporto per il proprio progetto.
Logged


Sicily
Offline Offline
Newbie
*
Karma: 0
Posts: 48
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ragazzi scusate la mia assenza, dopo diversi test ecco i primi risultati:

ho utilizzato le librerie:
1. leos
2. asincI2Ctest2_asinc (non bloccante)

devo dire che questa accoppiata funziona egregiamente.

La semplicità della realizzazzione dei task di leo, e l'utilizzo asincrono della wire di lesto
possono dare nuovi spunti a chi vuole realizzare sitemi anche complessi.

In questi giorni ho avuto modo di studiare e testare anche i sistemi RTOS (chibios e freertos), questi ultimi nonostante le loro caratteristiche importanti che si basano sui sistemi operativi real time, non risultano essere semplici nell'utilizzo, inoltre come accennato anche da leo ad esempio per scrivere un banale blick_led bisogna scrivere ben 4 volte il numero di righi di codice rispetto all'esempio di leos.

Certo ancora manca da implementare semafori, code ed altre logiche... ecc ecc
A mio avviso già questo è un passo avanti
ed il lavoro di leos non ha nulla da invidiare ai sistemi RTOS

questo è il mio umile giudizio
Logged

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

Certo ancora manca da implementare semafori, code ed altre logiche... ecc ecc
A mio avviso già questo è un passo avanti
ed il lavoro di leos non ha nulla da invidiare ai sistemi RTOS

questo è il mio umile giudizio
smiley-kiss Grasssie

PS:
sto usando il leOS su un Attiny85, è un progettino a cui sto lavorando da 2 giorni a questa parte (ecco perché sono un po' latitante, oltre agli impegni di lavoro): 3 task che fermo e riavvio, con intervalli differenti, abbinati alla gestione di un segnale PWM, a 2 letture analogiche e sleep/risveglio. E funziona tutto perfettamente. Siccome i 3 task dovevano girare "intrecciati" tra di loro e con il resto del codice, l'uso del leOS mi ha semplificato non poco la stesura del codice.
Logged


Pages: 1 ... 14 15 [16] 17 18 ... 31   Go Up
Jump to: