Arduino Forum

International => Italiano => Software => Topic started by: doppiozero on Jun 13, 2018, 10:15 pm

Title: freeRTOS - problema temporizzazione blink
Post by: doppiozero on Jun 13, 2018, 10:15 pm
Ciao, sto provando freeRTOS con una mega2560 pro mini.

Il programma di prova dovrebbe far accendere il led integrato (pin13) per 20ms, ad intervalli di x millisecondi.
Finchè l'intervallo di lampeggio sta sotto i 1000ms tutto ok, sopra i 1000ms il comportamento è bizzarro. Se imposto 1100 ms ottengo una frequenza di 30Hz(invece di 0.9Hz), se imposto 1500ms ottengo 2.23Hz (invece di 0.66Hz), se imposto 2000ms ottengo 1.04Hz (invece di 0.5Hz)

Non riesco a capire dove sta l'inghippo, uso la funzione vTaskDelayUntil() e pdMS_TO_TICKS()

il codice
Code: [Select]
#include <Arduino_FreeRTOS.h>

void TaskBlink(void *pvParameters);

void setup() {

  xTaskCreate(TaskBlink, (const portCHAR *)"Blink", 128, NULL, 2, NULL);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void TaskBlink(void *pvParameters)  // This is a task.
{
  pinMode(LED_BUILTIN, OUTPUT);
  TickType_t xLastWakeTime;
  const TickType_t xPeriod = pdMS_TO_TICKS(2000);
  xLastWakeTime = xTaskGetTickCount();
  for (;;) // A Task shall never return or exit.
  {
    vTaskDelayUntil( &xLastWakeTime, xPeriod );
    digitalWrite(LED_BUILTIN, HIGH);
    vTaskDelay( pdMS_TO_TICKS( 20 ) );
    digitalWrite(LED_BUILTIN, LOW);
  }
}


mi servirebbe una dritta (magari da un mod a caso, che mi pare sia esperto  :D )
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 07:19 am
Allora, butta quel codice :D

1. Per evitare problemi, su Arduino usa sempre l'allocazione statica delle risorse e non quella dinamica

2. l'inizializzazione del HW si fa nel setup(), NON nei task

3. ricorda sempre che stai su Arduino e NON su un PIC32 (dove il "tick" è 1 msec) ... su Arduino il "tick" del sistema operativo, per ragioni di compatibilità con le librerie che usano i timers, è fatto con il WatchDog ed il "tick" minimo è di 15 msec.
Task che terminano prima dello scadere del tick ritornano correttamente il controllo al SO, ma operazioni che coinvolgono i ticks vanno fatte tenendone conto.

4.  Per quanto detto sopra, i periodi calcolati sui tick devono ovviamente essere multipli del tick o ... verranno arrotondati. Per cui, vTaskDelay(20 / portTICK_PERIOD_MS); ti darà, in reltà, il ritardo di circa 1 tick, difatti 20/16 = 1.25 (operazioni con interi arrotondata) e quindi di circa 15 msec.

Detto questo, il tuo codice riscritto correttamete diventa:

Code: [Select]
#include <Arduino_FreeRTOS.h>
#include <task.h>

#define  RITARDO  2000

StackType_t   uxStackBuffer_T1[192];
StaticTask_t  xTaskBuffer_T1;

void MyTask1(void * pvParameters) {
   for (;;) {
      digitalWrite(LED_BUILTIN, HIGH);    // LED acceso
      vTaskDelay(20 / portTICK_PERIOD_MS);
      digitalWrite(LED_BUILTIN, LOW);     // LED spento
      vTaskDelay(RITARDO / portTICK_PERIOD_MS);
   }
}

void setup() {
   pinMode(LED_BUILTIN, OUTPUT);
   digitalWrite(LED_BUILTIN, LOW);
   //
   xTaskCreateStatic(MyTask1, "Task1", 192, NULL, 1, uxStackBuffer_T1, &xTaskBuffer_T1);
}

void loop() {

}

... dove, per divertirti a cambiare l'intervallo x di cui tu parli, ti basta andare a correggere il valore nella #define RITARDO.

Provalo e vedi come va ;)

Guglielmo

P.S.: Tieni sempre a mente che, su un Arduino a 16 MHz hai i seguenti valori costanti definiti dal OS:
portUSE_WDTO = 0 (che corrisponde a WDTO_15MS)
configTICK_RATE_HZ = 62
portTICK_PERIOD_MS = 16
Title: Re: freeRTOS - problema temporizzazione blink
Post by: doppiozero on Jun 14, 2018, 07:53 am
Quote
1. Per evitare problemi, su Arduino usa sempre l'allocazione statica delle risorse e non quella dinamica
ok, annotato

Quote
2. l'inizializzazione del HW si fa nel setup(), NON nei task
ok, però nell'esempio fornito a corredo della libreria l'hardware viene inizializzato nei task. Vedi esempio blink_analogRead.  :smiley-sweat:  

Quote
su Arduino il "tick" del sistema operativo, per ragioni di compatibilità con le librerie che usano i timers, è fatto con il WatchDog ed il "tick" minimo è di 16 msec.
Task che terminano prima dello scadere del tick ritornano correttamente il controllo al SO, ma operazioni che coinvolgono i ticks vanno fatte tenendone conto.
questa era l'altra domanda che volevo fare. Quindi in pratica, se un task termina in <16ms lo scheduler fa partire subito il successivo o aspetta comunque 16ms? Immagino sia tutto scritto nelle guide ma già che ci sono ne approfitto..

