Interface à base de pic pour gestion d'impulsions

jihelbi:
Je veux juste te dire que la multiplication de fréquence c'est du hardware et du software qui ne sert absolument à rien.

JLB

C'est bien ce que je pensais, t'as pas compris du tout... le PIC ne doit pas mesurer la fréquence, mais la multiplier (la valeur qu'il peut mesurer dans le premier timer, une fois qu'elle est transmise dans le second timer, on s'en fout). Regarde le graph que j'ai mis : c'est le nombre d'impulsions qui est multiplié, pas une valeur numérique! Si je compte mes impulsions sur la troisième courbe, tu ne crois pas que je vais compter plus ou moins d'impulsions? et pas forcément par bloc de 10... la preuve :

Si mon signal d'entrée fait 25 impulsions / sec (25Hz quoi), je le multiplie par 10 dans le pic à l'aide de ses deux timers. en sortie du pic, j'ai quoi? ben un signal qui fait 250 impulsions par seconde, non?

Bon, dans l'arduino qui est à l'autre bout du fil, si je compte les impulsions du signal d'entrée sur une fenêtre de 990ms, alors je trouve 24 (il faut une seconde complète pour trouver 25 imp). Avec cette même base de temps, je compte le signal généré par le pic : je trouve 247 impulsions. Pour savoir où j'en suis et retrouver le nombre d'impulsions de mon signal d'origine, comme la fréquence à été multipliée par 10, je divise le nombre d'impulsions par 10, et je trouve : float x = NB_Imp / 10 = 24.7

Est-ce que mon comptage n'est pas plus précis en multipliant ma fréquence avant comptage? avec 990ms, je suis très proche de la seconde, donc mon comptage devrait être très proche de 25. avec ma solution, je suis plus proche de 25 qu'en ne comptant que les impulsions de départ.

Dans mon exemple, mon moteur tourne à 34,090909... tr/min.

Comptage des impulsions d'entrée (abstraction des dents manquantes pour le coup) : je dois multiplier le nombre d'impulsions comptées par (60/44/0.99 = 1.37741) pour trouver la rotation du moteur. donc j'ai compté 24, je trouve une vitesse de 33.05784 tr/min Erreur = ~ -1,03.

Comptage des impulsions de sortie du pic : je dois maintenant multiplier par (60/44/0.99/10 = 0,137741), j'ai compté 247, je trouve 34,022027 tr/min. Erreur = ~ -0,07.

Quelle méthode est la plus précise? sachant qu'en réel, mon moteur tournant à 34.09090909... tr/min donne 24.75 impulsions par tranche de temps de 0.99s... dans le premier comptage, on a perdu 0,75 impulsions, dans le second, seulement 0,05. (0,75 x 1,37741 = 1,03305 et 0,05 x 1,37741 = 0.068882). Si t'arrives encore à me dire que je me plante, va falloir que je trouve une nouvelle forme pour te l'expliquer!

De même, il m'arrive d'utiliser le truc suivant pour arrondir un nombre avec des décimales :

float arrondi2(float x){
  float y;
  y = x*100;
  return (int(y)/100);
}

Tu vas me dire que x contenait déjà des décimales... ok, mais dans un beau signal carré où on synchronise les impulsions sur front montant, le front descendant ne correspond-il pas à une demi impulsion (0,5)?

Et un signal de période 1 seconde, est-ce que pour t = 1,4541220147 s on ne peut pas considérer le signal quand même? les impulsions contiennent une donnée importante : la période (le temps entre deux impulsions) qui s'exprime en secondes, ms, µs, ns... ne sont-ce pas des décimales, tout ça? Et c'est justement le rôle des impulsions d'un signal (hormis PWM) de donner des bases de temps. Si ta montre n'affichait pas les secondes, comment ferais-tu un oeuf à le coque? n'essaierais-tu pas d'inventer un système qui te permet de découper les minutes de ta montre et ainsi avoir le temps correct pour la cuisson?

sur mon moteur, une dent correspond à 8.182°. j'ai quand même le droit de savoir ce qu'il se passe quand il est à 45°, même si ça na correspond pas à une impulsion... c'est pas un moteur pas-à-pas... (45 degrées correspond à 5,5 dent).

essaie de comprendre : le système qui compte les impulsions existe déjà. il me faut juste un petit circuit qui adapte le signal. (vais finir pas le faire moi-même...)

Je reconnais que j'ai bien tartiné le truc, un beau pavé, alors si j'ai pris le temps de l'écrire, prends le temps de lire, merci.


A part ça, quelqu'un saurait me programmer un PIC? je viens de télécharger MPLab, pour voir si ça peut me le simuler dans un premier temps... Pis ben... J'voudrais bien programmer moi-même, mais j'ai pas de port // sur mon PC pour utiliser les montages du net.

Bon, dans l'arduino qui est à l'autre bout du fil, si je compte les impulsions du signal d'entrée sur une fenêtre de 990ms, alors je trouve 24 (il faut une seconde complète pour trouver 25 imp). Avec cette même base de temps, je compte le signal généré par le pic : je trouve 247 impulsions. Pour savoir où j'en suis et retrouver le nombre d'impulsions de mon signal d'origine, comme la fréquence à été multipliée par 10, je divise le nombre d'impulsions par 10, et je trouve : float x = NB_Imp / 10 = 24.7

Ce post relève du canular...

COMMENT LE PIC TROUVE T-IL 247 ???????????? IL NE PEUT TROUVER QUE 240 OU 250 OU 230 !!!!!!!!!!!!!!!!!!

JLB

PS: surtout ne pas craquer ! surtout ne pas craquer ! surtout ne pas craquer !..

jihelbi:
Ce post relève du canular...

COMMENT LE PIC TROUVE T-IL 247 ???????????? IL NE PEUT TROUVER QUE 240 OU 250 OU 230 !!!!!!!!!!!!!!!!!!

JLB

PS: surtout ne pas craquer ! surtout ne pas craquer ! surtout ne pas craquer !..

J'essaie de rester zen, mais t'es bougrement têtu! je remets les courbes :

Les deux premières sont identiques, c'est le signal qui sort du capteur. Moi, je veux juste que le pic me fournisse les deux autres courbes, c'est à dire un signal contenant 8 fois plus d'impulsions que celui du capteur. Regarde l'algo du premier post : où vois-tu un comptage? ben non, y'a pas besoin de compter! il suffit de mesurer la période des impulsions avec un timer à 2MHz et de générer avec cette même mesure mais sur un timer 8 fois plus rapide un signal carré... c'est pas assez clair? ]:slight_smile:

MA METHODE DE MESURE SE TROUVE DANS UN AUTRE SYSTEME QUE J'ETALERAI DANS UN AUTRE TOPIC! ICI? IL FAUT JUSTE ME PONDRE LES TROISIEME ET QUATRIEME COURBES.

compte les impulsions de la troisième courbe : tu la comptes 10 par 10? ben pas moi, et encore moins l'arduino dont on ne parle pas ici.

et je répète encore :

le PIC ne doit pas mesurer la fréquence

le pic NE COMPTE PAS LES IMPULSIONS vindédiou!

Je reconnais que j'ai bien tartiné le truc, un beau pavé, alors si j'ai pris le temps de l'écrire, prends le temps de lire, merci.

t'as lu cette phrase? T'es en train de parler d'un autre sujet, et j'imagine que si quelqu'un pouvait me rendre le service que je demande, ben il n'aura plus trop envie de se farcir tout ça...

Bon, dans l'arduino qui est à l'autre bout du fil, si je compte les impulsions du signal

C'est l'arduino qui compte les impulsions!!! et là, c'est un topic qui parle d'une interface contenant un PIC, mais pas d'arduino!

Il est des cas fortuits où l'homme le plus entreprenant est soumis à des vicissitudes des plus aléatoires...

Il n'est point besoin de réagir à l'épiphonème du docte logographe dont je tiens à dulcifier l'éloquence mordacite pour sémiologer une prose hyaline dont l'indéhiscence ne peut apparaître qu'à quelques onguligrades lignicoles à l'affut d'amphibologies gonadotropiques.

A bon entendeur adieu à ce post...

JLB

PS: J'aurais du accepter de lui faire son PIC multiplicateur. Il proposait de l'argent après tout...

Bien tenté, mais ça montre juste que tu t'es rendu compte de ta bourde et que tu n'oses même pas le dire... utiliser des mots si savants est un beau bouclier pour cacher sa bêtise.

Non, je ne paye pas l'intervenant, je le défraie, c'est pas vraiment pareil.

Quelqu'un a compris ce que je cherche et pourrait m'aiguiller?

Réouverture du sujet XD

Je précise également que j'ai indiqué à jihelbi qu'un forum est un espace ouvert où l'on partage les opinions et non pas un exutoire qui sert à imposer ses idées comme étant unique en pensant de façon unilatérale que les autres sont des ignares hébétés profonds.

Je n'ai jamais utilisé un PIC de ma vie (je ne veux pas de faire de faux espoir ;)), en revanche la subtilité de la multiplication de la fréquence me titille les neuronnes...

Ce que j'ai compris :

Tu as un contrôleur côté moteur (disons le PIC), qui lit le signal suivant :

(Au fait, quelle est la fréquence max de ce signal ?)

Il doit :

  • Constituer, un signal basé sur la fréquence T multipliée (disons 10T, c'est humainement plus facile même si au final ça sera 8T ou 16T) ET combler la(es) dent(s) manquante(s)
  • Générer un second signal qui ne montera que durant 1T, juste après constatation de la dent manquante

Le signal multiplié me semble relever du post traitement (ou de l'estimation) et tu ne pourra le générer qu'avec plusieurs T de retard, est-ce acceptable ? dois-tu synchroniser le second signal pour qu'il accuse le même retard ?

Dans le cas ou tu préfère l'estimer à l'avance, tu pars plutôt sur le cas des fronts montants ou descendants ?

Tu as un autre µc qui lit les 2 signaux générés :

  • Il compte régulièrement les changements d'état du premier signal transmis pour définir la vitesse de rotation du moteur (c'est la que la multiplication est utile).
  • Fais je ne sais pas quoi de la dent manquante en rapport avec le retard à l'allumage ?

Suis-je dans le ton ?

Pour avoir 2 timers 16 bits, ne peux-tu pas étendre "logiciellement" l'un des timers 8bits d'un 328P ?

Sev

Pour multiplier une fréquence, une PLL genre CD4046 ne ferait-il pas l'affaire ?

On va réexpliquer un peu...

On part du volant moteur (qui est fixé à l'arbre de sortie du moteur, donc qui tourne tout pareil) :

On voit ici les deux crénaux élargis, à la fin desquels on trouve notre info "synchro" (décalée en réalité de 90°, pour permettre au µP d'avoir un peu d'avance pour calculer le bon moment d'étincelle (entre 8 et 45°avant le PMH réel), ce qui lui laisse 1/4 de tour moteur pour faire son petit calcul).

Pour l'instant, on s'affranchit du décalage...

Le capteur fournit le premier signal :

Il faut donc un circuit qui me sorte les deux signaux du bas.

Dans mon idée,

1) un timer 16 bits mesure le temps T ou 3T entre deux fronts descendants du signal d'entrée, avec une base de 2MHz.
Pour rester ne pas déborder, le temps le plus long étant 3T, ne doit pas dépasser 65535/2.106 = 32,768 ms, soit Tmax = 10,92ms, ce qui correspond à une vitesse de rotation du moteur de Vmot-min = 60/44/Tmax = 125tr/min. De même, On trouvera Vmot-max = 2730000tr/min, mais on n'ira pas jusque là...

  1. A chaque impulsion du capteur, on trouve donc un temps T(n) = T (dent normale) ou 3T = (dent PMH). Donc si T(n) > 2xT(n-1), on en déuit qu'on a à faire à une dent PMH (comme le précisait jihelbi, avec l'inertie du moteur, la vitesse de rotation ne peut pas varier trop vite, et pour que la comparaison T(n) > 2xT(n-1) soit vérifiée en dehors d'une dent PMH, cela reviendrait à faire passer le moteur de 1000tr/min à 500tr/min en 1ms, c'est pas très pensable). Donc deux cas :
    2.a) Si T(n) > 2xT(n-1) (dent PMH) : on met à 1 la sortie "synchro".
    2.b) Si T(n) < 2xT(n-1) (dent normale) : on met T comme nouvelle base pour le timer de sortie (qui tourne à 16MHz) et on met à 0 la sortie Synchro.

Je pense qu'avec ça, j'ai mes deux signaux. Reste une sombre histoire de débordements (lors du démarrage par exemple) du timer d'entrée (si le moteur tourne en dessous de 125tr/min), de ne pas générer de signaux, mais c'est accessoire.

UniseV: Pour avoir 2 timers 16 bits, ne peux-tu pas étendre "logiciellement" l'un des timers 8bits d'un 328P ?

J'y avais pensé, mais j'étais tellement dans mon idée d'un pic à côté qui me gère le tout... attends... heu... En effet, je pourrais utiliser le timer2 en mesure d'entrée avec une ISR(T2_OVF) qui incrémente une variable genre T2_MSB et le timer1 en générateur de sortie avec ICR1H = T2_MSB; ICR1L = TCNT2;
Pas bête... je crois que je vais tester...

barbudor : Pour multiplier une fréquence, une PLL genre CD4046 ne ferait-il pas l'affaire ?

j'en parlais aussi avec Al1fch, par rapport aux dents manquantes, la PLL ne risque pas de "dérailler" un court instant? J'ai pas trop bossé sur les PLL, car à l'école (dans l'temps), on ne les utilisait que pour émission/réception radio, c'était encore du temps où on ne savait pas faire de µP aussi rapides que les quartz, maintenant, les quartz sont largement dépassés par la vitesse de l'électronique... Donc je ne vois pas trop. (puis je me suis spécialisé très vite dans l'audio, donc dès qu'on passe le "mûr du son" qui chez moi est à 300KHz, je suis tout perdu, et je n'utilise jamais de PLL)... Mais si t'as une idée, pourquoi pas...

Et pourquoi ne pas utiliser les 2 sorties "hard" d'un même timer 16bits ?

Genre :
OCR1A & OCT1B sur un 328P.

Sev

UniseV:
Et pourquoi ne pas utiliser les 2 sorties "hard" d'un même timer 16bits ?

Genre :
OCR1A & OCT1B sur un 328P.

Sev

Je vois pas trop... il ne me faut qu'un seul générateur de signal carré... Faut que je regarde comment configurer mon timer justement...

Salut,

Super_Cinci:

UniseV:
Et pourquoi ne pas utiliser les 2 sorties "hard" d'un même timer 16bits ?

Genre :
OCR1A & OCT1B sur un 328P.

Sev

Je vois pas trop... il ne me faut qu'un seul générateur de signal carré... Faut que je regarde comment configurer mon timer justement...

Le générateur de signaux et l'interruption d'overflow/comparaison d'un même module OCRx sont liée physiquement, mais les modules sont séparé entre eux.

Avec le Timer2 (par exemple) tu peut générer un signal carré en utilisant OCR2A + générateur de signaux A.
Et faire ton signal n°2 avec l'interruption "compare match" de OCR2B (+ morceau de code).

Seul contrainte : 1 même timer = 1 prescaler commun, il faut donc calculer le prescaler pour que les valeurs de OCR2A et OCR2B ne dépasse pas la valeur max de TCNT2 (16 bits).

La comme ça, je ne vois pas du tout. Qu'est le "générateur de signaux A"? Il me parrait difficile d'utiliser le timer 2 en sortie, donc j'ai fait un premier code pour le 328p :

/*********************************************
**        Multiplicateur d'impulsions       **
**********************************************
**        Circuit d'accessoire pour         **
**        ODB / REGULATEUR de vitesse       **
**********************************************
** Pin / por - Signal                       **
**  02 - PD2 - PMH IN                       **
**  09 - PB1 - Imp moteur OUT               **
**  10 - PB2 - Imp PMH OUT                  **
*********************************************/

volatile byte T2_MSB;  // extention logicielle de timer2
volatile word TCNT2_New, TCNT2_Old; // ancienne mesure de timer2

void Timers_Setup(){  // configure les timers 1 et 2
  TCCR1A = 0x02;   // WGM1 = fast PWM
  TCCR1A += 0x80;  // Activation PWM sur OC1A
  TCCR1B = 0x18;   // (WGM1 = Fast PWM)
  OCR1A = 200;  // durée d'impulsion sur OC1A
  
  TCCR2A = 0x00; // normal port operation
  TCCR2B = 0x00; // Clock = 0Hz
  TIMSK2 = 0x01; // int sur OverFlow
}

void Timers_start(){
  TCCR1B += 0x01;   //  Prescaler = 1 (16MHz)
  TCCR2B = 0x02; // Clock = 2MHz
  EICRA = 0x02;  // autoriser INT0
}

void setup() {
  Timers_Setup();
  DDRB |= 0x06; // pins PHM_OUT en sortie
  DDRD &= 0xFB; // pin PMH en entrée
  PORTD |= 0x04; // activation pullup pin PMH
  Timers_start();
}

ISR(T2_OVF){   // extention logicielle de T2 en 16 bits
  T2_MSB++;
  if (T2_MSB = 0) { // débordement, le moteur ne tourne pas assez vite ou pas du tout)!
    // a définir
  }
}

ISR(INT0_VECT){   // réception impulsion capteur PMH
  TCNT2_New = TCNT2 + (T2_MSB << 8);    // lecture Timer2
  TCNT2 = 0;
  T2_MSB = 0;  // mise à zéro timer2
  if (TCNT2_New < TCNT2_Old){  // impultion "normale"
    ICR1 = TCNT2_New;   // update Timer1
    TCNT2_Old = TCNT2_New << 1;  // préparation de la prochaine comparaison (TCNT2_Old = TCNT2_New * 2)
    PORTB |= 0xFB; // impulsion PMH OFF
  } else {                     // Impulsion "PMH"
    PORTB |= 0x04; // impulsion PMH ON
  }
}

void loop() {
}

Sachant que pour le tester, j'ai un second code qui me génère le signal du capteur à faire tourner dans un MEGA2560 (je n'ai que ces deux cartes sous la main actuellement). En même temps, la MEGA me génèrera également les autres signaux (vitesse véhicule, conso...) histoire d'avoir un banc de mesure complet...

