Arduino peut-on faire du multitâche?

J’ai entendu dire plusieurs fois “L’Arduino n’est pas multitâche!”. Bon. Mais le matin au réveil, c’est là que je trouve les idées qui me donne une solution, une nouvelle piste pour avancer dans un programme qui jusqu’à présent bloquait. Par exemple:

  • c’est un matin que j’ai pensé a faire une bibliothèque pour les boutons, les leds, les timers, un peu comme easyRun ou comme timer.h, mais sans mettre le fameux timer.tick();t.update(); easyRun(); scanEvent(); etc…
  • c’est un matin que j’ai pensé à utiliser le timer 0, sans toucher à la gestion (que je n’aime pas) pour avoir d’autres bases de temps en plus
  • c’est un matin que j’ai pensé mettre un moteur 5 fils unipolaire sur un driver bipolaire.
    … Enfin toutes des chose qu’il est admis que ce n’est pas possible.

Personne n’a démontré qu’on ne peut pas se passer de scanEvent(); que l’on ne peut pas avec le timer 0 faire deux bases de temps, que l’on ne peut pas mettre le fameux 5 fils… On l’a admis. Axiome! Pour les maths, rien n’est démontré. Par contre on peut prouver le contraire… si on y arrive.

L’idée du jour (aller au bar dès le matin, ma grand-mère me le défendait, pourtant j’y suis, paix à son âme) c’est le multitâche. J’attrape Oui-qui qui me sort:
Un système d’exploitation est multitâche s’il permet d’exécuter, de façon apparemment simultanée, plusieurs programmes informatiques. On parle également de multiprogrammation. Cette fonction est indépendante du nombre de processeurs présents physiquement dans l’ordinateur.

Bonne pioche, si c’est ça le multitâche, “indépendante du nombre de processeurs” cela veut dire que j’i j’ai un seul processeur, je peux avoir plusieurs tâches qui s’exécutent en même temps de “façon apparemment simultanée”. L’idée est simple: on aurait pour rester dans les habitudes arduinosiennes une fonction setup() - ou setUp() suivant la règle du C -, et plusieurs fonctions loopEt(), loopIng(), loopIot(), loopItal()… qui serait actives “apparemment” en même temps, c’est à dire un petit bout pour la première, un petit bout pour la deuxième…

Reste à voir pour la répartition, mon idée, c’est de dire 1ms chacune pour commencer.

Si quelqu’un me dit c’est impossible, qu’il le démontre! Et dans le cas contraire, qu’on le fasse. Imaginez la joie des utilisateurs de delay():

loop1()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}

loop2()
{
  for (uint32_t i=1; i<100000000; i++) Serial.println(i);
}

loop3()
{
  tft.clrscr();
  ...
}

Qu'est-ce que tu appelle "une arduino" ?
La carte de base avec son atmega 328p, les MKR avec des ARM Samd ou la dernière "Potenta" avec son STM32 H7 de compétition : 480 MHz et 1 mega de mémoire ?

Concernant la carte de base ce que tu dis est déjà réalisé depuis longtemps, il me semble que dans ses nombreux tutos Bricoleau a déjà proposé une bibliothèque ( a vérifier).

Ca c'est pour le principe après il y a le coté "qu'est ce qui est réalisable".
Ce coté fait intervenir la rapidité d'exécution du microcontroleur et la quantité de mémoire disponible.
Et sur ce plan on ne peut pas dire que les micros avr soient le meilleur choix, même si le coté défi est sympa intellectuellement.

La série des ARM STM32 dont la célèblre blue pill peut recevoir FreeRtos, système d'exploitation multitache. Des exemples sont disponibles.
Probablement que la série Atmel ARM SAM (dont les cartes MKR) peut aussi recevoir FreeRtos

Les circuits Espressif tournent de base sous FreeRtos pour pouvoir gerer simultanément le programme et le WiFi.
Ce n'est dit pas clairement et c'est bien la cause de rebootages intenpestifs en cas de blocage d'une tâche. On en parle à intervalle régulier sur ce forum. Je ne pense pas que la gestion de FreeRtos soit à la portée de beaucoup, en tout cas pas de moi.

vileroi:
Reste à voir pour la répartition, mon idée, c'est de dire 1ms chacune pour commencer.

Bonjour,
c'est pertinent si toutes les tâches ont la même charge cpu, et la même priorité ... donc pas top

Bonjour

Pour répondre à la question formulée dans le titre accrocheur et en considérant les cartes avec des ATmega328, ATMega32U4, ATmega2560 : oui il peut le faire !

voir par exemple les portages de FreeRTOS comme celui-ci : GitHub - ExploreEmbedded/Arduino_FreeRTOS: FreeRtos tutorial examples on arduino

Mais le matin au réveil, c'est là que je trouve les idées qui me donne une solution

Un pastis le matin,
C'est bon pour l'innovatin

La preuve, j'ai trouvé une rime riche au bout de mon troisième...

vileroi:
Reste à voir pour la répartition, mon idée, c'est de dire 1ms chacune pour commencer.

C'est très ambitieux. La config par défaut du tick rate de FreeRTOS est de 100Hz (10ms). Plus la fréquence augmente plus le microcontrôleur passe de temps dans le code du scheduler.
Pour une fréquence de 1KHz il faudrait un gros STM32.

D'autre part il ne faut pas oublier les 2Ko de RAM d'un Atmega328, auxquels il faut soustraire la mémoire réservée aux variables statiques. La création de chaque tâche implique l'allocation d'un espace de RAM pour sa pile, et le diagnostic risque d'être pénible en cas de débordement.

Hello

Autre question toute simple : quels types de montages arduino nécessitent un "vrai" multi-tâche?
C'est-à-dire un système capable de switcher à haute fréquence entre plusieurs process.

Perso je navigue depuis des années dans l'univers arduino.
Je me suis posé la même question que toi, et ma réponse a été :
En dehors des programmes très basiques, il est très souvent nécessaire de faire "plusieurs choses à la fois".
Et pour cela, 99% des cas d'usage sont largement couverts par un simple ordonnanceur coopératif.

C'est dans ce sens que j'ai écrit easyRun, en essayant d'y embarquer un maximum d'outils de base, les plus simples possibles à utiliser, avec un code généré compact, et de multiples possibilités d'extensions.
Ce n'est certainement la solution miracle pour tous les montages, on peut préférer gérer soi-même le temps avec millis(), mais perso depuis que j'appuie 100% de mes dev sur ce socle de base, j'en suis de plus en plus fan.
Il m'arrive d'écrire du code ou des libs pour les autres, au final je ne m'en sers pas ou peu.
Mais là le premier utilisateur satisfait c'est vraiment bibiche :slight_smile:

Qu'est-ce que tu appelle "une arduino" ?

Effectivement, pour chacun cela représente autre chose. J'en suis resté à l'Uno/nano, parfois la Mega. J'aime mieux avoir une carte que je connais assez bien plutôt que plein de cartes avec les quelles je n'y comprend rien.
Cette idée me trotte dans la tête suite aux nombreux messages sur Uno qui disent, "j'ai tester mon machin, ça marche, j'ai testé mon truc, ça marche, comment faire pour les mettre ensembles?". Et la réponse est en principe, c'est simple, il faut tout changer, va dire bonjour à millis() et au revoir à delay().

Concernant la carte de base ce que tu dis est déjà réalisé depuis longtemps, il me semble que dans ses nombreux tutos Bricoleau a déjà proposé une bibliothèque ( a vérifier).

Si c'est de easyRun dont tu parles, il ne s'agit pas de multitâche, mais de programmation évènementielle. J'ai fais aussi un peu la même chose pour gérer mon écran, et j'ai vu 2 ou 3 réalisations dans le même sens. Avec easyRun, on ne peut pas écrire deux programmes qui fonctionnent et les mettre ensembles

Ca c'est pour le principe après il y a le coté "qu'est ce qui est réalisable".
Ce coté fait intervenir la rapidité d'exécution du microcontroleur et la quantité de mémoire disponible.
Et sur ce plan on ne peut pas dire que les micros avr soient le meilleur choix, même si le coté défi est sympa intellectuellement.

C'est sans doute le côté défi qui m'intéresse. Et puis pour beaucoup d'applications, on n'a pas forcément besoin d'une usina à gaz. C'est pour cela que j'aime bien l'Uno.

Probablement que la série Atmel ARM SAM (dont les cartes MKR) peut aussi recevoir FreeRtos

FreeRtos est exactement ce dont je parlais. Et c'est dit que cela tourne sur Uo. Moi, je veux bien, mais l'exemple Blink_AnalogRead utilise 146% de la mémoire. A priori, je ne comprend pas pourquoi le programme est si gros.
Si j'ai un gros système, on peut avoir quelque chose de puissant, si le système est petit, on doit réduire ses exigences.

C'est pareil pour les 1ms que j'ai donné. Il n'est pas question de faire un truc super performant. Et les programmes que l'on a bien souvent sont assez basiques.

voir par exemple les portages de FreeRTOS comme celui-ci : GitHub - ExploreEmbedded/Arduino_FreeRTOS: FreeRtos tutorial examples on arduino


Je n'ai vu que ceci sur une Uno:
_01-TaskSwitching -> 174% de l'espace de stockage
AnalogRead_DigitalRead -> 165% de l'espace de stockage
Je ne les ai pas tous faits.

C'est très ambitieux. La config par défaut du tick rate de FreeRTOS est de 100Hz (10ms). Plus la fréquence augmente plus le microcontrôleur passe de temps dans le code du scheduler.

C'est bien ça qui me pose problème. Qu'y a-t-il de si long à faire pour changer de tâche?
Je reprends ce que j'ai vu quand on a une interruption. On sauvegarde le contexte (les registres et le contenu de la pile). On procède à l'interruption, puis on remet le contexte. Pour une simple interruption, on peut ne sauvegarder qu'une partie des registres.
Je lis un livre, on sonne à a porte, je mets un marque page, je réponds et quand c'est fini, je reprend mon livre ou j'en étais. La différence est qu'ici, on change de livre à chaque fois.
La nano qui gère la lumière de la cuisine tourne à 16MHz, et je suis sûr que si la carte tournait à 16kHz, je ne verrais pas la différence.

D'autre part il ne faut pas oublier les 2Ko de RAM d'un Atmega328, auxquels il faut soustraire la mémoire réservée aux variables statiques. La création de chaque tâche implique l'allocation d'un espace de RAM pour sa pile, et le diagnostic risque d'être pénible en cas de débordement.

Si on a deux programmes qui fonctionnent indépendamment et qu'on mange un partie de la pile pour faire les tests, ce ne devrait pas poser de problème pour l'assemblage. En fait si on déborde c'est qu'on n'est pas dans le schéma simple de deux petits programmes.

Autre question toute simple : quels types de montages arduino nécessitent un "vrai" multi-tâche?
C'est-à-dire un système capable de switcher à haute fréquence entre plusieurs process.

Aucun, je pense, c'est simplement la possibilité d'écrire deux codes simples et de pouvoir les coller.
C'est vrai au final, j'utilise mon ordonnanceur perso...
Je ferais mieux de me pencher sur la carte SD et ses 700o de ram nécessaire...