Pages: 1 ... 22 23 [24] 25 26 ... 31   Go Down
Author Topic: leOS - un semplice OS per schedulare piccoli task  (Read 34552 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Faraday Member
**
Karma: 45
Posts: 5784
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

grazie dei consigli, però sia che aggiorni prima un buffer o che aggiorni direttamente il display leggendo i dati al momento, devo temporizzare comunque la print() sul display, quindi in pratica per la funzione per scrivere sul display devo per forza fare un controllo tipo il blinkwithoutdelay, o ho capito male?
Non confondiamogli le idee (si stanno mettendo in campo tante variabili, fino ad addirittura la gestione di un monitor pc)
Io ti do' la mia risposta secca, per il tuo lavoro va bene Looper
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

Quote
Come fa a te a funzionare?

E' quello che vorrei sapere anch'io  smiley-sweat

Può essere che c'entrino le chiamate all'lcd ? Non mi sembra un motivo plausibile a dire il vero, cmq stasera per scrupolo provo la tua versione con i led.
Se parliamo della LiquidCrystal allegata all'IDE 1.0.2, gli ho dato un'occhiata ma non ho trovato cose eclatanti tipo manipolazioni dei timer od uso degli interrupt.

Sì, sto usando la 1.0.2.

Comunque non vedi lampeggiare i led perché
Code:
' ' != 0

smiley-razz

Prova con questo:
Code:
#include <leOS.h>

leOS myOS;


//variables to control the LEDs
byte led1Status = 0;
byte led2Status = 0;
byte led3Status = 0;
const byte LED1 = 7;
const byte LED2 = 8;
const byte LED3 = 9;

void setup() {
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT);
   
    myOS.begin();
    myOS.addTask(flashLed1, 500);
    myOS.addTask(flashLed2, 500);
}


//main loop
void loop() {
    digitalWrite(LED3, led3Status ? HIGH : LOW);
    led3Status ^= 1;   
    delay(1000);
}


//first task
void flashLed1() {
    digitalWrite(LED1, led1Status ? HIGH : LOW);
    led1Status^=1;
    delay(800);                // <<<<<<<<<<<<<<<< (*)
    digitalWrite(LED2, led1Status ? HIGH : LOW);
}


//second task
void flashLed2() {
    digitalWrite(LED2, led2Status ? HIGH : LOW);
    led2Status^=1;
}
Logged

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

Comunque non vedi lampeggiare i led perché
Code:
' ' != 0
Ho convertito al volo, non ho controllato più di tanto.  smiley-sweat
Quote
Prova con questo:
Oggi lo farò.... ma tu: hai provato questo codice? smiley-razz
Logged


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

Usando come pin per i led 11, 12, 13 a rotazione il led sul 13 lampeggia sempre. Oggi sperabilmente dovrei riuscire a provare collegando contemporaneamente tre led  smiley-sweat
Logged

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

@tuxduino
Allora.... ho fatto un po' di test.
Intanto le certezze: una ISR di default non è interrotta da un'altra ISR.
Ho provato il tuo sketch e vedevo anch'io lampeggiare i 3 led. Una cosa che ho notato, però, è stata che i led 7 e 8 lampeggiavano entrambi con una frequenza che era la metà di quella del led 9, quindi non solo il led 8 ma anche il led sul pin 7, quello pilotato da un task in cui c'era un delay(800). Un delay che avrebbe dovuto inserire una certa differenza e quindi togliere la sincronizzazione dei flash.

Ho perciò preso un semplice sketch:
Code:
#include <leOS.h>

leOS myOS;


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

void setup() {
    pinMode(LED1, OUTPUT);
    Serial.begin(19200);    
    myOS.begin();
    myOS.addTask(flashLed1, 500);
}


//main loop
void loop() {
    digitalWrite(LED1, led1Status ? HIGH : LOW);
    led1Status ^= 1;    
}


//first task
void flashLed1() {
    delay(10000);
}

Se il delay avesse funzionato nei task come tu affermavi accadeva, il led avrebbe lampeggiato regolarmente ogni secondo. Invece vedevo un velocissimo lampeggio.

Ho preso un altro sketch:
Code:
#include <leOS.h>

