Facteurs ralentissant un code

Bonjour,
Je serais soucieux de perdre des mauvaises habitudes , qui ralentissent dans les croquis Arduino !

J'ai l'habitude de mettre des noms de variables long et explicites par des "_"
A la compilation , j'ai lu que pour chaque variable, une attribution mémoire est réalisée

  1. A partir de combien de caractère dans le nom de la variable la quantité de mémoire est augmentée ?

  2. A partir de combien de caractère dans le nom de la variable vitesse d'exécution du code est ralenti ?

  3. J'ai lu que les commentaires dans le code sont ignorés, j'adore me mettre des penses bêtes pour m'aider lors d'une reprise du code dans l'avenir : Est-ce bien sans conséquences sur la vitesse?

  4. Y-a-il un moyen d'insérer un fichier texte d'aide hors du fichier .Ino et dans un onglet du croquis.
    pour l'instant je les renomme, certainement à tord, avec l'extension h

  5. Les boucles for pénalisent-ils beaucoup la vitesse par rapport à l'exécution à la queue leu leu ?

  6. Est ce une variable défini ainsi, int DeadZone = DEADZONE; dans le fichier ino et par #define DEADZONE 5 dans un fichier config.h présent dans le croquis influence la vitesse par rapport à une déclaration directe dans le fichier ino de int DeadZone = 5;

  7. L'usage des tableaux est-elle conseillé pour minimiser le temps d'exécution d'un code ?

Merci de vos expériences que vous mettez en commum

Bonjour

  1. et 2)

J'ai l'habitude de mettre des noms de variables long et explicites par des "_"

Garder cette bonne habitude !! des noms longs et explicites

A la compilation , j'ai lu que pour chaque variable, une attribution mémoire est réalisée

L'espace occupé en mémoire par une variable est sans rapport avec son nom mais uniquement avec son type ( char, int, float...)

Les noms des variables ne sont pas présents dans le code, le compilateur les fait disparaître.
Ces noms sont sans influence sur la vitesse d'éxécution du code et son encombrement en mémoire.

  1. Oui
  1. tu peux mettre un fichier txt ou autre dans le même répertoire que ton programme. Le compilateur ignore toutes les extensions de fichier qu'il ne connait pas.

  2. les boucles for n'ont rien de pénalisant d'un point de vue performance. Cela dépend juste des instructions présentes dans la boucle.

  3. le mieux est de déclarer :
    const int deadZone = 5;
    deadZone ne sera alors pas une variable qui occupe de la place en mémoire.
    Le compilateur va remplacer deadZone par 5 partout où il est présent.
    Cela revient un peu au même qu'avec un #define, mais là au moins le compilateur va pouvoir vérifier que les usages de deadZone sont bien compatibles avec son type int.

  4. rien de pénalisant dans les tableaux d'un point de vue performance.

Tfou57:
5) Les boucles for pénalisent-ils beaucoup la vitesse par rapport à l'exécution à la queue leu leu ?

Ca dépend de ce qu'il y a à l'intérieur de la boucle. Pluys c'est lourd, moins la le supplément dû à la boucle est important.
Mais bon, programmer à la queu leu leu au delà de 3 éléments, ça devient ingérable.

  1. Est ce une variable défini ainsi, int DeadZone = DEADZONE; dans le fichier ino et par #define DEADZONE 5 dans un fichier config.h présent dans le croquis influence la vitesse par rapport à une déclaration directe dans le fichier ino de int DeadZone = 5;

Aucune incidence. Tout ça disparait dès la phase de compilation.

  1. L'usage des tableaux est-elle conseillé pour minimiser le temps d'exécution d'un code ?

Ca prend toujours un peu plus de temps d'accéder à X [ i ] qu'à Y simple variable.
Mais comme dit plus haut, au delà de 3 éléments, le tableau s'impose (sauf si la vitesse est absolument critique)

C’est assez difficile de donner des affirmations car le compilateur fait pas mal d’optimisations, il peut par exemple remplacer une boucle for par autre chose d’équivalent. On ne peut pas être aussi catégorique. Par exemple avec les définitions

uint8_t i, t[10];

le code

i++;

prends 5 périodes d’horloge

t[0]++;

prends aussi 5 périodes d’horloges car i comme t[0] ont des adresses fixes

t[i]++;

lui va prendre 10 cycles si i ne peut pas être évalué à la compilation. Mais si i peut être évalué par le compilateur, il est possible que t*++; soit remplacé par t[]*
Pour les boucles, c’est pas mieux, j’ai testé:
* *t[i++]++; t[i++]++; t[i++]++; t[i++]++; t[i++]++; t[i++]++;* *
cela me prends 85 périodes d’horloges et
* *for (uint8_t i=0 i<6; i++) t[i]++;* *
gaspille 133 périodes (8µs)
MAIS cela prend 100 octets de moins dans la mémoire programme. Mieux, pas mieux, cela dépend du besoin.

5 et 7) --> Le compilateur se charge de transformer les boucles for en répétition de code quand il juge que ce sera un gain. (loop unrolling)

"7) L'usage des tableaux est-elle conseillé pour minimiser le temps d'exécution d'un code ? "
Bonjour,
pas certain d'avoir compris la question
pour info, j'utilise volontiers des tableaux en flash pour éviter au mcu d'avoir à faire des calculs (une abaque)
-> on gagne forcément en vitesse
-> voire souvent, à son grand étonnement, en occupation de la flash

trimarco232:
"7) L'usage des tableaux est-elle conseillé pour minimiser le temps d'exécution d'un code ? "
Bonjour,
pas certain d'avoir compris la question
pour info, j'utilise volontiers des tableaux en flash pour éviter au mcu d'avoir à faire des calculs (une abaque)
-> on gagne forcément en vitesse
-> voire souvent, à son grand étonnement, en occupation de la flash

L'intervention de @trimarco232 ,me fait penser à une série de questions
J'utilise des tableaux variables et résultats de calcul mélangés
Je pense que ces tableaux sont chargé en RAM ( arrêtez moi si je suis dans l'erreur)
Dans un gain de pas pénaliser la vitesse d'exécution faut -il:

  1. Ne pas utiliser de grand tableau mélangeant variables et résultats de calcul ?

  2. Utiliser plusieurs tableau par thème ( cela éclaircirait la lecture du code) ?

  3. Comment charger et lire un tableau de variable de configuration en mémoire Flash ?
    Un petit code exemple serait le bienvenu pour les tableaux en Flash

Je profite de cette intervention pour poser une autre question concernant la diminution du temps d'exécution:
Sur une Arduino Due avec un "programming port" et un "native USB port"

  • La branche centrale travail sur le "programming port" en lisant par les commande serial... les consignes de position provenant d'un logicel SimTools, elle calcule et commande les Output en fonction des positions cible et position actuelle
  • La branche secondaire exécutée à chaque boucle de Loop est gourmante en vitesse d'éxécution.
    A l'aide des commandes serielUSB... , elle affiche en simultanée sur le moniteur série du "native USB port", les positions actuelles et la position cible à atteindre pour tous les moteurs.
  1. Peux-t-on, sans planter "programming port" et un "native USB port" établir l’exécution ou non l’exécution de la branche secondaire de débuggage
    Je pensais utiliser une pin libre et un switch pour basculer en mode visualisation sur le moniteur série "native USB port" et pour sortir de ce mode
    Sans jamais arrêter la branche principale et planter un des 2 ports USB, j'aurais besoin d'établir ou d'interrompre le moniteur série de la branche secondaire

Je remercie tous les intervenants qui partagent leurs connaissances !

J’ai l’impression que vous vous faites des noeuds au cerveau si vous essayez de tout optimiser avant de voir où le temps est passé. Si en plus vous êtes dépendant du port série pour recevoir des commandes, la vitesse du port sera aussi sans doute un facteur limitant important

Pour les tableaux en flash, regardez la doc de PROGMEM

J-M-L:
Si en plus vous êtes dépendant du port série pour recevoir des commandes, la vitesse du port sera aussi sans doute un facteur limitant important

Pouvez-vous un peu développer …
Je crois comprendre que je dois d’abord mesurer le temps d’exécution de la branche principale pour adapter la vitesse du “programming port” ? ( en affichant le résullat sur le moniteur série “native USB port”
et en fonction du résultat adapter la vitesse des 2 ports série
Pour l’instant le “programming port” et le “native USB port” sont a 115200 bauds

Le Baud étant la vitesse de transmission est égale à un bit par seconde, ensuite je doute pour la relation entre la vitesse d’éxecution en µs et le baud . ( 1 / 115200 ???)
Que sont les conséquence si le code tourne plus vite que les liaisons série ?
? Je pense que les conséquences se font sentir lorsque le code est plus lent que la liaison série … ?

Pour mesurer le temps d’exécution du programme y a t-il une manière plus fiable qu’une autre ?

Merci de votre aide à ce sujet, je ne pensais pas du tout à ce problème de vitesse de liaison série !

Pour faire simple, à 115200 bauds il vous faut 3 millisecondes pour recevoir une commande d’environ 30 caractères. Pendant ce temps si vous ne bloquez pas votre processus ça vous donne du temps pour travailler sur la commande précédente

Vous prenez votre problème un peu à l’envers. Expliquez ce que doit faire le code, la complexité de traitement d’une commande, la fréquence d’arrivée des commandes etc

Une fois que vous avez les idées claires sur le temps dont vous disposez pour traiter une commande, vous cherchez à optimiser le traitement si ça ne rentre pas dans le temps imparti

Pour mémoire, c'est un challenge que les programmeurs ont depuis des générations; Déjà en 1974 Donald Knuth avait publié "Structured Programming with Goto statements" dans lequel il disait:

"There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."

Bonjour,
Merci pour ces éclaircissements,
Dites-moi si je me trompe, j'ai compris que selon cycle ci-dessous
Je vois à première vue que je dois paramétrer la réactualisation des données SimTools à une valeur en ms assez élevée

Comme la valeur de réactualisation des valeurs consigne doit être le plus faible possible pour ressentir au mieux la télémétrie! (voir ci-dessous l'étape 0)
et
> Comme l'étape 0 doit être plus rapide que la somme du temps d'exécution des étapes 1 à 5

Comment configurer le programming port (COM3) de la Due à une vitesse de 250000 bauds , cela permettra de diminuer drastiquement le temps de la boucle Loop ?

Nota:
Sur mon imprimante 3D ayant une base Arduino Méga 2560, je configure le logiciel Repetier à 250000 bauds pour commander l'imprimante et ceci malgré que windows ait son port COM à 115200.
Pouvez-vous m'aider à configurer l'Arduino Due à vitesse 250000 bauds sur programming port ?

Je ne souhaite pas utiliser le "native USB port" pour exécuter ma branche principale du code Arduino, car sur ce port le numéro de port attribué par Windows 8.1 est trés souvent changeant. Par contre le programming port est toujours rattaché au COM3
Y-a-il un moyen de le fixer sur un numéro comme le COM4 (par exemple) ?

Comme vous le souhaitiez, je vous résume le cycle du projet SimTools - Arduino Due
SimTools
Etape 0: SimTools extrait la télémétrie des jeux de simulation et envoie 20 caractères pour les consignes de position pour 4 moteurs
La fréquence d'envoie de ces données de consignes est réglage en nombre de ms entier (1,2,3 ...)
Mon projet étant évolutif de 2 moteurs (stade initial) à 4 moteurs (stade final) et comme chaque moteurs reçoit 5 caractères pour sa consigne de valeur cible à atteindre

Arduino Due
Etape 1 :Lecture par Serial.read (branche principale du code qui est à terme appelée à tourner seule) des valeurs de positions cibles
Lecture de 20 caractères pour la gestion de 4 moteurs

Etape 2 Lecture ADC de la position des 4 motoréducteurs (utilisation d'un potentiomètre entrainé par chaque moto réducteur

Etape 3 Interprétation des commandes en fonction de la lecture par Serial.read et de la lecture ADC de la position des 4 motoréducteurs

Etape 4 Evaluation de l'écart de position souhaitée par rapport à la position actuelle des actionneurs ( axes des moto-réducteurs)
Calcul avec gestion du PID du correctif de position à effectuer sur les 4 actionneurs

Etape 5 Commande des 4 motoréducteurs via une interface de puisance ( PWM pour la vitesse et 2 signaux digitaux pour le sens de rotation)

Puis à nouveau Etape 1 sur Arduino Due , l'étape 0 se réactualise systématiquement une fréquence fixe indépendante de l'Arduino .

Merci pour votre aide pour optimiser la vitesse du port programmation de l'Arduino Due (Serial.read) :grin:

je n'ai pas de Due mais il y a des discussion en ligne, il y a des limitations sur ce port ==> cf par exemple ici

Pourquoi passer par le Programing port sur le Due cependant alors que vous avez 3 ports Séries supplémentaires

The Arduino Due has three additional 3.3V TTL serial ports: Serial1 on pins 19 (RX) and 18 (TX); Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX). Pins 0 and 1 are also connected to the corresponding pins of the ATmega16U2 USB-to-TTL Serial chip, which is connected to the USB debug port. Additionally, there is a native USB-serial port on the SAM3X chip, SerialUSB'.

prenez un de ces autres ports avec un petit FTDI branché sur votre PC (comme cela ça devrait conserver le port) et ouvrez la communication à 2,000,000 bauds si vous voulez que ça booste !

Ensuite comment envoyez vous les données ? je ne connais pas SimTools mais y-a-t-il moyen d'envoyer les chiffres en binaire plutôt qu'en ASCII ? vous gagnez en nombre d'octets à transférer et en temps de conversion ASCII -> nombre côté Arduino.

Concernant les moteurs, être capable de réagir à des changements de position sous la ms nécessitent des moteurs puissants, avec grosse alimentation et une armature mécanique de tout premier ordre (en fer). est-ce que c'est ce dont vous disposez ?

J-M-L:
je n'ai pas de Due mais il y a des discussion en ligne, il y a des limitations sur ce port ==> cf par exemple ici

Ensuite comment envoyez vous les données ? je ne connais pas SimTools mais y-a-t-il moyen d'envoyer les chiffres en binaire plutôt qu'en ASCII ? vous gagnez en nombre d'octets à transférer et en temps de conversion ASCII -> nombre côté Arduino.

Concernant les moteurs, être capable de réagir à des changements de position sous la ms nécessitent des moteurs puissants, avec grosse alimentation et une armature mécanique de tout premier ordre (en fer). est-ce que c'est ce dont vous disposez ?

Merci pour le lien, j'avais déjà vu ce site ou il conseille de le configurer Serial à 210000 au lieu de 250000.
Je pensais que vous aviez une autre source d'information à une vitesse fiable

SimTools m'envoie uniquement sur le port série des données binaire en 10 bits pour ma version actuelle de code et 12 bits dans le second stade.

Les motoréducteurs SEW sont robustes ( type industriel 550W tri 16tr/mn) , ils sont pilotés par des variateurs de fréquence Omron qui permettent d'atteindre sans problème une vitesse d'approche à 32tr/mn. En sortie d'arbre il y une bielle pouvant commander un basculement de la plate forme du simulateur dynamique

Etape 0: SimTools extrait la télémétrie des jeux de simulation et envoie 20 caractères pour les consignes de position pour 4 moteurs. La fréquence d'envoie de ces données de consignes est réglage en nombre de ms entier (1,2,3 ...)

SimTools m'envoie uniquement sur le port série des données binaire en 10 bits pour ma version actuelle de code et 12 bits dans le second stade

vous parlez de 20 caractères, je suppose qu'il s'agit d'octets ? Vos données sont sur 10 ou 12 bits, donc 2 octets par donnée où tout est packé sous forme de 10 bits + 10 bits + 10 bits (ie 160 bits en 20 octets soit 16 données au final ? pouvez vous expliquer un peu plus ce que vous recevez ?

à 115200 bauds vos premiers 20 octets vont mettre 1,8ms à arriver. Une fois qu'ils sont dans le buffer vous pouvez les lire d'un coup si vous avez besoin d'une trame entière pour commencer à bosser.

Si vous réglez la période d'émission à 2ms ça vous laisse 2,2ms avant l'arrivée de la prochaine trame complète pour traiter la commande ==> si vous êtes capable de traiter une commande en 2ms disons pour avoir 10% "de gras" vous tiendrez la cadence

Dans votre

Etape 2 Lecture ADC de la position des 4 motoréducteurs

s'agit-il d'un bête analogRead() ou vous avez un ADC qui lit les valeurs ? Si vous faites le traitement sur Arduino il faudra faire une double lecture pour avoir une bonne précision (microcontrôleur SAM3X8E comporte un convertisseur analogique-numérique 12 bits et un multiplexeur permet d'utiliser vos 12 entrées analogiques). Donc 8 analogRead. Si vous ne faites rien de particulier ça va prendre 8x40 = 320µs soit 0,3 précieuses millisecondes... Il existe des techniques pour améliorer cela et en passant en free running mode et en lisant directement le registre on peut diviser ce temps significativement (l'article dit 1µs), comptons large à 30µs

Mettre le PWM est rapide à exécuter (un analogWrite() ?)

donc le gros du boulot est plutôt le calcul du PID qui devra être bien fichu - avez vous chiffré le temps de calcul ?

Merci de s’interesser à mon projet,

" Vous parlez de 20 caractères, je suppose qu’il s’agit d’octets ? " Zut, c’est bien 20 octets pour 4 moteurs !

" Vos données sont sur 10 ou 12 bits, donc 2 octets par donnée où tout est packé sous forme de 10 bits + 10 bits + 10 bits (ie 160 bits en 20 octets soit 16 données au final

? pouvez vous expliquer un peu plus ce que vous recevez ? "

Par moteurs, ce sont 5 octects qui sont lus , donc dans le stade final avec 4 moteurs se sera 20 octetsqui seront lus
Pour le stade inital avec 2 moteurs, je recois une trame de consigne de positions à réaliser ayant une synthase : X1CX2C
Attente de reception de la lettre X pour lire, stocker et analyser les 4 octets derrière
La trame est validée en vérifiant que le dernier caractère est bien un C
Après le X j’ai le numéro du moteur (1 à 6) suivi de deux octets pour la valeur de consigne (sur 10 bits) puis le “checksum” C pour valider sinon la trame est rejetée

“à 115200 bauds vos premiers 20 octets vont mettre 1,8ms à arriver. Une fois qu’ils sont dans le buffer vous pouvez les lire d’un coup si vous avez besoin d’une trame entière pour commencer à bosser.”
(1 x 20 ) / 115200 = 0,0001736 = 0,17ms sauf erreur. la formule que j’ai posée est incorrecte ?

“Si vous réglez la période d’émission à 2ms ça vous laisse 2,2ms avant l’arrivée de la prochaine trame complète pour traiter la commande ==> si vous êtes capable de traiter une commande en 2ms disons pour avoir 10% “de gras” vous tiendrez la cadence”
Je n’arrive pas à comprendre votre résonnement ! Pouvez-vous me l’expliquer autrement ?
“Si vous réglez la période d’émission à 2ms”, il s’agit donc de la trame de consigne émise sur le port COM Programming par SimTools !
Donc “période d’émission à 2ms” doit être supérieur de 10% par rapport à la somme des temps d’exécution des étapes 1 à 5 ?(voir post11)

ADC


" Etape 2 Lecture ADC de la position des 4 moto réducteurs
s’agit-il d’un bête analogRead() ou vous avez un ADC qui lit les valeurs ? Si vous faites le traitement sur Arduino il faudra faire une double lecture pour avoir une bonne

précision (microcontrôleur SAM3X8E comporte un convertisseur analogique-numérique 12 bits et un multiplexeur permet d’utiliser vos 12 entrées analogiques). Donc 8 analogRead.

Si vous ne faites rien de particulier ça va prendre 8x40 = 320µs soit 0,3 précieuses millisecondes… Il existe des techniques pour améliorer cela et en passant en free

running mode et en lisant directement le registre on peut diviser ce temps significativement (l’article dit 1µs), comptons large à 30µs "

Pour l’instant je cherche à terminer l’adaptation du code de Wanegain en supprimant les manipulations de registres non adapter à l’Arduino Due
Dans l’étape 2 “beta” , j’utilise des commandes Arduino de base dans une boucle for qui prend les pins ADC dans un tableau et renseigne les valeurs de postions actuelle dans le même tableau.

Oui quand le code sera 100% fonctionnel avec des ordres basiques et qu’il sera en 12 bits, j’envisage d’utiliser pour le stade inital de 2 moteurs, le code suivant déjà testé:
Je serais obligé de supprimer la colonnes Pin ADC du tableau ! …

//  int t=analogRead(0);
void setup() 
{
 ADC->ADC_MR |= 0x80; // Mode FREERUN
 ADC->ADC_CR=2; // Demarrage convertisseur
 ADC->ADC_CHER=0xC0; // Activation voies 6 et 7 (A0 et A1)
 Serial.begin(115200);
}

void loop() 
{
Serial.print("A0--> ");
 Serial.println(ADC->ADC_CDR[7]);    //AD7
 Serial.print("--> PIN2 <=> PWM E5--> ");
//Serial.print("     A1--> "); 
// Serial.println(ADC->ADC_CDR[6]);  //AD6
}

Sorties Digitales
J’envisage également d’utiliser la gestions des ports pour les commandes de sens de rotation
Là aussi , je devrais quitter la gestion par tableau des numéro de pins digitales

Ci dessous mon code d’essai les concernant:

 uint32_t pin_25 = (1u << 0);             // masque pour la pin 25 (Port Pin D0)
 uint32_t pin_45 = (1u << 18);             // masque pour la pin 45 (Port Pin C18)
 uint32_t pin_53 = (1u << 14);             // masque pour la pin 53 (Port Pin B14)
 uint32_t pin_35 = (1u << 3);             // masque pour la pin 35 (Port Pin C3)
 

void setup() 
{ 
 REG_PIOD_OER = pin_25;                   // pin 25 est configuré en output au niveau du port D
 REG_PIOC_OER = pin_35;                   // pin 35 est configuré en output au niveau du port C 
 REG_PIOC_OER = pin_45;                   // pin 45 est configuré en output au niveau du port C
 REG_PIOB_OER = pin_53;                   // pin 53 est configuré en output au niveau du port B
 
 REG_PIOD_CODR = pin_25;                 // Basculement pin 25 en OFF  (clear)
 REG_PIOC_CODR = pin_35;                 // Basculement pin 35 en OFF  (clear)
 REG_PIOC_CODR = pin_45;                 // Basculement pin 45 en OFF  (clear) 
 REG_PIOB_CODR = pin_53;                 // Basculement pin 53 en OFF  (clear) 
 
 /* États persistants des pins OutPut  commandant le sens de rotation */
//bool Rotation_Forward_M1 = LOW ;
 //bool Rotation_Reverse_M1 = LOW ;
 
Serial.begin(115200);
} 

void loop() 
{
//Changement état des pins 25 et 45 avec "Delay" 
//**********************************************
REG_PIOC_CODR = pin_45;                  // Basculement pin 45 en OFF  (clear)
         delayMicroseconds(1);          // wait for a 1ms
REG_PIOD_SODR = pin_25;                  // Basculement pin 25 en ON (set) 
         delayMicroseconds(1);          // wait for a 1ms
REG_PIOD_CODR = pin_25;                  // Basculement pin 25 en OFF  (clear)
        delayMicroseconds(1);            // wait for a 1ms
REG_PIOC_SODR = pin_45;                    // Basculement pin 45 en ON (set)
        delayMicroseconds(1);            // wait for a 1ms
}

PWM


“Mettre le PWM est rapide à exécuter (un analogWrite() ?)” : Oui

Au niveau des PWM 12 bits, je pense utiliser les PWM Timer des pins 4,5,11 et 12 et augmenter leur fréquences à 10kHz (fréquence maxi pour le 12bits)
J’ai déjà perdu une Due avec des PWM 12 bits à 40kHz, cela marche !, mais après quelques heures : la Due est OUT !!!
Pour l’instant je ne sais augmenter la fréquence que en modifiant le fichier variant.h
Je suis preneur d’un code commenté forçant la fréquence des pins 4,5,11 et 12 à la fréquence de 10kHz

" Donc le gros du boulot est plutôt le calcul du PID qui devra être bien fichu - avez vous chiffré le temps de calcul ? " Non
Pour cette zone “PID”, je pense que c’est un PID simplifié

Le code que j’adapte provient un code que Wanegain nous mets à la disposition. Il est inspirer d’un code initial de Sirnoname (X-Sim)
Le code que j’adapte avec Wanegain (il s’est proposé de m’aider depuis cet après_midi! a le modifier pour commander des variateurs), il est prévu et optimisé à l’origine pour un Arduino Micro et des Sabertooth 2 x 32 (simulateur avec des moto-réducteur DC)
Son aide se limitera à l’adaptation basique (non optimisé pour la Due) pour le pilotage d’un variateur de fréquence (1 PWM et 2 sorties digitales par moteur) et pour passer sont code pour lire une trame SimTools 12 bits + ADC 12 bits + Gestion PID 12 bits afin d’obtenir un PWM 12 bits à fréquence basique de 1khz (par défaut sur Due)

Merci de l’intérêt et des renseignements que vous m’apportez !

je recois une trame de consigne de positions à réaliser ayant une synthase : X1CX2C

donc c'est de la communication ASCII, pas binaire ?

Après le X j'ai le numéro du moteur (1 à 6) suivi de deux octets pour la valeur de consigne (sur 10 bits) puis le "checksum" C pour valider sinon la trame est rejetée

Donc est sur deux octets 'bruts' (le nombre en 10 bits étendu sur 2 octets) ? vous pouvez très bien recevoir un 'X' ou un 'C' qui seront des valeurs admissibles ce qui peut désynchroniser un peu votre décodeur au lancement. Quelle tolérance à la perte d'information initiale avez vous ?

(1 x 20 ) / 115200 = 0,0001736 = 0,17ms sauf erreur. la formule que j'ai posée est incorrecte ?

Oui, elle est incorrecte. les bauds ce sont des "bits par seconde", pas des "octets par seconde".

De plus vous avez potentiellement des des bits supplémentaires. On a pour habitude de prendre 10 bits transmis pour 1 octet pour simplifier les calculs. donc la formule c'est (10 x 20 ) / 115200 * 1000= 1,736 ms
(par défaut sur arduino 1 octet est transféré sous forme 8N1 => 8 data bits, pas de parité, 1 stop bit donc plutôt 9 que 10)

Je n'arrive pas à comprendre votre résonnement ! Pouvez-vous me l'expliquer autrement ?
"Si vous réglez la période d'émission à 2ms", il s'agit donc de la trame de consigne émise sur le port COM Programming par SimTools !
Donc "période d'émission à 2ms" doit être supérieur de 10% par rapport à la somme des temps d'exécution des étapes 1 à 5 ?(voir post 11)

Oui j'ai dit des bêtises. il faut que:

  • la période d'émission soit supérieure au temps nécessaire pour l'émission physique.
  • le temps de traitement soit inférieur au temps de traitement + la réception des octets

Donc à 115200 bauds on met (en arrondissant) 1,8ms pour envoyer 20 bits. Avec votre granularité à la ms pour la période d'émission ça veut dire que au minimum vous devez régler à 2ms cette période.

Le port série matériel fonctionne par interruption et un bout de code (_rx_complete_irq()) est appelé à chaque fois qu'une octet complet a été reçu mais pas pour chaque bit c'est traité en hardware. Cet octet est mis dans un buffer côté arduino, ça prend un petit peu de temps (20 x quelques microsecondes).

On ne peut donc pas se permettre d'avoir les phase 1 à 5 qui mangent ces 2 ms, il faut aller plus vite. En première estimation c'est là que je prends "10% de gras" et donc si vous traitez les phase 1 à 5 en 1.8ms et allouez 200µs pour recevoir les octets (10µs par interruption, @84MHz ça laisse le temps pour 840 instructions de base du micro processeur) vous tenez la cadence, l'Arduino est dispo pour traiter la prochaine trame


c'est clairement une mesure au doigt mouillé, faudra tester dans la vraie vie si quand l'Arduino a vraiment fini ses calculs les 20 octets sont directement déjà disponibles ou pas. Idéalement il ne faudrait pas.

je cherche à terminer l'adaptation du code de Wanegain

j'ai aucune idée de ce dont vous parlez... un lien sur le code ?

Là aussi , je devrais quitter la gestion par tableau des numéro de pins digitales

faudra passer par les registres si vous voulez de la perf.

Je suis preneur d'un code commenté forçant la fréquence des pins 4,5,11 et 12 à la fréquence de 10kHz

Comme je vous l'ai dit je n'ai pas de DUE, donc je n'ai jamais été amené à faire cela (il y a des discussions sur le sujet, je suppose que vous avez déjà lu cela)

Avant de chercher à tout optimisez regardez où le temps sera passé. A mon avis le PID sera coûteux donc après l'avoir optimisé, regardez le temps qu'il reste et ça guidera les optimisations nécessaire pour le reste du code des phase 1 à 5 - et si c'est pas possible dans ce cas à une augmentation de la période d'émission.

Bonjour

je recois une trame de consigne de positions à réaliser ayant une synthase : X1CX2C
donc c’est de la communication ASCII, pas binaire ?"

Non c’est du binaire ,et tu as bien compris, Simtools remplace seulement Axis1a … par 2 octects qui définissent la consigne à atteindre avant d’envoyer la trame sur le port COM
Voir la pièce jointe faite avec Serial Port Monitor démo 14jours et voir la pièce jointe copie d’écran de SimTools / Interface

vous pouvez très bien recevoir un ‘X’ ou un ‘C’ qui seront des valeurs admissibles ce qui peut désynchroniser un peu votre décodeur au lancement. Quelle tolérance à la perte d’information initiale avez vous ?

Voici la question piège !.. j’ai aucune idée !..

De plus vous avez potentiellement des des bits supplémentaires. On a pour habitude de prendre 10 bits transmis pour 1 octet pour simplifier les calculs. donc la formule c’est (10 x 20 ) / 115200 * 1000= 1,736 ms (par défaut sur arduino 1 octet est transféré sous forme 8N1 => 8 data bits, pas de parité, 1 stop bit donc plutôt 9 que 10)

Encore une confusion de ma part !.. A ces novices !.. C’est sous la forme 8N1
Voir la pièce jointe copie d’écran de SimTools / Interface

je cherche à terminer l’adaptation du code de Wanegain
j’ai aucune idée de ce dont vous parlez… un lien sur le code ?

Afin d’être correct par rapport au travaille fourni par Wanegain, je ne m’autorise pas de vous fournir le code directement
Pour l’obtenir il faut aller sur le forum , s’incrire et dire “Merci” sur un post
https://pcshm-simulateurs-homemade.clicforum.com/t420-Profils-Converter-et-codes-pour-Arduino.htm
et … Les liens apparaitront sur le post 1 (Avant le post 1 est partiellement masqué)

**ADC et digitales **

il faudra passer par les registres si vous voulez de la perf

Avant d’abandonner le scruture du code utilisant des bouclees for… qui effectue les opérations de chaque moteur à chaque tour de la boucle
Ces boucles for… sont indissociables de l’utilisations des tableaux pour les ADC et digitales par les registres
ADC : Peut-on envisager d’intégrer dans un tableau " un peu spécial " des données du style ADC->ADC_CDR[7] ?
Digitales: Peut-on envisager d’intégrer dans un tableau des données du style REG_PIOC_CODR = pin_45 ?
Quelle type de tableau pourrais-je utiliser pour les ADC et digitales?

Je suis preneur d’un code commenté forçant la fréquence des pins 4,5,11 et 12 à la fréquence de 10kHz
Comme je vous l’ai dit je n’ai pas de DUE, donc je n’ai jamais été amené à faire cela (il y a des discussions sur le sujet, je suppose que vous avez déjà lu cela)

Oui , j’ai vu et participé à ce post et et on m’a gentillement dit :
“Vous êtes trop loin du niveau requis pour mener à bien un tel projet.”

Merci encore de votre aide pour avancer dans le projet, certes quelque peu au delà de mon niveau, mais c’est intéressant d’avancer pas à pas !..

Bonjour,

j'ai vu un article qui semble intéressant pour éclaircir un code

Qu'en pensez-vous ?

A-t-il un intérêt pour des petits codes déportés ?

Lors de la compilation , cela pénalise le temps d’exécution ?

Merci de votre retour d'expérience

vos images:


j'ai vu un article qui semble intéressant pour éclaircir un code

C’est pour faciliter la lecture et la maintenance du code. Ça ne change rien aux perfs au final tout est mis ensemble et compilé

Concernant les lectures ADC vous n’avez pas le choix (si vous ne voulez pas rajouter du hardware) il faudra passer par une boucle car il n’y a qu’un seul ADC physiquement sur le carte qui est dynamiquement configuré (multiplexeur) pour aller mesurer une broche particulière. En prenant des ADC externes vous pourriez paralléliser la phase d'échantillonnage / conversion et lire cela directement en numérique (genre ADS1015 en 12 bits ou ADS1115 en 16 bits, on peut le lire en I2C et certains modules ont la possibilité de choisir l'adresse parmi 4 possibles, donc vous pourriez en avoir un par motoréducteur).

Afin d'être correct par rapport au travaille fourni par Wanegain, je ne m'autorise pas de vous fournir le code directement
Pour l'obtenir il faut aller sur le forum , s'incrire et dire "Merci" sur un post

:o :o et deux génuflexions ? Drôle de conception du partage et gros ego..., mais chacun faut comme il veut mais Je n’irai certainement pas faire des courbettes... cela dit vous avez tout à fait raison de ne pas partager son code, faut respecter les attentes de l’auteur et le contrat moral.

Oui , j'ai vu et participé à ce post et et on m'a gentillement dit :
"Vous êtes trop loin du niveau requis pour mener à bien un tel projet."

Je pense que plutôt il a dit qu'il n'avait pas le temps de vous prendre par la main pour résoudre votre projet car vous n'étiez pas assez autonome et qu'il aurait dû faire tout le boulot (et il n'avait pas le besoin).
Pour le Pwm, avez vous exploré des composants externes genre PCA9685 ?


C'est parfois plus simple que de triturer les entrailles des registres avec parfois des conséquences sur certains pins ou timers que l'on maîtrise mal.