Par quoi remplacer la fonction delayMicroseconds() ?

Slt tout le monde,

comme dit dans le topic, je cherche un moyen de remplacer la fonction "delayMicroseconds()" dans une fonction que j'écris.

En faite j'utilise un timer (N°3) de mon arduino mega pour réaliser une fonction périodique :

ISR(TIMER3_COMPA_vect)          // interrupt fonction
{
  TIMSK5 |= (0 << ICIE5);
  DDRB = (1 << DDB4); //Pin 10 en mode OUTPUT
  PORTB = (0 << PORTB4); // Pin 10 à 0
  delayMicroseconds(9); // temps a l'état bas du trigger
  PORTB = (1 << PORTB4); // Pin 10 à 1

  // PASSEAGE EN INPUT POUR LIRE LA REPONSE DU CAPTEUR
  DDRB = ( 0 << DDB4); // Pin 10 en entrée et attente de la réponse capteur
  TIMSK5 |= (1 << ICIE5);//enable Input Capture interrupt
}

Cette fonction inter-agit avec un autre timer ( N°5) et met un pin a 0 pendant 9µs.

le problème est que plus tard dans mon programme j'utilise un DAC, et quand j'observe la sortie de mon convertisseur, elle est impacter par le "delayMicroseconds()"; la sortie passe à zero, ce qui fausse le résultat de la conversion.

donc voila: Par quoi/comment remplacer la fonction delayMicroseconds() ?

Bonjour,

Je ne sais pas si c'est ça ton problème, mais au lieu d'agir sur un seul bit du port B, tu agis sur tous les bits.
par exemple
PORTB = (0 << PORTB4); // Pin 10 à 0 met tout le port à 0

Le programme correct serait:

ISR(TIMER3_COMPA_vect)          // interrupt fonction
{
  TIMSK5 &= ~(1 << ICIE5);
  DDRB |= (1 << DDB4); //Pin 10 en mode OUTPUT
  PORTB &= ~(1 << PORTB4); // Pin 10 à 0
  delayMicroseconds(9); // temps a l'état bas du trigger
  PORTB |= (1 << PORTB4); // Pin 10 à 1

  // PASSEAGE EN INPUT POUR LIRE LA REPONSE DU CAPTEUR
  DDRB &= ~(1 << DDB4); // Pin 10 en entrée et attente de la réponse capteur
  TIMSK5 |= (1 << ICIE5);//enable Input Capture interrupt
}

je comprends pas tres bien ? quelle est différence entre c'est deux lignes ?
PORTB = (0 << PORTB4); // Pin 10 à 0

PORTB &= ~(1 << PORTB4); // Pin 10 à 0

et Pourquoi agir sur tout le port alors que j'ai besoin que d'un seul PIN ?

Ausmoz1:
je comprends pas tres bien ? quelle est différence entre c'est deux lignes ?

Dans le premier cas tu met tout le port à 0 (0<<PORTB4) vaut 0

Dans le deuxième cas tu mets le bit 4 à 0 uniquement.

Ausmoz1:
et Pourquoi agir sur tout le port alors que j'ai besoin que d'un seul PIN ?

Car le processeur lit ou écrit un octet entier. Il faut donc faire un 'ou' ou un 'et' avec la valeur précédente du port pour modifier un seul bit.

Merci, tu m'en apprends bcp !! mais à quoi sert précisément le "~" ( tild) ?
je peux t'envoyer mon code en MP pour que t'y jette un oeil ?

C'est un NOT binaire.
Par exemple
(1<<PORTB4) donne 00010000
~(1<<PORTB4) donne 11101111

Dans arduino, il existe des macros bitSet() et bitClear() qu'on peut utiliser au lieu de manipuler les bits explicitement.

  bitSet(PORTB,PORTB4);
  bitClear(PORTB,PORTB4);

Postes ton code ici.

c'est un plaisir d'apprendre. en faite t'avais raison, en modifiant le fonction d'interruption mon convertisseur fonction correctement.
:slight_smile: :slight_smile:

Content pour toi! :slight_smile:

Ne jamais oublier quand on travaille avec des circuits intégrés externes le temps d’exécution peut jouer fortement. L'utilisation de macros et fonctions Arduino n'est pas forcement optimisée.

Par exemple l'execution d'un DigitalRead ou DigitalWrite dure 5.5µs sur un Mega, l'instruction Port que 0.35µs.

La fonction delayMicrosecond(1) exécute un retard effectif de 2µs, delayMicrosecond(2) de 2.7µs, pour des valeurs plus longues on retombe sur nos pattes la séquence d’initialisation de la commande (interruption) devenant moins prépondérante : delayMicrosecond(50)=50.5µs reel.

Pour créer de tres courts retards réguliers il faut bien sur désactiver les interruptions générales pour ne pas etre embêté ce qui rend inoperand les fonctions de temporisation delay. Et comme il n'y a pas de fonction nop en direct, il est possible d'utiliser une ou une suite de fonctions simple a usage bidon comme un Var1&Var2

sur un Mega, l'instruction Port que 0.35µs.

Il me semble que L'instruction elle même (un out en assembleur) sur un MEGA prend 1 cycle Soit 0.0625 µs

Ce qui consomme du temps c'est le calcul du masque. Donc la durée dépend plus de cela, s'il est contant ou que vous savez qu'il faut inverser une pin particulière alors on peut faire plus rapide que 5 ou 6 cycles d'horloge, si le calcul du masque doit être dynamique alors ça peut prendre bien plus longtemps - tout dépend ce que vous mesurez

(Et 0.35µs ce n'est pas un nombre entier de cycles, comment vous trouvez cette valeur?)

Et 0.35µs ce n'est pas un nombre entier de cycles, comment vous trouvez cette valeur?

Parce-que 0.35 c'est plus simple que 0.3125 ou 0.375 ;>)

De plus analyse statistique car les interruptions non désactivées par défaut prennent de la ressource. Comme évoqué plus haut si l'on veut travailler avec des valeurs exactes au cycle d'horloge près il faut désactiver tout process annexe et bosser en assembleur. A mon époque on calculait les cycles d'horloge a la main et l'on compensait éventuellement les differences si il y avait des branchements en rajoutant des instructions, je suppose que maintenant il y des outils qui font cela automatiquement.

Désolé mais je débute en Arduino et mes vieux souvenirs polluent la réflexion, le compilateur C me laisse parfois rêveur, je viens de m’apercevoir sur un essai de petit projet en cours que pour un quarantaine de variables int8 utilisées(dont un tableau de 32) le compilateur consommait 231 octets la difference étant mangée par les fonctions utilisées.

pas de soucis of course, le 0.35µs c'était juste de la curiosité :slight_smile:

je viens de m'apercevoir sur un essai de petit projet en cours que pour un quarantaine de variables int8 utilisées(dont un tableau de 32) le compilateur consommait 231 octets la difference étant mangée par les fonctions utilisées.

vous utilisez des librairies peut-être?