leOS myOS;


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

void setup() {
    pinMode(LED1, OUTPUT);
    Serial.begin(19200);    
    myOS.begin();
    myOS.addTask(flashLed1, 500);
}


//main loop
void loop() {
    digitalWrite(LED1, led1Status ? HIGH : LOW);
    led1Status ^= 1;    
}


//first task
void flashLed1() {
    Serial.println(micros(), DEC);
    delay(10000);
    Serial.println(micros(), DEC);
}

Sul monitor seriale ho ottenuto:
Code:
1000372
1000632
1500140
1500344
1999844
2000056
2499560
2499768
2999264
2999480
3498984
3499192
3998700
3998904
4498420
4498620
4998132
4998332
5497828
5498040
In teoria la cosa dovrebbe essere impossibile perché delay è una funzione che attende del tempo sfruttando un contatore interno:
Code:
void delay(unsigned long ms)
{
uint16_t start = (uint16_t)micros();

while (ms > 0) {
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
Come vedi, ogni 1000 microsecondi, viene sottratto 1 ms al valore passato.
E micros() legge direttamente dal contatore agganciato al timer 0 (ed il timer continua a funzionare, solo che non viene più chiamato il relativo interrupt). Quindi non passa dalla ISR che aggiorna invece il valore di millis(). Però ovviamente, essendo gli interrupt fermi, il valore di timer0_overflow_count non viene incrementato per cui il ritardo non è esattamente calcolato.
Che tu metta un delay(1000) o un delay(10000) il risultato è di pochissimo differente.
Usando millis, invece, il tutto "muore". Ecco uno sketch di esempio:

Code:
#include <leOS.h>

leOS myOS;


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

void setup() {
    pinMode(LED1, OUTPUT);
    Serial.begin(19200);    
    myOS.begin();
    myOS.addTask(flashLed1, 500);
}


//main loop
void loop() {
    digitalWrite(LED1, led1Status ? HIGH : LOW);
    led1Status ^= 1;
}


//first task
void flashLed1() {
    unsigned long tempMillis = millis() + 10000;
    while (tempMillis > millis()); //morte cerebrale....
}
« Last Edit: November 27, 2012, 10:53:08 am by leo72 » Logged


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

attenzione, non è che muore ma che millis() non cambia mai (loop infinito)
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

@leo, per la cronaca io affermavo proprio che la delay() sembrava non funzionare. Il tuo esempmio in cui l'unica funzione del task è chiamare una delay(1000) conferma quanto avevo osservato anch'io in precedenza.

Direi che hai spiegato perfettamente perché la delay() è "istantanea" (perdona la semplificazione... smiley ) quando il task è chiamato dalla timer2 isr.

Grazie.

Per ora mi sembra di aver capito. Casomai rileggo la tua risposta un paio di volte... smiley
Logged

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

attenzione, non è che muore ma che millis() non cambia mai (loop infinito)
Per "muore" intendo che si freeza lì perché appunto la millis, non vedendo più il valore che restituisce cambiato, genera un loop infinito.

@leo, per la cronaca io affermavo proprio che la delay() sembrava non funzionare.  Il tuo esempmio in cui l'unica funzione del task è chiamare una delay(1000) conferma quanto avevo osservato anch'io in precedenza.
Ah, ok. Non ricordavo più l'oggetto della discussione  smiley-sweat

Quote
Direi che hai spiegato perfettamente perché la delay() è "istantanea" (perdona la semplificazione... smiley ) quando il task è chiamato dalla timer2 isr.

Grazie.

Per ora mi sembra di aver capito. Casomai rileggo la tua risposta un paio di volte... smiley
A tua disposizione  smiley-wink
Logged


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

sucsate un'ultima domanda sul display lcd e poi finisco l'off topic: quando ho il buffer pronto ed è il momento di inviarlo all'lcd, è meglio tenermi anche una copia del buffer precedente, confrontarlo con l'attuale e inviare al display solo le differenze, o va bene fare un clear() dell'lcd e inviare il buffer intero?
in pratica non dovrebbe cambiare niente, ma la soluzione migliore qual'è?
se facessi clear() prima sarebbe più semplice...

tornando a leOS
a me serve che un task venga eseguito ogni 1000 millisecondi esatti, quindi uso leOS e non leOS2 perchè 1000 non è multiplo di 16.
se però volessi eseguire il task ogni 2000 millisecondi (multiplo di 16), il task verrebbe eseguito ogni 2 secondi esatti o ogni 2 secondi ± 16ms ?
Logged

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

meglio le differenze. Eviti sfarfallamenti
Logged

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

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

sucsate un'ultima domanda sul display lcd e poi finisco l'off topic: quando ho il buffer pronto ed è il momento di inviarlo all'lcd, è meglio tenermi anche una copia del buffer precedente, confrontarlo con l'attuale e inviare al display solo le differenze, o va bene fare un clear() dell'lcd e inviare il buffer intero?
in pratica non dovrebbe cambiare niente, ma la soluzione migliore qual'è?
se facessi clear() prima sarebbe più semplice...
Non voglio andare contro lesto ma, secondo la mia modesta opinione, tenere 2 buffer in memoria, fare un confronto fra i 2 e spedire solo le differenze è un'inutile spreco di memoria (2 matrici) e di tempo (devi comunque confrontare tutte le celle dei 2 buffer per trovare i cambiamenti).
Tieni 1 solo buffer per volta e riscrivilo ogni xxx ms senza fare un clear() primo, in modo da: occupare meno memoria possibile; impiegare il minor tempo possibile per gestirlo; evitare sfarfallii dell'immagine (sovrascrivere i dati non crea sfarfallamenti).

Quote
tornando a leOS
a me serve che un task venga eseguito ogni 1000 millisecondi esatti, quindi uso leOS e non leOS2 perchè 1000 non è multiplo di 16.
se però volessi eseguire il task ogni 2000 millisecondi (multiplo di 16), il task verrebbe eseguito ogni 2 secondi esatti o ogni 2 secondi ± 16ms ?
Il leOS è la prima versione ed è stato scritto basandolo sui timer per cui si ottiene una discreta precisione, ma non una precisione assoluta. Ricordati che stai facendo i conti con un risonatore ceramico (quello dell'Arduino) che è più impreciso di un quarzo per cui anche se setti 1000 ms non avrai un intervallo accurato al millisecondo.
Il leOS2 è meno preciso perché si basa sul watchdog però, a differenza del leOS, non usa timer. Quindi ne va prima di tutto fatta una scelta in base alle proprie necessità. Che si scelga il leOS o il leOS2, poi, l'intervallo scelto è quello poi che effettivamente si avrà: questo vale sia per il leOS, che misura gli intervalli in ms, sia per il leOS2, che li misura in tick.
Logged


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

Quote
Tieni 1 solo buffer per volta e riscrivilo ogni xxx ms senza fare un clear() primo, in modo da: occupare meno memoria possibile; impiegare il minor tempo possibile per gestirlo; evitare sfarfallii dell'immagine (sovrascrivere i dati non crea sfarfallamenti).
molto meglio così, non ho pensato alla riscrittura senza clear
Logged

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

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

ok grazie!
Logged

0
Offline Offline
Faraday Member
**
Karma: 45
Posts: 5784
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

logicamente se non usi il clear devi sovrascrivere tutte le celle di memoria dell'LCD, se ad esempio hai scritto pippolino, e dopo devi scrivere solo pippo, devi aggiungere alla matrice spazi vuoti per cancellare "lino"
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

(slightly-OT) Mi viene in mente che usando un buffer più ampio rispetto alla dimensione del display (ad esempio 40 colonne x 2 righe) e parametrizzando la routine di refresh con la colonna di partenza, si possono generare facilmente delle animazioni. Ad esmpio testo scorrevole. Il codice "applicativo" si comporta come se il display avesse 40 colonne anziché 16. La routine di refresh del display parte dalla colonne impostata (chiamiamola currRefreshCol) per copiare i 16x2 caratteri sul display fisico. Variando currRefreshCol, ad esempio con un'azione temporizzata, si ha che il testo sembra scorrere sull'lcd.
Logged

Pages: 1 ... 22 23 [24] 25 26 ... 31   Go Up
Jump to: