Comment connaître les limites en vitesse du microcontrôleur ?

Bonsoir,

Je suis en train de "prototyper" un séquenceur MIDI (tout en apprenant) qui à son terme, aura un programme assez lourd et devra gérer beaucoup d'instructions.
Pour résumer le fonctionnement :

  • Le séquenceur reçoit des signaux de synchronisation via Rx (entre 24 et 60 bytes par seconde en moyenne).
  • Le séquenceur envoie des signaux MIDI via Tx. Chaque signal est une série de 3 bytes (plusieurs signaux devront être envoyés en même temps chaque seconde, à 31250 bauds).
  • Il doit gérer l'affichage d'un écran LCD à caractères
  • Il doit lire les entrées analogiques et numériques

Voilà, tout ça sans compter toutes les instructions qui permettent de traiter les signaux et de faire tourner la machine. Tout ça fait donc un fameux programme.
Le tout doit tourner avec le moins de latence possible (25 ms maximum).

J'en viens donc au point de me poser la question " Jusqu'où je vais pouvoir aller " ? Pour l'instant ça tourne bien, mais si je compte mettre 16 pistes à mon séquenceur (qui en comporte pour l'instant une seule), mettre un écran graphique monochrome à la place de celui à caractères, ça va forcément multiplier les instructions.
Je me suis toujours dit que avec une fréquence de 16Mhz ça laissait une bonne marge mais après réflexion, je pense qu'on peut vite arriver aux limites. J'ai la MEGA (Atmega 2560).

Quels sont alors les moyens de calculer le temps que met le µC à exécuter le programme, de savoir à partir de quel moment j'aurai de la latence ou des pertes de données dans le buffer serial ? Quelles instructions prennent le plus de temps à s'exécuter ?

Bref, j'aimerais être un peu éclairé à ce sujet, je pense que c'est très important à savoir pour savoir par la suite quel µC sera la plus adapté pour un montage définitif, quelle fréquence d'horloge suffira (ça sert à rien d'acheter un µC à 15€ si un à 10€ suffit pour mon appareil).
Je suppose que les réponses vont être assez complexes, mais il pourrait toujours y avoir des explications simplifiées :slight_smile:
Avec Arduino, tout ça est un peu hasardeux, c'est la dernière question qu'on peut se poser... J'aimerais vraiment comprendre comment les pros font pour calculer tout ça 8)

Rien trouvé sur le web à propos de ça.

La première des actions à faire est d'optimiser le code, cela ne sert à rien de choisir un micro hyper rapide si le ralentissement provient du code.

Le code Arduino n'est pas fait pour les applications à faible latence : ce n'est tout bonnement pas son but.
Sans aller jusqu'à l'assembleur, mais peut-être ce sera à envisager, il est possible de programmer directement avec l'avr-libc et la manipulation des registres gérant les sorties.
Mais dans ce cas on est dans la programmation aux petits oignons et plus question d'utiliser des bibliothèques universelles.

Optimiser le code, un point important, ça c'est sûr ! Est-ce que je peux, en attendant de me passer de la carte Arduino, programmer le µC sans utiliser les bibliothèques Arduino mais en passant quand même par la carte et le compilateur ? Je suppose que oui. Dans ce cas j'apprendrai à optimiser la programmation pour que le µC soit le plus rapide possible.
J'imagine qu'il y a du boulot mais ça prendra le temps qu'il faut.

Arduino ça permet d'apprendre facilement mais je pense qu'au bout d'un certain temps, si on est vraiment passionné, il faut passer aux choses sérieuses :stuck_out_tongue: Parce-que après tout, Arduino ne permet pas vraiment de comprendre dans les détails le fonctionnement d'un µC et la façon dont il traite un programme. Or pour pouvoir optimiser un programme à fond, je suppose qu'il faut bien connaître le fonctionnement. :slight_smile:

Est-ce que je peux, en attendant de me passer de la carte Arduino, programmer le µC sans utiliser les bibliothèques Arduino mais en passant quand même par la carte et le compilateur ?

Oui à 100%. Tu n'es même pas obligé d'utiliser l'IDE fourni par Arduino.
A ta disposition il y a Eclipse, code::blocks, le makefile avec tout à la main où d'autres programmes si tu es sous windows.

Je dirais même que sauf besoin très particulier tu n'as pas intérêt, financièrement parlant, a te passer d'une carte "de type Arduino".
Dans ce type de matériel la production en masse fait baisser drastiquement les prix donc autant en profiter tant que faire se peut.

68tjs:
Je dirais même que sauf besoin très particulier tu n'as pas intérêt, financièrement parlant, a te passer d'une carte "de type Arduino".
Dans ce type de matériel la production en masse fait baisser drastiquement les prix donc autant en profiter tant que faire se peut.

Là je comprends pas très bien.. Si on ne prend pas en compte le prix d'un programmateur et du PCB (que je pourrais faire moi-même), de l'alimentation, pourquoi ça me coûterait plus cher qu'une carte Arduino ? Si on prend en compte tout le matériel qu'il faut pour faire fonctionner l'AVR, là je suis d'accord, mais si on a déjà tout ce qu'il faut, je vois pas..
A moins que j'aie oublié certains détails :slight_smile:

Si tu additionne le prix de tous les composants y compris les cm2 de circuit imprimé tu verras que tu ne peux pas rivaliser.
Le prix d'un atmega acheté à l'unité ou même par 10 n'a pas grand chose de commun avec celui négocié directement avec Atmel pour une quantité de 10 000 (ou plus) par an pendant 5 ans.
Parce que les assembleurs de cartes ne commandent pas les atmega uniquement pour faire des cartes ou des clones de cartes arduino ils ont de nombreux autres clients qu'ils ont incité à uniformiser les approvisionnements.

Juste un exemple on trouve des cartes complètes d'interfaçage I2C pour des afficheurs LCD ACL à base de PCF8574 au même prix qu'un PCF8574 à l'unité. C'est bien la preuve que le PCF, ou son clone, est acheté à peine au 1/4 du prix de détail.

A mon avis, a moins que tu ais des circuits d'approvisionnement peu onéreux, merci patron, seuls des besoins spécifiques [1] ou le plaisir de faire soi même, justifient de faire ses cartes soi-même.

[1] les besoins spécifiques peuvent être un schéma particulier ou la nécessité de maîtriser la fiabilité et donc la provenance des composants. La société Arduino décline toute responsabilité si ses cartes sont utilisées dans des domaines touchant à la sécurité, si c'est la cas pour les officielles que dire des clones chinois.

Oui ça je suis au courant, c'est le même principe pour toutes les industries de toute façon :). Moi c'est surtout le plaisir de le faire moi-même et le désir d'apprendre qui justifie le fait de vouloir me passer d'une carte Arduino.
C'est pour ça que j'ai bien précisé que je ne prenais pas en compte le prix du PCB et des accessoires. Une fois qu'on a tout ce qu'il faut, ça reviendra moins cher d'acheter les composants à l'unité pour les assembler soi-même que d'acheter une carte pour chaque projet.

De toute façon je ne cherche pas à faire un produit commercialisable, ça reste de l'amateurisme. Je compte pas faire faire des PCB qualité pro qui me reviendront à 40€ le dm² :wink:

kevo:
Quels sont alors les moyens de calculer le temps que met le µC à exécuter le programme, de savoir à partir de quel moment j'aurai de la latence ou des pertes de données dans le buffer serial ? Quelles instructions prennent le plus de temps à s'exécuter ?

Je dirai d'une manière basique d'utiliser millis() pour connaitre le temps que met ton programme pour faire une boucle et de l'afficher toutes les X boucles.

Cela souligne l'ENORME besoin que nous avons tous d'un simulateur non payant .

Bonjour,

un énorme +1 pour l'optimisation du code.
L'IDE arduino est très pratique, mais certaines de ses fonctions ne sont pas du tout optimisées pour la vitesse, mais plutôt pour la réutilisation facile du code.
Tu peut très bien "taper" directement dans les registres dans tes programmes arduino. Rien que le temps passé pour faire changer 1 sortie d’état et drastiquement changé.
De même tu peut aussi intégrer du code assembleur direct a l’intérieur de la structure principale de ton code en C.

60 octets par secondes, c'est juste super lent pour l'UART de l'arduino. A 9600 bauds, sa vitesse minimum / 11 bit par "coup de transmission" (1 bit de start, 1 stop, 1 parité + 8 bits de données) tu arrive a 872 octets par secondes. A 31250 bauds tu va un peu plus de 3 fois plus vite.
De plus c'est géré en hardware, avec un petit buffer et tout, laissant au CPU du temps pour faire sa petite cuisine pendant que l'UART se charge d'envoyer le paté. Ça ne ralenti presque pas ton code tant que le buffer n'est pas saturé.

Le temps d’acquisition d'une entrée ana je ne m'en rapelle plus exactement mais il est de l'ordre de quelques micro secondes il me semble. De plus sur les PIC je sait qu'on peut le raccourcir a condition de sacrifier une partie de la régulation. Sur l'arduino je pense qu'on peut faire la même chose, a condition de taper dans les registres au lieu d'utiliser les fonctions toutes faites.

Si tu peut modifie ton code pour allumer la led pendant que tu fait des trucs, et éteins la quand tu attends et que tu ne fait rien.
Avec un coup d'oscilloscope tu pourra mesurer avec précision le temps qu'il te reste disponible.
Rien que visuellement tu sera surpris de la voir briller aussi peu, voire pas du tout si ton code est optimisé a fond.

