Bonjour,
J'ai un signal extérieur qui me génère une interruption Int0.
Je souhaite alors attendre un certain délai (entre 0 et 3millisecondes) avant de changer l'état d'une sortie digitale.
J'imagine qu'il n'est pas conseillé d'utiliser delayMicroseconds() dans l'interruption, donc que me conseillez-vous?
Peut-être démarrer un timer depuis l'interruption et stopper le timer une fois sa première interruption déclenchée? Mais je ne suis pas certain de comment démarrer ce timer depuis Int0
void loop()
{
if (activerSortie) { // si l'ISR a été déclenchée
noInterrupts();
uint32_t copie_t0 = t0; // pour éviter toute modification intempestive on travaille sur une copie capturée en section critique
interrupts();
if (micros() - copie_t0 >= 3000ul) { // déclenche la sortie 3ms après l'interruption
digitalWrite(pinSortie, HIGH);
activerSortie = false;
}
}
... // ici le code normal
}
Bien sûr cela va fonctionner correctement que si votre loop tourne rapidement car il faut vérifier le drapeau activerSortie au moins toutes les millisecondes si vous voulez tenir les 3ms.
Sinon il faut effectivement gérer cela par un timer que vous armez dans l'interruption. Vous pouvez utiliser des bibliothèques comme TimerOne par exemple pour vous simplifier la vie.
Sinon il existe aussi des composants dit "Ligne de Retard" qui permettent d'insérer un décalage très précis sur le trajet d'un signal... comme ça pas besoin de traiter le problème avec un Arduino, vous retardez le signal qui déclenchait l'ISR du temps souhaité et vous activez la pin directement dans l'ISR. Par exemple voilà le premier trouvé sur une recherche internet (je ne dis pas que c'est celui qui convient, juste un exemple) LTC 6994 -> vous pouvez le configurer de 1μs à 33.6 secondes.
Si c'était moi, je n’embêterai moins. Si les interruptions de l'extérieur arrivent à une cadence plus faible que 4 millisecondes, et qu'on est sûr de ne pas avoir d'interruption par la voie extérieure, je ne me gênerais pas pour utiliser un delai de 3ms dans la fonction d'interruption.
Maintenant deux cas
soit on a besoin de garder l'heure système, et il faut mettre une fonction setInterrupt() interrupt() dans l'interruption extérieure. Si on n'est pas sûr qu'il y ait une nouvelle interruption extérieure, il faut alors désactiver l'interruption extérieure
soit on n'a pas besoin de l'heure, et on ne fait rien, on suspend la remise à l'heure, et on attend tranquillement les 3ms
Bonsoir et merci bien pour la réponse détaillée. J'aurais du détailler que je cherche une précision en deça de la milliseconde et que la loop contient de la COM série et d'autres choses, donc je ne parierais pas sur cette solution.
Je vais regarder/tester la librairie TimerOne
Pour les composants externes, c'est intérressant mais je souhaite pouvoir le régler via une variable en cours d'exécution, donc pas une option
vileroi:
Si c'était moi, je n’embêterai moins. Si les interruptions de l'extérieur arrivent à une cadence plus faible que 4 millisecondes, et qu'on est sûr de ne pas avoir d'interruption par la voie extérieure, je ne me gênerais pas pour utiliser un delai de 3ms dans la fonction d'interruption.
Maintenant deux cas
soit on a besoin de garder l'heure système, et il faut mettre une fonction setInterrupt() dans l'interruption extérieure. Si on n'est pas sûr qu'il y ait une nouvelle interruption extérieure, il faut alors désactiver l'interruption extérieure
soit on n'a pas besoin de l'heure, et on ne fait rien, on suspend la remise à l'heure, et on attend tranquillement les 3ms
Merci bien. Effectivement les interruptions sont prévisibles et arrivent moins souvent que 3ms et on n'a pas besoin de l'heure système. Je vais également essayer cette solution
Si on a besoin de la com, il vaut mieux dans ce cas réactiver les interruptions.
Si on réactive les interruptions pendant le traitement de l'une d'elle, cela permet aux autres de fonctionner. Le problème c'est uniquement que la fonction ne doit pas s'interrompre elle même pour ne pas déborder.
Et encore, je vais bientôt continuer une bibliothèque ou une interruption appelée par un timer toutes les 20ms peut durer plus de 3s. Elle s'interrompt elle même mais un test en début finit la deuxième fonction d’interruption si une autre instance est en train de s'exécuter. Et pendant ces 3 secondes, je compte continuer à remettre l'horloge à l'heure et faire avancer un pas à pas.
Ce genre d'interruption qui réautorise les autres interruptions, c'est comme une fonction mais qui est appelée par un évènement extérieur.
Il me semble avoir travaillé avec un micro qui désactivait les interruptions moins prioritaires lors d l'appel , et qui donc laissait les inter plus prioritaires fonctionner. C'est un peu le même principe que j'applique.
Hmm, ok ça dépasse mon niveau de compétences.
Pour la COM, elle est initiée par le micro contrôleur, donc prévisible.
J'ai codé avec le délai dans l'interruption, ça a l'air de fonctionner sur ma board de test mais je vais essayer en situation réelle et je ferai un retour
Merci
Si tu n'est pas réinterrompu rajoute simplement
interrupts();
en début de ta fonction d'interruption pour ne pas gêner les autres interruptions. Ainsi tu ne perdra pas de caractères venant de COM.
Si comme tu ne le précises pas alors que c'est demandé dans "Règles du forum francophone" tu utilises une carte avec un microcontroleur avr (Uno, nano, pro-mini,mega,leonardo,micro) il existe l'équivalent des fonctions de delai dans l'avr libC de la société Atmel concepteur de ces microcontroleurs.
Ces fonctions, écrites par Atmel et non pas arduino, n'utilisent pas les intéruptions.
Elles sont basées sur la connaissance qu'a le concepteur du microcontroleur des possiblités de son produit.
Elles existent depuis plus longtemps que les fonctions wiring/arduino mais elles ne sont valables que pour l'architecture Atmel avr.
68tjs:
Si comme tu ne le précises pas alors que c'est demandé dans "Règles du forum francophone" tu utilises une carte avec un microcontroleur avr (Uno, nano, pro-mini,mega,leonardo,micro) il existe l'équivalent des fonctions de delai dans l'avr libC de la société Atmel concepteur de ces microcontroleurs.
Ces fonctions, écrites par Atmel et non pas arduino, n'utilisent pas les intéruptions.
Elles sont basées sur la connaissance qu'a le concepteur du microcontroleur des possiblités de son produit.
Elles existent depuis plus longtemps que les fonctions wiring/arduino mais elles ne sont valables que pour l'architecture Atmel avr.
Bonjour et merci.
Je n'ai pas précisé la carte utilisée car je n'ai pas arrêté mon choix. Pour l'instant je fais des tests sur un Arduino Mega 2560 et sur un Arduino Ethernet. L'avantage d'Arduino (pour les débutants comme moi tout du moins) est d'offrir une certaine abstraction du hardware et c'est la raison pour laquelle je regarde d'abord si je trouve une solution à ce niveau avant d'aller plus bas.
Merci pour le tuyau sur l'avr libC, j'irai voir si ma solution actuelle ne fonctionne pas
Bonne journée
L'avantage d'Arduino (pour les débutants comme moi tout du moins) est d'offrir une certaine abstraction du hardware
C'est l'avantage du "framework", as they say, mais cela n'est pas lié au côté matériel.
Le "framework", ou bibliothèque de fonctions, a primitivement été écrit pour un microcontrôleur architecture avr du fabricant Atmel par le projet Wiring puis il a été porté sur d'autres microcontrôleurs par le projet Arduino.
Actuellement ces bibliothèques de fonctions ont été portées sur des architectures ARM que ce soit pour des micros Atmel (cartes Arduino DUE et série MKR) ou STmicro (gamme STM32) plus quelques autres micro moins fréquents comme les tensy. Il faut ajouter des micros non ARM comme Espressif (Esp 8266, Esp 32) et STM8 (micro 8 bits).
Le code des fonctions est adapté à chaque microcontrôleur, il faut donc charger la version qui va bien mais du point de vue de l'utilisateur c'est entièrement transparent car les noms et les fonctionnalités sont les mêmes.
Le portage a selon les cas été réalisé par Arduino, par les fabricants de micro (STmicro, Espessif) ou par des initiatives individuelles.
Conclusion : le choix est vaste dans les cartes pouvant se programmer "à la mode arduino" à partir de l'EDI Arduino.