Super_Cinci, merci pour tes explications, mais je n'ai pas trouvé l'information suivante : "A quelle vitesse max tourne cette roue dentée ?"
D'ailleurs j'ai une autre question : à quelle vitesse minimum tourne cette roue dentée quand le moteur est allumé (ralenti) ?

Je te prépare une proposition de parametrage de timer... qui j'espère te plaira :roll_eyes:

Sev

UniseV:
Super_Cinci, merci pour tes explications, mais je n'ai pas trouvé l'information suivante : "A quelle vitesse max tourne cette roue dentée ?"
D'ailleurs j'ai une autre question : à quelle vitesse minimum tourne cette roue dentée quand le moteur est allumé (ralenti) ?

Je par du principe que lorsqu'on démarre le moteur, il tourne aux environs de 200tr/min, puis une foi au ralenti, minimum 600tr/min. Max : 10 230tr/min (le 230, c'est une vilaine histoire que 10230 = 10 x 1023 et que analogRead() renvoie au max 1023. C'estcon, mais dans l'avenir, ça peut avoir son importance...)

Bref, pour les trois régimes listés ci-dessus, on a :
x = 200; 600; 10230. (tr/min)
T = 6.82ms; 2.27ms; 133.3µs.
3T = 20.46ms; 6.82ms; 400µs.

la formule magique : T = 60/44/x , x étant la vitesse de rotation du moteur en tr/min.

si T = 130 µs alors x = 10 489,5
si T = 130,5 µs alors x = 10 449,3

Je pense que c'est ce pas de 40 trs/min que tu veux gommer en multipliant la fréquence ?

Peux-tu nous en dire plus sur la globalité tu projet, que fait le MEGA avec les 2 signaux que tu souhaites générer ?
La première sert à calculer les trs/min mais la seconde avec la dent PMH ?

Sev

A partir de mes deux signaux, dans le MEGA2560 :

  • le carré représentant 352 dent / tour moteur incrémentera le timer5 (via T5 par exemple).
  • le second (impulsion PMH) viendra déclencher l'ICP5.

