Mesure de la largeur d'une impulsion issue d'une voie d'un RC

Bonjour

Quelqu'un a t'il un bout de code pour un PIC pour mesurer la valeur de l'impulsion issu d'une voie (récepteur de radiocommande) afin de réaliser un asservissement perso. Je vois un peu comment faire (sur interruption, mesure à l'aide du timer de la largeur de l'impulsion ; je sais qu'il faut autoriser les interruptions et peut être utiliser le prescaler ; je suppose qu'il faut voir du coté des registres Intcon et Option_reg) , mais je n'arrive pas à traduire ça en code. (je suis débutant total dans les pics)

De préférence en C (pas d'ASM) ; ça serait pour un 16F628 et juste le code pour mesurer cette impulsion, le reste, je m'en débrouille.

Merci.

Reply to
HITS
Loading thread data ...

"HITS" a écrit dans le message de news:

4a243f0a$0$17749$ snipped-for-privacy@news.orange.fr...

======== /* principe fonction pour mesure impulsion basse */ byte pulse_low() { // fonction retournant une valeur while(input(IRin)); // boucle d'attente tant que niveau haut set_rtcc(0); // debut niveau bas, compteur à zero delay_us(3); while(!input(IRin)); // boucle d'attente tant que niveau bas return(get_rtcc()); // fin niveau bas return resultat du comptage } L'armemnt du timer0 (RTCC) depend du type du compilateur , voir ta notice Bonne nuit

Reply to
maioré

"HITS" a écrit dans le message de news:

4a243f0a$0$17749$ snipped-for-privacy@news.orange.fr...

en C on utilise le mot cle "interrupt" ce mot cle genere un rti au lieu d'un rts, et il ne sert qu'a cela. ne pas oublier de declarer les variables utilisees pour le traitement (fin d'interruption, par ex, ou it traitee) en tant que "volatile" ceci oblige le soft qui tourne (en dehors du traitement de l'it) de relire cette variable. le traitement de l'it doit etre le plus court possible, l'idee serait donc de mettre une variable globale a 0 sur un front montant de l'it, de lancer un timer, et une autre it sur le front descendant, qui lit la valeur du timer, a voir suivant le pic, et le compilateur utilise.

Reply to
jlp

Il faudrait connaitre l'ordre de gandeur de la duree de cette impulsion : plutot de l'ordre de la microseconde, de la milliseconde, ou au-dela ? Quand au code, ca depend du compilateur C que tu utilises, c'est lequel ? Certains compilateurs ont des macros qui rendent l'init des interruptions tres facile a ecrire, mais qui cachent les details d'initialisation des registres, et ce code n'est pas portable d'un compilo a l'autre et pas bon pour apprendre.

Je ne connais pas le 16F628 mais le principe reste le meme pour les uC. Tu valides l'interruption d'overflow d'un timer ininterruptible, dans cette interruption tu incrementes juste une variable qui indiquera le nombre d'overflows eventuels que le timer a fait. Le prediviseur de ce timer est a choisir en fonction de la duree de l'impulsion que tu vas mesurer : plus l'impulsion sera courte, plus le diviseur sera petit pour garder un increment faible, et inversement.

Tu valides une interruption qui se declenche lors d'un changement d'etat sur l'entree du PIC qui recoit l'impulsion : quand cette impulsion se declenche sur le front montant, tu mets a zero le compteur du timer ainsi que la variable associee.

Lors de la seconde interruption (front descendant) tu lis la valeur du timer (et de la variable) qui te donnent la duree de l'impulsion avec une precision de l'ordre de celle de ton quartz multipliee par les pre-diviseurs.

Le code pour la mesure (a traduire pour ton PIC) avec un timer 16 bits :

//-------------------------------------------------------

// definition de l'entree qui recoit le signal #define ENTREE BIT_RB0 // exemple avec RB zero

// constantes #define FQUARTZ 20000000 // frequence du quartz (ex: 20 MHz) #define DIVISEUR 16 // pre-diviseur du timer (exemple)

// variables globales unsigned long uTimer=0, uOverflow=0; // compteurs timer float fValeur = 0.0; // valeur du timer unsigned char flag=0; // flag de fin de mesure

// interruption du timer --------------------------------- void interrupt timer(void) { ++uOverflow; // increment du compteur d'overflows }

// interruption de changement d'etat --------------------- void interrupt change(void) { // etat logique de l'entree a cet instant if ( ENTREE ) // front montant { TIMER = 0; // reset du compteur du timer start_timer(); // demarrage de l'interruption du timer } else // front descendant { uTimer = TIMER; // lecture de la valeur actuelle du timer stop_timer(0); // arret de l'interruption du timer flag = 1; // mesure terminee } }

// programme de fond -----------------------------------

void main(void) {

// inits preset_timer(DIVISEUR); // initialise les pre-diviseurs du timer

while ( 1 ) // boucle principale { // inits uTimer = uOverflow = 0; // remise a zero des compteurs flag = 0; // reset du flag de fin de mesure

// mesure while( ENTREE ) ; // attend la fin de l'etat "un" sur l'entree start_change(); // demarrage de l'interruption de changement d'etat while( !flag ) ; // attend la fin de la mesure stop_change(); // arret de l'interruption de changement d'etat

// affichage fValeur = (float)uTimer + (float)uOverflow * 65536.0; // valeur de comptage fValeur *= (DIVISEUR / FQUARTZ); // conversion en secondes (ou ms, ou us) print( "%f\n", fValeur ); // affichage de la valeur delay( ? ); // attente eventuelle pour l'affichage }

}
Reply to
Jean-Christophe

Réponse à tous.

D'abord merci d'avoir répondu.

Le PIC utilisé est un 16F628A (j'ai aussi un 16F877A) J'utilise MikroC pour compiler (ai-je fais le bon choix ???) J'ai sous la main la doc MikroC et les datasheets des composants cités. La valeur à mesurer est comprise entre 0,8 ms et 2,2 ms. Fréquence OSC = 4Mhz Donc avec un timer sur 8 bits, il me faut utilser le préscaler (/8) (sinon, il déborde à 255 µs ; OK ? Avec un timer sur 16 bits, pas besoin du préscaler ; OK ?

Ma seule expérience avec les PIC en C et d'avoir fait jou jou avec des leds et des boutons ainsi que la mise oeuvre d'un afficheur LCD (j'ai démarré avec des exemples fonctionnels et j'ai modifié les programmes afin d'obtenir des résultats plus "évolués"

Voilà.

Reply to
HITS

Ils se valent, a quelques subtilites pres, differences de facilite d'utilisation, possibilite de cross-linker differents codes objets, bonnes librairies, interface intuitive, etc ... il n'y a pas de bon ou mauvais choix *a mon avis* mais plutot des preferences personnelles.

Oui, il deborde a 0xFF =3D 255, mais ce ne sont pas des microsecondes, parce-que l'increment temporel est (Freq_Osc / prescaler), dans ton cas ca fait 4 MHz / 8 =3D 500 KHz =3D> 2 uS par increment, et multiplie par 256, le debordement se produira a 512 uS.

Oui: 2,2 ms / 2 uS =3D 1100 et dans ce cas tu pourras mesurer des durees jusqu'a 131 ms, avec une precision de 2 uS. Toujours sur 16 bits mais avec un prescaler de 1, la precision sera de 250 nS et la mesure maxi de 16 mS.

Plus la valeur du prescaler sera petite, plus la precision de la mesure sera grande.

es

Alors tu as toutes les billes pour cette manip !

L'ideal serait de faire des tests avec un generateur de signaux rectangulaires dont tu connais precisement les durees des crenaux, comme ca tu peux valider les mesures faites par ton programme.

Ca pourrait meme etre une sortie du PIC que tu reboucles physiquement sur l'entree de mesure.

Reply to
Jean-Christophe

Jean-Christophe a émis l'idée suivante :

Otez-moi d'un doute ; il y a bien un seul langage C pour les PIC contrairement au basic où il y en a plusieurs ???

Reply to
HITS

Bonjour,

Cette manière de procéder me paraît un peu bizarre (certains diraient bien moderne) ! Dans le cadre d'un développement, j'aurais tout simplement connecté un oscilloscope pour observer le signal. N'importe quel modèle bas de gamme ou d'occasion à trois sous convient pour cet usage. Le signal issu de la voie est peut être plus complexe que ce vous pensez et avec une "mesure" par PIC vous prenez le risque de grossières erreurs d'interprétation.

Bonnes manips

Jean-François FOURCADIER

------------------------------------

HITS a écrit :

Reply to
J.F. FOURCADIER

J.F. FOURCADIER a exposé le 03/06/2009 :

Je ne comprend pas bien votre remarque, pourquoi cette manière de proceder est t'elle bizzare ???

Quant au signal de sortie , je le connais parfaitement ; c'est un signal variant de 1ms à 2ms avec une période de 20ms. Pouvez-vous m'aider pour le bout de programme ? (en MikroC)

Cordialement. Pat.

Reply to
HITS

La reponse a ta question est OUI, mais il faut bien differencier les differents niveaux de code :

Le seul language que connaisse un uC ou un uP, c'est le code binaire de ses instructions machine (qu'on ecrit en mnemoniques assembleur) Le PIC ne connait pas le C, ni le Basic, ni aucun autre language evolue, c'est le travail du compilateur que de "traduire" le C en code ASM.

Pour ce qui est des compilateurs C, ils ont tous en commun de reconnaitre et respecter les structures standard du C, donc un programme ecrit en C sera plus portable qu'un programme ecrit en Basic.

Reply to
Jean-Christophe

Excusez moi, j'ai mal compris la question posée. J'ai été abusé par le terme "mesure". Je comprends maintenant que vous voulez faire une acquisition de la durée des impulsions pour un traitement.

cordialement,

HITS a écrit :

Reply to
J.F. FOURCADIER

Je t'ai deja donne du code qui fait la mesure par interruption, mais voici du code plus simple qui fait la mesure sans utiliser d'interruption.

Ce code est compilable avec MikroC, puisque c'est du C !

Tu dois juste adapter ceci: (voir la doc du PIC et la doc MikroC)

1) Le (#define ENTREE) pour le port sur lequel tu entres le signal. 2) La fonction init_timer() que je ne connais pas sur ton PIC. 3) La fonction printf() pour l'affichage du resultat sur ton LCD

/************************************************ Horloge OSC = 4 MHz Timer = 16 bits Prescaler = 1 Le timer va s'incrementer toutes les 250 ns La duree mini de mesure sera de 250 ns et la duree maxi sera de 16,383 ms

************************************************/

// constantes #define ENTREE RA0 // signal sur le bit zero du port A #define FACTEUR 4000 // 4000 fois 250 ns font 1 ms

// variables unsigned long uDebut, uFin; // valeur du timer en debut et fin de mesure float fDuree; // variable flottante pour l'affichage en ms avec decimales

// programme void main(void) { // initialisation init_timer(1); // initialise le timer 16 bits avec prescaler = 1

// boucle principale while(1) { // mesure de l'impulsion while( !ENTREE ) ; // attend le debut de l'impulsion uDebut = TIMER; // lit la valeur du timer au debut de l'impulsion while( ENTREE ) ; // attend la fin de l'impulsion uFin = TIMER; // lit la valeur du timer a la fin de l'impulsion

// calcul de la duree et conversion en millisecondes fDuree = (float)(uFin - uDebut) * FACTEUR;

// affichage du resultat de la mesure printf( " duree = %f ms \n " , fDuree );

delayMs(1000); // on attend une seconde pour lire l'affichage

} // boucle principale

} // fonction main

Reply to
Jean-Christophe

"HITS" a écrit

========== Il n'y a pas qu'un seul langage C pour pic Leur particularité commune est que l'architecture générale du code source est celle du "C" crée autrefois pour programmer simplement les ordinateurs. Il sont tous différents , plus ou moins performants dans leur travail de traduction en code exécutable par le PIC , plus ou moins onéreux . Par exemple un compilateur C à plus de 4500 euros ht sera sans doute plus performant que le MiKroC à 150 euros.

Reply to
maioré

Il n'existe qu'un seul language C, celui defini par Kernighan & Ritchie, et dont l'evolution en C ANSI est duement standardisee depuis 1988 par une norme ISO.

source

urs.

Il s'agit donc toujours de C dans tous les cas, alors d'ou sors-tu ces differents languages C ?

Les performances d'un compilateur pour un language donne, sont independantes de la structure du language lui-meme !

Tu confonds "language C" avec "compilateur C".

Reply to
Jean-Christophe

"Jean-Christophe" a écrit dans le message de news: snipped-for-privacy@d31g2000vbm.googlegroups.com...

et si le timer a fait un tour ?

Reply to
jlp

Et si tu lisais les specifications qu'il a donne ?

- Frequence OSC = 4 Mhz

- Valeur a mesurer de 0,8 ms a 2,2 ms.

Sur 16 bits a 4 Mhz on va au-dela de 16 ms, le timer ne fera donc pas un tour complet.

J'ai aussi donne du code avec une variable 16 bits incrementee par l'interruption d'overflow du timer. Ca donne 32 bits qui couvrent plus de 17 minutes, toujours avec une precision de 250 nanosecondes.

Reply to
Jean-Christophe

comme ton timer n'est pas lance par interruption, il peut donc faire un tour meme sur 16 bits

s ' il est rendu a 0xFFFE quand tu lis la valeur de debut, il sera passé par

0 quand ti liras la valeur de fin

on ne peut pas lancer le timer sur un front sur ces pics ?

Reply to
jlp

Oui tu as raison.

Sur ce PIC la je ne sais pas, mais on peut toujours forcer sa valeur a zero lors de la detection du front montant :

while( !ENTREE ) ; // attend le debut de l'impulsion TIMER =3D 0; // force la valeur du timer a zero while( ENTREE ) ; // attend la fin de l'impulsion uDuree =3D TIMER; // lit la valeur du timer fDuree =3D (float)(uDuree) * FACTEUR; // conversion en ms

Reply to
Jean-Christophe

Le Wed, 03 Jun 2009 11:01:36 +0200, Jean-Christophe a écrit:

... ou plus exactement en une suite d'octets que l'on représente généralement sous la forme hexadécimale? A moins qu'il existe des PICs a qui on peut faire ingérer directement de l'ASM? (connais pas encore ces bestioles, mais ça m'intéresse)

Absolument, et c'est ce qui rend ce langage intéressant. Mais pour ma part, je n'ai jamais réussi à digérer la syntaxe très particulière du C. Ce qui fait que, par fénéantise, je ne programme qu'en BASIC (BBC BASIC et HPBASIC). A tort, puisque je ne peux pas vraiment "porter" mes applications vres la plateforme wintel par exemple...

JLuc

Reply to
jls

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.