Quote
Detto questo, il tuo codice riscritto correttamete diventa:
grazie, stasera lo provo  :)
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 08:38 am
... questa era l'altra domanda che volevo fare. Quindi in pratica, se un task termina in <16ms lo scheduler fa partire subito il successivo o aspetta comunque 16ms?
Come ti ho scritto ... "Task che terminano prima dello scadere del tick ritornano correttamente il controllo al SO ...", quindi, il successivo parte subito.

Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 08:43 am
ok, però nell'esempio fornito a corredo della libreria l'hardware viene inizializzato nei task. Vedi esempio blink_analogRead.  :smiley-sweat: 
... NON è buona pratica !

Anzi, la cosa migliore, sarebbe proprio avere una funzione dedicata all'inizializzazione del HW (... funzione che trovi in tutti gli esempi sul sito di freertos con il nome di prvSetupHardware())

Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 09:01 am
... ah ... occhio, in vTaskDelay() di NON scendere sotto il valore di portTICK_PERIOD_MS, altrimenti la divisione per detto valore, troncata all'intero, da ZERO e ... è un valore che quella funzione NON gradisce affatto :D

Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: doppiozero on Jun 14, 2018, 06:46 pm
Allora, ho fatto qualche prova.

il tuo codice Guglielmo non compila
Code: [Select]
In function 'void setup()':
sketch_jun14b:22: error: 'xTaskCreateStatic' was not declared in this scope
    xTaskCreateStatic(MyTask1, "Task1", 192, NULL, 1, uxStackBuffer_T1, &xTaskBuffer_T1);

 e non sono riuscito a sistemarlo.

Se invece faccio un ibrido tra i due allora funziona:

questo
Code: [Select]
#include <Arduino_FreeRTOS.h>

void TaskBlink(void *pvParameters);

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
  xTaskCreate(TaskBlink, (const portCHAR *)"Blink", 192, NULL, 1, NULL);

}

void loop() {
  // put your main code here, to run repeatedly:

}

void TaskBlink(void *pvParameters)  // This is a task.
{
  for (;;) // A Task shall never return or exit.
  {

    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay(20 / portTICK_PERIOD_MS);
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay(2000 / portTICK_PERIOD_MS);
  }
}

 
e anche questo
Code: [Select]
#include <Arduino_FreeRTOS.h>

void TaskBlink(void *pvParameters);

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
  xTaskCreate(TaskBlink, (const portCHAR *)"Blink", 128, NULL, 2, NULL);

}

void loop() {
  // put your main code here, to run repeatedly:

}

void TaskBlink(void *pvParameters)  // This is a task.
{

  TickType_t xLastWakeTime;
  const TickType_t xPeriod = 2000 / portTICK_PERIOD_MS;
  xLastWakeTime = xTaskGetTickCount();
  for (;;) // A Task shall never return or exit.
  {
    vTaskDelayUntil( &xLastWakeTime, xPeriod );
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay( 20 / portTICK_PERIOD_MS ); // wait for 20millisecond
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  }
}


nel mio codice il problema principale sembra essere pdMS_TO_TICKS()  ::)

p.s. nei reference in pdf, quelli che sto leggendo, portTICK_PERIOD_MS non viene neanche menzionato   :smiley-yell:
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 06:56 pm
Ti da errore perché occorre abilitare le funzioni statiche nel file di configurazione.

Vai nella cartella dei sorgenti della libreria e edita il file "FreeRTOSConfig.h", alla linea 68 modifica in:

Code: [Select]
#define configSUPPORT_STATIC_ALLOCATION     1
Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: doppiozero on Jun 14, 2018, 08:23 pm
Perfetto, compila, grazie  :)
Title: Re: freeRTOS - problema temporizzazione blink
Post by: Patrick_M on Jun 14, 2018, 09:06 pm
ho letto qui (https://www.freertos.org/FreeRTOS_Support_Forum_Archive/February_2016/freertos_On_pdMS_TO_TICKS_macro_definition_317c7160j.html) che pdMS_TO_TICKS() può avere dei problemi a causa dell'overflow nel calcolo che viene eseguito tra interi... non so se può esserti d'aiuto
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 09:13 pm
Perfetto, compila, grazie  :)
Non avevo dubbi  (http://www.nikonland.eu/forum/public/style_emoticons/default/bigemo_harabe_net-03.gif)
Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: gpb01 on Jun 14, 2018, 09:16 pm
ho letto qui (https://www.freertos.org/FreeRTOS_Support_Forum_Archive/February_2016/freertos_On_pdMS_TO_TICKS_macro_definition_317c7160j.html) che pdMS_TO_TICKS() può avere dei problemi a causa dell'overflow nel calcolo che viene eseguito tra interi... non so se può esserti d'aiuto
Si, direi che probabilmente è il suo caso ...
... ma non vale la pena andare a mettere le mani nei sorgenti e modificare, anche perché poi, ogni release il problema si ripete.

La cosa migliore è usare la sintassi che gli ho mostrato (e, su Arduino, ricordarsi che comunque sotto una certa risoluzione NON si va causa il periodo di tick minimo usato). :)

Guglielmo
Title: Re: freeRTOS - problema temporizzazione blink
Post by: doppiozero on Jun 15, 2018, 12:08 am
ho letto qui (https://www.freertos.org/FreeRTOS_Support_Forum_Archive/February_2016/freertos_On_pdMS_TO_TICKS_macro_definition_317c7160j.html) che pdMS_TO_TICKS() può avere dei problemi a causa dell'overflow nel calcolo che viene eseguito tra interi... non so se può esserti d'aiuto
grazie della segnalazione :)