Merci pour ces précisions, un peu de chiffres ça donne déjà une petite idée des performances. Je n'ai plus qu'à me lancer dans la programmation d'un niveau plus bas 8)
A ce propos, pourquoi le compilateur ne fait pas en sorte d'adapter tout le code arduino en langage de bas niveau directement ?

Et oui, un simulateur, ça serait génial ! Je me suis posé la question si ça existait.

Pour ce qui est de la fonction millis (), je compare la valeur entre le début de la boucle et la fin de la boucle, c'est ça ?

Bonjour,

Avec un AVR à 16MHz et une fourchette de temps de 25ms tu peut en faire des choses ! :wink:
~400K instructions en 25ms, c'est de la triche tellement ça en fait :grin:

@MiGaNuTs par défaut tu n'as pas de bit de parité c'est du 8-N-1 = 10 bits au total.

Pour le simulateur ça existe mais c'est pas super "user friendly" et pas non plus très complet :

  • simavr
  • emular
  • ...

Rien ne remplacera jamais un bon vieux test IRL avec un oscilloscope pour voir les timings 8)

Quels sont alors les moyens de calculer le temps que met le µC à exécuter le programme, de savoir à partir de quel moment j'aurai de la latence ou des pertes de données dans le buffer serial ? Quelles instructions prennent le plus de temps à s'exécuter ?

Il faut regarder la fréquence du quarts sur ta carte, la plus par des cartes Arduino ont un cristal de 16 mhz,
16 mhz sa fais a peu près 16 000 000 boucle seconde,
Le Microcontroleur étant 8 bit il doit théoriquement générée 8 bit d'information par boucle ( en théorique ),
Maintenant n'utilisent pas du bas niveau aller savoir ce qu'il nous reste a utiliser ?

sinon topic très intéressent cela me fais me demander si l'ont peu utiliser du bas niveau avec un Arduino déjà monter ou si l'ont doit utiliser un montage autre pour le microcontroleur ?

kevo:
Pour ce qui est de la fonction millis (), je compare la valeur entre le début de la boucle et la fin de la boucle, c'est ça ?

Je pensai à un seul endroit de ta loop() (début ou fin), tu stock millis() dans une variable et cette variable tu la compares au millis() quand tu reviens au même endroit de ta loop().

lacolombenoir:
sinon topic très intéressent cela me fais me demander si l'ont peu utiliser du bas niveau avec un Arduino déjà monter ou si l'ont doit utiliser un montage autre pour le microcontroleur ?

Bien sûr que l'on peu :wink:
Une carte arduino c'est avant tout un microcontrôleur AVR et le compilateur AVR-GCC.
Exemple de code bas niveau : GitHub - skywodd/AVR_DCPU_16: AVR based DCPU-16 emulator (from notch game spec 1.1)

Pac2Kro:

kevo:
Pour ce qui est de la fonction millis (), je compare la valeur entre le début de la boucle et la fin de la boucle, c'est ça ?

Je pensai à un seul endroit de ta loop() (début ou fin), tu stock millis() dans une variable et cette variable tu la compares au millis() quand tu reviens au même endroit de ta loop().

La meilleur solution c'est de faire commuter une broche (sans digitalWrite ! Directement avec le registre PORTx qui va bien) et de regarder la fréquence du signal sur cette broche avec un oscilloscope.
A part pour un traitement très gourmand en ressources cpu faire un delta-temps avec millis donnera toujours 0.

skywodd:
A part pour un traitement très gourmand en ressources cpu faire un delta-temps avec millis donnera toujours 0.

Même sur 1000 loop() (ou plus)?

Pac2Kro:
Même sur 1000 loop() (ou plus)?

1ms à 16MHz ça fait 16 000 instructions environ, donc ta boucle de 1000 itérations va être vite fini :wink:
En plus si la boucle fait "rien" le compilateur va la virer par soucis d'optimisation.

Et en utilisant micros () ? :slight_smile:

Je n'ai malheureusement pas d'oscillo pour voir ça en détails.. Je vais pas trop m'en faire pour le moment alors, je verrai bien en testant jusqu'où je pourrai pousser les capacités de la pupuce :stuck_out_tongue:

Merci pour votre collaboration :wink:

kevo:
Et en utilisant micros () ? :slight_smile:

C'est envisageable mais n'oublie pas que tu auras une perte de temps constante due à l'appel de la fonction micros() :wink:

kevo:
Je n'ai malheureusement pas d'oscillo pour voir ça en détails.. Je vais pas trop m'en faire pour le moment alors, je verrai bien en testant jusqu'où je pourrai pousser les capacités de la pupuce :stuck_out_tongue:

Tu aurais un code à tester ? J'ai un oscillo numérique, si besoin je peut te faire des captures d'écrans :wink:

Non c'est bien gentil, mon programme n'est pas encore complet et il tourne bien pour le moment.. Je reviendrai sur ce topic quand ça sera vraiment nécessaire. En attendant, j'y vais à l'aveuglette 8)

Merci merci :wink: