Go Down

Topic: RAZ du timer (µs) sur int (Read 3926 times) previous topic - next topic

Artouste

bonsoir à tous
ça fait un peu suite à mes verifs de dispersions d'horloge (selon "qualité" )  :smiley-mr-green:

petit appel aux excellents codeurs (et comme je sais qu'il y en a ici  :smiley-mr-green: )


quel serait le code le plus simple/concis (sous l'IDE arduino) pour (re)mettre à 0  le timer sur reception (ou sortie) d'interruption ?

pour faire plus simple : quelle est la meilleure methode soft pour que la RAZ soit la plus synchro entre les differentes cibles ?

ça vaut aussi pour la lecture  :smiley-mr-green:

skywodd

Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

Artouste

#2
Feb 04, 2014, 02:24 pm Last Edit: Feb 04, 2014, 02:32 pm by Artouste Reason: 1

Salut,

J'ai pas tout compris :smiley-sweat:

ça ne m'etonne pas  :smiley-mr-green:
j'avoue ne pas avoir été tres limpide  8)

je repose :

X arduino (uno pour la demo) qui vivent leur vie avec un programme "identique" et chacun ayant sa propre BdT,
inevitablement il y aura de la dispersion temporelle sur la longueur de temps = le micros() millis() de l'un n'aura jamais la meme durée .

je cherche "simplement" à remettre periodiquement à zero sur un "top" commun (interruption)  le compteur micros() millis() renvoyé par chaque MCU, les dispersions intrinseques existeront toujours, mais ramené sur la durée entre 2 tops de RAZ , l'erreur due aux dispersions devrait etre acceptable.


je ne veux pas (ne souhaite pas) faire du calcul de difference sur micros() millis()

pratiquement je cherche sur interruptions materielles à faire une RAZ  commune sur INT N°1  de toutes les unités et qu'ensuite chaque unité fasse un log du compteur (temps) sur INT N°2.

la premiere question , déjà , c'est est ce que c'est possible ?

pour resumer le vrai besoin : quelle est la meilleure methode soft pour faire une RAZ du compteurs temps la plus synchrone possible de tous les MCU avec un stimuli unique ...

Je ne suis pas sur d'avoir été bien plus clair... :smiley-mr-green:

68tjs

Quand j'ai vu ça :
Quote
petit appel aux excellents codeurs (et comme je sais qu'il y en a ici )

Je me suis dit que je n'étais pas concerné.

Vu l'affluence de réponse je tente ma chance :
Est-ce qu'une raz des préscalers pourrait faire l'affaire ?
NB sur un 328p il y a 2 préscalers 1 commun aux timer0 (8bits)  et timer1(16 bits) et le 2eme pour le timer 2.

Sinon quitte à dire des bêtises autant y aller : quid d'une synchronisation par les entrées T0, T1 et T2 ?

Artouste


Quand j'ai vu ça :
Quote
petit appel aux excellents codeurs (et comme je sais qu'il y en a ici )

Je me suis dit que je n'étais pas concerné.

Vu l'affluence de réponse je tente ma chance :
Est-ce qu'une raz des préscalers pourrait faire l'affaire ?
NB sur un 328p il y a 2 préscalers 1 commun aux timer0 (8bits)  et timer1(16 bits) et le 2eme pour le timer 2.

Sinon quitte à dire des bêtises autant y aller : quid d'une synchronisation par les entrées T0, T1 et T2 ?


bonjour 68tjs

là je suis en mode reflexion
et ça n'a aucun caractere d'urgence  :smiley-mr-green:
tripoter un prescaler est peut etre une bonne solution

de toutes façons , le compteur soft micros() est bien à un moment ou un autre initialisé à zero


haifger


je ne veux pas (ne souhaite pas) faire du calcul de difference sur micros() millis()

C'est bien dommage parce c'est de loin la plus simple et la moins «dangereuse»...

Il faut bien avoir conscience qu'un nombre non négligeable de librairies Arduino utilisent millis() en interne et que remettre le compteur à zéro brutalement peut occasionner des comportements assez étranges :smiley-mr-green: D'un autre côté, si tes MCU ne font que «tourner en rond» en regardant le temps passer, ceci devrait faire l'affaire :
Code: [Select]

extern volatile unsigned long timer0_millis;

void reset_millis(void){
  uint8_t old_sreg = SREG;
  cli();
  timer0_millis = 0;
  SREG = old_sreg;
}

La première ligne te donne accès à la variable qui stocke millis dans le core Arduino.

Je suppose également que tu voudra appeler la fonction de reset dans une interruption, auquel cas tu peux te passer des lignes concernant SREG/cli().

haifger

Euh oui, j'ai oublié, remettre à zéro le prescaler hardware et la valeur du Timer0 également...

Artouste



je ne veux pas (ne souhaite pas) faire du calcul de difference sur micros() millis()

C'est bien dommage parce c'est de loin la plus simple et la moins «dangereuse»...


Merci haifger
je regarde ton code + tard
J'en suis bien conscient  8)
mais là (au moins à ce stade dans mon esprit)
j'utiliserais une librairie "time dependante" seulement apres avoir fais de l'acquisition par chaque module

je resume ma vision :
- top synchro "RAZ des modules" 
- top acquisition differencié par module = lecture/sauvegarde du  "temps brut rendu"
- ensuite "et là on est moins pressé"  :smiley-mr-green:
- restitution par vecteur de comm (typiquement pour test le bon vieux serial "time dependant" )  de la/les valeurs prealablement acquises

haifger

Ce que je ne comprends pas c'est pourquoi tu veux absolument remettre millis à zéro. Tu pourrait faire :
- top synchro : enregistrement de la valeur actuelle de millis : millis_prev (chaque MCU a la sienne)
- top acquisition : revoi la valeur de (millis - millis_prev)
De ce que je comprends, le résultat est le même tout en t'évitant de mettre tes mains toutes propres dans le cambouis...

Artouste

#9
Feb 04, 2014, 03:30 pm Last Edit: Feb 04, 2014, 03:35 pm by Artouste Reason: 1

Ce que je ne comprends pas c'est pourquoi tu veux absolument remettre millis à zéro. Tu pourrait faire :
- top synchro : enregistrement de la valeur actuelle de millis : millis_prev (chaque MCU a la sienne)
- top acquisition : revoi la valeur de (millis - millis_prev)
De ce que je comprends, le résultat est le même tout en t'évitant de mettre tes mains toutes propres dans le cambouis...

comme déjà expliqué , et  ce n'est encore qu'une simple reflexion
previous millis ou micros - millis ou micros "consomme du temps de calcul"  qui est lui aussi dependant de l'horloge du MCU et est donc affecté par son erreur propre .
tu me repondras que la dispersion reste identique , mais son influence est multipliée le nombre de cycles

haifger

En fait je crois que je ne comprends pas :smiley-mr-green:
Dans mon esprit l'acquisition consiste à acquérir millis(). Qu'ensuite tu doives calculer la différence avec millis_prev ou pas, c'est du temps de restitution, ça ne doit pas générer d'erreur supplémentaire.

Artouste


En fait je crois que je ne comprends pas :smiley-mr-green:
Dans mon esprit l'acquisition consiste à acquérir millis(). Qu'ensuite tu doives calculer la différence avec millis_prev ou pas, c'est du temps de restitution, ça ne doit pas générer d'erreur supplémentaire.


A ce stade c'est vraiment purement intellectuel
mais (et je me plante peut etre)

je fais une difference de deviation temporelle  finale relative (peut etre parfaitement inutile)
entre  un arduino (ou autre MCU  ) et un autre,  pour exemple exagéré (encore que)

- le 1er cadencé à 15.950 MHz
- le 2eme cadencé à 16.150 MHz

ça ne va pas les perturber pour executer du code "tout venant"

mais plus tu a d'instructions dans un meme programme injecté sur plusieurs cible identique, plus cet ecart relatif d'horloge de 200 KHz est perceptible sur la duréee.

faire une soustraction consomme du temps de calcul (cycles/unités d'horloge)
ne pas en faire n'en consomme pas (là je suis presque sur que j'ai bon  :smiley-mr-green:  )

dans mon esprit : moins tu pollue le resultat avec du calcul intermediaire (meme si une soustraction "ça va vite"  :smiley-mr-green:  )
moins tu "amplifie" la deviation relative temporelle entre MCUs.









haifger

En fait je ne suis pas certains de comprendre ce que tu essaie de faire :smiley-mr-green: Est-ce juste un test pour mesurer/calibrer/... des cartes différentes, ou bien un système "en production" que doit périodiquement se resynchroniser de cette façon ?

Si je reprends ton idée précedente :

je resume ma vision :
- top synchro "RAZ des modules" 
- top acquisition differencié par module = lecture/sauvegarde du  "temps brut rendu"
- ensuite "et là on est moins pressé"  :smiley-mr-green:
- restitution par vecteur de comm (typiquement pour test le bon vieux serial "time dependant" )  de la/les valeurs prealablement acquises

La soustraction tu la fait au point 4, du coup, peut importe le nombre de cycles qu'il lui faut, elle n'influence pas la mesure.

D'un autre côté, si vraiment tu veux de la précision et que tu es à la chasse au cycle près, utiliser les librairies Arduino n'est sans doute pas la meilleure solution. Tu devrais plutôt te contenter d'utiliser directement les timers, la résolution sera bien meilleure.

fdufnews

millis avance sous interruption; Ce que tu fais à coté ne change pas l'avance de millis.

Artouste

bonjour
merci à tous pour vos reponses
je vais continuer à reflechir là dessus


Go Up