Dans le MEGA, un timer déclenche une interruption toutes les 256ms, dans laquelle je relève TCNT5 puis fais TCNT5 = 0, et je multiplie ma valeur par 1.5 pour trouver la vitesse du moteur en tr/min.

Lors de l'iCP5, je relève ICR5 tout en laissant tourner le compteur bien sûr, puis à l'aide une seconde interruption déclenchée par l'étincelle de l'allumage, je calcule l'avance à l'allumage. (c'est surtout là que la multiplication d'impulsions aide dans la précision...)

C'est tout... Tu vas me dire que le 328P peut certainement s'occuper de tout ça de envoyer les valeur au MEGA via USART, mais non, je veux des signaux bien précis, c'est comme ça...

Les pins mentionnées ici ne sont données qu'à titre indicatif, car le MEGA va mesurer tout un tas d'autres données, et au final, les faire afficher sur deux écrans graphiques LCD de 160 x 128 qui remplaceront le tableau de bord actuel. Les autres mesures sont beaucoup plus simples, ça se fera tout seul.

De plus, le MEGA aura la lourde (mais essentielle) tâche de remplacer le câble d'accélérateur : un portar sur la pédale et un servo sur le carbu, plus de câble. Il y aura un mode "régulateur de vitesse" et un autre "limiteur de vitesse". Et certainement la gestion du starter avec un autre servomoteur, puis il me restera une troisième voie pour un troisième servo, mais pour quoi faire? je ne sais pas encore...

mon coéf de 1.5 risque de tomber à 1 si je fais une fenêtre de 170.45ms au lieu de 256ms, mais ma "fenêtre" doit être assez large pour y éxécuter les différentes fonctions, donc notamment le régulateur qui a besoin d'intervalles de calcul réguliers pour être précis.

A partir de ces deux signaux, dans un autre projet, je compte refaire un AEI (calculateur d'allumage) que l'on peut reprogrammer à souhaits. Mais je pense passer à une multiplication plus élevée, et peut-être passer sur une plateforme 32bits/168MHz comme le STM32F4 par exemple.

Mais tout ça, c'est un autre projet. Ce qui compte ici, c'est de faire de l'extraction de synchro et multiplication, rien d'autre (un peu comme les circuits vidéo)...

Super_Cinci:
La comme ça, je ne vois pas du tout. Qu'est le "générateur de signaux A"? Il me parrait difficile d'utiliser le timer 2 en sortie

Pour mieux comprendre -> datasheet page 146, figure 18-1.

Tu peut voir que OCRnA (le registre qui est comparé avec TCNTn et qui peut générer une INT sur overflow et/ou "match compare") et associé à un module "Waveform Generation" OCnA.

Comme tu as OCRnA et OCRnB tu peut utiliser OCRnA en INT "match compare" pour générer le signal n°2 (avec le morceau de code qui va bien) et OCRnB en "waveform génération" (mode FastPWM avec TOP = OCRnB) pour générer le signal n°1.

En gros le canal A génère une INT (sans signal PWM) sur lors du "match compare" OCRnA/TCNTn et le canal B génère un signal PWM (sans INT) lors du "match compare" OCRnB/TCNTn .

Tant que tu peut caser tes deux valeurs de "match compare" dans OCRnA et OCRnB avec un même prescaler pour les deux tout va bien.

skywodd:
Pour mieux comprendre -> datasheet page 146, figure 18-1.

heu... pas trouvé, page 146 : on est dans le 17.1...

Ce que je ne vois pas, c'est comment un timer peut générer un un signal carré B et une impulsion A toutes les 352 impulsions de B... Sachant que l'on décide de générer l'impulsion A en fonction du signal de référence externe...

@Super_Cinci :
Je comprends que tu ne veuilles pas utiliser de liaison Asynchrone type USART puisque tout ton système est synchrone, tu veux du temps réel côté MEGA pour la partie calcul du retard à l'allumage. (donc dent PMH ?)

En revanche pour la partie trs/min, pour une mesure précies, il suffit de prendre un tour complet (entre 2 passsages de la dent PMH) et on obtient un calcul précis... (même haut dans les tours avec un prescaler à clk/8 on garde une précision de moins d'un tour par minutes).

Ne peut-on pas imaginer de séparer ces 2 fonctions ?