541
Vos projets / Re : projet centrale wifi DCC++ Can
« le: mars 19, 2020, 08:46:16 pm »
Marcel, qu'est-ce que tu appelles "continuer manuellement" ?
Le forum LOCODUINO est consacré aux discussions ayant trait à l'utilisation de l'Arduino dans les automatismes et les animations pour le train miniature. Nous avons eu récemment quelques inscriptions de personnes ayant des projets plus généraux mais surtout inapplicables au train miniature. Si votre projet ou vos questions ne concernent pas le modélisme ferroviaire, ne vous inscrivez pas, vous perdriez votre temps et nous aussi.
Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.
Pour me permettre une évolution en douceur vers les satellites en CAN, au moins l'entrée de commandes en serial sur RX/TX me serait nécessaire.
Tu est sur que les xQueue incluent un mécanisme de protection contre les accès simultanés issus de plusieurs taches ?
/*
Documentation @ http://web.ist.utl.pt/~ist11993/FRTOS-API/group___queue_management.html#xQueueReceive
*/
TaskHandle_t vSenderTask;
TaskHandle_t vReceiverTask;
/* Declaration d'une variable xQueue de type QueueHandle_t qui servira a stocker la file. */
QueueHandle_t xQueue;
/* Taille de la file*/
const uint32_t queueSize = 1000; // Prevoir une taille suffisante pour ne pas perdre de messages
/* Taille maxi de la chaine de caractere */
#define maxCaractInQueue 25
struct Msg {
uint32_t id;
char str[maxCaractInQueue];
} msg;
void setup() {
Serial.begin(115200);
delay(2000);
Serial.printf("\n");
xQueue = xQueueCreate( queueSize, sizeof( struct Msg * ));
if ( xQueue != NULL ) {
xTaskCreatePinnedToCore(
vSenderTaskCode, /* Task function. */
"vSenderTask", /* name of task. */
10000, /* Stack size of task */
NULL,
1, /* priority of the task */
&vSenderTask, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
xTaskCreatePinnedToCore(
vReceiverTaskCode, /* Task function. */
"vReceiverTask", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
2, /* priority of the task */
&vReceiverTask, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
else
Serial.printf("The queue could not be created.");
}
void vSenderTaskCode( void *parameter ) {
struct Msg *ptTxMsg;
BaseType_t xStatus;
ptTxMsg = &msg;
Serial.print("vSenderTask\n");
for (int i = 0; i < 10000; i++) {
ptTxMsg->id = i;
sprintf(ptTxMsg->str, "Ligne %d", i);
xStatus = xQueueSendToBack( xQueue, (void*) &ptTxMsg, 0 );
if ( xStatus == pdPASS )
Serial.printf("Send : %d\n", ptTxMsg->id);
else
Serial.printf( "Could not send to the queue.\n" );
}
vTaskDelete( NULL );
}
void vReceiverTaskCode( void *parameter ) {
struct Msg *ptRxMsg;
BaseType_t xStatus;
const TickType_t xTicksToWait = pdMS_TO_TICKS( 100 );
Serial.print("vReceiverTask\n");
for ( ;; ) {
if ( uxQueueMessagesWaiting( xQueue ) != 0 )
Serial.printf( "Queue should have been empty!\n" );
xStatus = xQueueReceive( xQueue, &(ptRxMsg), xTicksToWait );
if ( xStatus == pdPASS )
Serial.printf( "Received n° %d - value : %s\n", ptRxMsg->id, ptRxMsg->str );
else
Serial.printf( "Could not receive from the queue.\n" );
}
}
void loop() {}
TaskHandle_t vSenderTask;
TaskHandle_t vReceiverTask;
/* Declaration d'une variable xQueue de type QueueHandle_t qui servira a stocker la file. */
QueueHandle_t xQueue;
/* Taille de la file*/
int queueSize = 1000;
/* Taille maxi de la chaine de caractere */
#define maxCaractInQueue 25
void setup() {
Serial.begin(115200);
delay(2000);
Serial.printf("\n");
xQueue = xQueueCreate( queueSize, maxCaractInQueue );
if ( xQueue != NULL ) {
xTaskCreatePinnedToCore(
vSenderTaskCode, /* Task function. */
"vSenderTask", /* name of task. */
10000, /* Stack size of task */
NULL,
1, /* priority of the task */
&vSenderTask, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
xTaskCreatePinnedToCore(
vReceiverTaskCode, /* Task function. */
"vReceiverTask", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
2, /* priority of the task */
&vReceiverTask, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
else
/* The queue could not be created. */
Serial.printf("The queue could not be created.");
}
void vSenderTaskCode( void *parameter ) {
BaseType_t xStatus;
/* Variable qui va contenir la valeur a envoyer*/
char strTx[maxCaractInQueue];
Serial.print("vSenderTask\n");
for (int i = 0; i < queueSize; i++) {
sprintf(strTx, "Ligne %d", i);
xStatus = xQueueSendToBack( xQueue, (char*) strTx, 0 );
if ( xStatus != pdPASS )
Serial.printf( "Could not send to the queue.\r\n" );
else
Serial.printf("Send : %s\n", strTx);
}
vTaskDelete( NULL );
}
void vReceiverTaskCode( void *parameter ) {
BaseType_t xStatus;
/* Variable qui va contenir la valeur recue*/
char strRx[maxCaractInQueue];
const TickType_t xTicksToWait = pdMS_TO_TICKS( 100 );
Serial.print("vReceiverTask\n");
for ( ;; ) {
if ( uxQueueMessagesWaiting( xQueue ) != 0 )
Serial.printf( "Queue should have been empty!\n" );
xStatus = xQueueReceive( xQueue, &strRx, xTicksToWait );
if ( xStatus == pdPASS )
/* Data was successfully received from the queue, print out the received
value. */
Serial.printf( "Received : %s\n", &strRx );
else
Serial.printf( "Could not receive from the queue.\r\n" );
}
}
void loop() {}
L'exemple est sympa et parlant. La difficulté de la gestion multi-tâche réside essentiellement par les synchronisations qu'il faut généralement mettre en place pour éviter les conflits d’accès et/ou d'écriture sur les mêmes données. Les langages C et C++ prévoient des mécanismes type mutex, sémaphore ou lock pour justement contourner ces problèmes. Je ne sais pas ce qui est vraiment disponible pour l'ESP32, et en particulier si c'est utilisable avec un Arduino IDE...
Bonjour Christophe,
Je pense que sur une donnée partagée de type int, ton code ne risque rien. Par contre, si on s'amuse à modifier un objet sur un coeur et de manipuler l'objet par l'autre coeur, je crois qua ça se passera mal tôt ou tard.
A+
TaskHandle_t Task0;
TaskHandle_t Task1;
int intVar = 0;
void setup() {
Serial.begin(115200);
delay(2000);
Serial.printf("\n");
//create a task that will be executed in the Task0code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task0code, /* Task function. */
"Task0", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task0, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
//Task0code
void Task0code( void * pvParameters ) {
Serial.printf("Task0 running on core : %d\n", xPortGetCoreID());
for (;;) {
intVar++;
delay(1000);
}
}
//Task1code
void Task1code( void * pvParameters ) {
Serial.printf("Task1 running on core : %d\n", xPortGetCoreID());
for (;;) {
Serial.printf ("intVar = %d\n", intVar);
delay(1000);
}
}
void loop() {}
Bonsoir,
Avec Dominique, on pensait qu'il fallait pouvoir profiter de l'ESP32 et notamment de ses doubles coeurs processeur.
L'ESP32 embarque le FreeRTOS, un OS temps réel puissant mais qui pour autant un peu bridé par Arduino IDE qui n'exploite au final qu'un coeur (le coeur n°1, sachant que le coeur n°0 ingère de l'idle pendant ce temps).
Après on entre dans le domaine du multitâche / multi thread donc attention aux MUTEX qu'il faudra gérer à la pogne si nécessaire.