Machine de relevé d'arbre à cames

Bonjour,

je travaille en ce moment sur un projet de relevé de profil de cames sur la machine que j'ai conçue. Un motoréducteur brushless fait tourner un mandrin à 6 tr/min, qui tient l'arbre à cames. Un codeur incrémental 1000 pts/tr donne une impulsion qui lance la requête à un comparateur mitutoyo, qui envoie ensuite l'information à mon arduino. J'en appelle non seulement à ceux qui peuvent m'aider pour l'acquisition avec l'Arduino mais aussi ceux qui ont l'habitude de communiquer avec lui par VB.NET et le port série (virtuel ou non).

L'application VB.NET que je tente de développer est un programme qui doit :

  • Trouver et ouvrir le port COM permettant la communication avec l'Arduino (Réussi)
  • Lancer un cmdByte demandant à l'arduino de lancer le moteur et de commencer l'acquisition grâce au comparateur (J'avais réussi mais ça ne marche plus)
  • Stopper l'acquisition soit par l'appui sur un bouton, soit après l'acquisition de 1000 pts (Problème ici ...)
  • Ecrire ces valeurs dans un tableau Excel et sauvegarder ces valeurs (Réussi)

Le programme d'acquisition de l'Arduino doit :

  • Récupérer l'instruction du PC demandant le lancement du cycle (J'avais réussi mais ça ne marche plus)
  • Lancer le moteur (Réussi)
  • Envoyer une requête au comparateur en réaction des interruptions déclenchées par le codeur (Réussi)
  • Récupérer l'information du comparateur et la retransmettre au PC (Réussi)
  • Recevoir l'instruction d'arrêt du cycle par le PC (Jamais marché)

Ces codes ne sont pas fonctionnels et j'en suis désolé, mais je me retrouve bloqué ici en espérant qu'une âme charitable vienne m'aider dans ma grande détresse :stuck_out_tongue:

Code VB.NET :

'Espace de noms permettant la gestion des ports série
Imports System.IO.Ports.SerialPort

Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop

Public Class Form1

    'Liste des ports COM disponibles
    Dim a() = GetPortNames()
    Dim cmdByte As Byte
    Dim releve() As String
    Dim id As Integer

    'Variables pour Excel
    Dim xls As Excel.Application
    Dim xlsclasseur As Excel.Workbook
    Dim xlsfeuille As Excel.Worksheet

    'Initialisation de la fenêtre lors de son chargement
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        'Ajout des ports com disponible dans la ComboBox
        For Each gatto In a
            ComboBox1.Items.Add(gatto)
        Next

        ReDim releve(1200)
        id = 0

        xls = CreateObject("Excel.Application")
        xlsclasseur = xls.Workbooks.Add
        xlsfeuille = xlsclasseur.Worksheets(1)

        'Initialisation de la barre de statut et du label d'affichage des valeurs
        ToolStripStatusLabel1.Text = ""
        Label1.Text = ""

        Button2.Enabled = True
        Button1.Enabled = False

        While (False = Button1.Enabled)

        End While

    End Sub

    'Validation du choix du port COM et envoi d'instruction à l'Arduino
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click

        'Ouverture et paramétrage du port si l'un des ports disponibles à été choisi
        If Not (ComboBox1.Text = "") And Not Button1.Enabled Then

            'Désactivation du bouton de validation du port COM
            ToolStripStatusLabel1.Text = "Port sélectionné : " & ComboBox1.Text
            'Button2.Enabled = False
            Button1.Enabled = True
            cmdByte = 1

            SerialPort1.PortName = ComboBox1.Text
            SerialPort1.BaudRate = 19200
            SerialPort1.Parity = IO.Ports.Parity.None
            SerialPort1.StopBits = 1
            SerialPort1.Open()
            SerialPort1.Write(cmdByte)

        End If

    End Sub

    'Evènement réception de données
    Private Sub SerialPort1_OnComm() Handles SerialPort1.DataReceived

        id = id + 1
        releve(id) = SerialPort1.ReadLine()

    End Sub

    'Envoi du signal d'arrêt des requêtes de l'arduino au comparateur
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        cmdByte = 0
        SerialPort1.Write(cmdByte)

    End Sub

    'Copie du tableau dans la feuille excel
    Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click

        For i = 1 To releve.Length
            xlsfeuille.Cells(i, 2).Value = releve(i - 1)
        Next

        xlsclasseur.SaveAs(xls.GetSaveAsFilename())
        xlsclasseur.Close()

    End Sub

End Class

Code Arduino :

int req = 13; //mic REQ line goes to pin 13 through q1 (arduino high pulls request line low)
int dat = 12; //mic Data line goes to pin 12
int clk = 11; //mic Clock line goes to pin 11
volatile int i = 0; int j = 0; int k = 0;

float mm;

int cmdByte;
byte mydata[14];

void setup()
{
  pinMode(52, OUTPUT);
  pinMode(50, OUTPUT);
  pinMode(48, OUTPUT);
  pinMode(46, OUTPUT);
  Serial.begin(19200);
  pinMode(req, OUTPUT);
  pinMode(clk, INPUT);
  pinMode(dat, INPUT);
  digitalWrite(clk, HIGH); // enable internal pull ups
  digitalWrite(dat, HIGH); // enable internal pull ups
  digitalWrite(req, LOW); // set request at high
}

void loop()
{
  
}

void pulse()
{
  digitalWrite(req, HIGH); // generate set request
  
  for (i = 0; i < 13; i++) {
    k = 0;
    for (j = 0; j < 4; j++) {
      while(digitalRead(clk) == LOW) { } // hold until clock is high
      while(digitalRead(clk) == HIGH) { } // hold until clock is low
      bitWrite(k, j, (digitalRead(dat))); // read data bits
    }

    mydata[i] = k; // data received into this array
  }
    
  long num;  // data treatment
  char buf[9];
  
  for(int lp=0;lp<6;lp++)
    buf[lp]=mydata[lp+5]+'0';
    
  buf[6]=0;
  num=atol(buf);
  
  mm = (float)num/100;
  
  if (mydata[4] < 1){
    Serial.print("+");
  }else{
    Serial.print("-");
  }
  
  Serial.println(mm);
  
      digitalWrite(req,LOW); // stops set request
}

void serialEvent()
{
  cmdByte = Serial.read(); // receive command from USB interface
  
  if (cmdByte==1){
    attachInterrupt(0, pulse, RISING); // enable requests to digital indicator triggered by the encoder
    digitalWrite(48, LOW);
  }else{
    detachInterrupt(0); // disable requests to digital indicator
    digitalWrite(48, HIGH);
  }
}

Up ?

Salut,

Je n'ai pas tout compris, mais je pense que ton programme arduino a besoin d'un petit quelque chose en plus, car vu comme ça, rien ne lui permet de démarrer : il faudrait déclarer "serialEvent()" dans le serial.begin() au niveau de ton setup pour qu'il soit déclenché à chaque réception série, non?

Ensuite, pour le comptage d'impulsions, tu peux utiliser peut-être l'entrée T5 du timer/compteur 5 qui peut compter tout seul sur 16 bits (soit de 0 à 65535). L'arduino pourrait de lui-même savoir quand on arrive à un tour complet et stopper la machine, car les temps de traitement par port série pourraient laisser tourner le moteur un peu plus que prévu...

Est-ce que tu cherches en fait à mesurer le "diamètre" de la came pour chaque impulsion du codeur incrémental (soit 1000 mesures / tour) et ainsi pouvoir avoir une "image" de la came? Dans ce cas, j'aurais tendance à laisser l'arduino gérer tout seul le moteur et faire lui-même un cycle de 1000 mesures sur un tour, puis une fois le tour fini, il enverrait ces 1000 relevés au PC pour traitement. Ce ne sont que des idées, tout dépend de ton système et tes besoins...

Je n'ai pas non plus compris ce "comparateur", qu'est-ce, au juste?

Super_Cinci:
...

Je n'ai pas non plus compris ce "comparateur", qu'est-ce, au juste?

Bonjour supercinci
je pense qu'il s'agit d'un comparateur avec sortie data de ce genre là
404 voir page 247

en fait à chaque top du codeur entrainé par le moteur, il souhaite lire la valeur renvoyé par le comparateur,
il faudrait connaitre la structure des data de sortie du comparateur pour faire une simulation d'encombrement
1000 points de mesure par tour ça peut grimper vite en occupation.

C'est effectivement pas clair ce que tu cherche a faire
Mais je constate surtout que tu fait trop de chose dans ta routine d'interruption.

Quelle est la vitesse de la liaison série que tu reçoit ?
Combien de temps te faut'il pour recevoir les 13x4 bits ?

Il est extrêmement déconseillé d'utiliser Serial depuis une routine d'interruption.
Serial utilise aussi les interruptions de l'UART or le processeur ne peut traiter qu'une seule interruption à la fois.
Donc tu risque de bloquer ou de ne rien transmettre.

Sépare ce qui est temps réel de ce qui est traitement de fond.
Descend le traitement de l'interruption vers loop en utilisant une variable globale volatile comme marqueur entre l'interruption et loop

volatile boolean go = false;

void loop()
{
  if ( go )
  {
    go = false;

    long num;  // data treatment
    char buf[9];
  
    for(int lp=0;lp<6;lp++)
      buf[lp]=mydata[lp+5]+'0';
    
    buf[6]=0;
    num=atol(buf);
  
    mm = (float)num/100;
  
    if (mydata[4] < 1)
      Serial.print("+");
    else
      Serial.print("-");
   Serial.println(mm);
  
     digitalWrite(req,LOW); // stops set request
  }
}

void pulse()
{
  digitalWrite(req, HIGH); // generate set request
  
  for (i = 0; i < 13; i++) {
    k = 0;
    for (j = 0; j < 4; j++) {
      while(digitalRead(clk) == LOW) { } // hold until clock is high
      while(digitalRead(clk) == HIGH) { } // hold until clock is low
      bitWrite(k, j, (digitalRead(dat))); // read data bits
    }

    mydata[i] = k; // data received into this array
  }
  go = true;
  
}

Merci pour vos réponses !

Pour le comparateur c'est exactement ça (celui de la page 248 du catalogue mis en lien par Artouste).

Pour les 1000 points du relevé, j'avais aussi pensé à garder ces valeurs dans l'arduino et les transmettre au PC à la fin de l'acquisition, mais je ne savais pas si la gestion de "grands tableaux" (enfin pas si grands que ça mais bon ...) dans la mémoire de l'Arduino serait une cause de ralentissement ou non, mais je pense que cette solution est tout à fait valable. Et effectivement, l'arduino pourrait gérer le cycle lui même, mais je pensais pouvoir utiliser le cmdByte (obligatoire pour lancer l'acquisition à 1) présent dans mon code pour arrêter l'acquisition.

Est-ce que tu cherches en fait à mesurer le "diamètre" de la came pour chaque impulsion du codeur incrémental (soit 1000 mesures / tour) et ainsi pouvoir avoir une "image" de la came?

Oui Super_Cinci, je veux avoir la valeur du diamètre de came à chaque impulsion du codeur, mais cette partie du code fonctionnait très bien et le port série m'envoyait bien les valeurs sur le PC (le SerialEvent() fonctionnait). Je n'ai pas souvenir d'avoir modifié cette partie du code mais cela ne fonctionne plus ...

Quelle est la vitesse de la liaison série que tu reçoit ?

Le comparateur fonctionne en 9600 baud mais je trouve cette solution software de gestion de l'interface série très fiable (bien qu'assez complexe), donc je ne souhaite pas repasser sur les pins TX et RX de la carte.

Pour les timers ... Je ne comprends pas vraiment ce que tu me propose, car je ne comprends pas comment les impulsions du codeur peuvent incrémenter le timer (n'est-il pas commandé par l'horloge ? Comment les compare match peuvent incrémenter une valeur ?)

Donc tu risque de bloquer ou de ne rien transmettre.

Barbudor, je suis d'accord pour le risque de blocage, auquel j'ai déjà été confronté, mais seulement lorsque la fréquence des impulsions données par le codeur (donc la vitesse de rotation) était trop élevée, lorsque je manipulais le codeur à la main. Mon moteur étant asservi à une vitesse que j'ai calculée pour fonctionner avec mon comparateur à 9600 baud et le codeur à 1000 pptr (environ 10 tr/min, et je fonctionne en réalité à moins de 6 tr/min), je n'ai normalement plus de risque de blocage.
Pour mettre le traitement de l'interruption dans la boucle loop, je n'ai rien contre, mais j'ai du mal à voir une différence (si tu peux m'expliquer, je le ferais sans soucis ^^)

Pour mettre le traitement de l'interruption dans la boucle loop, je n'ai rien contre, mais j'ai du mal à voir une différence (si tu peux m'expliquer, je le ferais sans soucis ^^)

Comme je l'ai indiqué quand tu es dans une routine d'interruption, toutes les autres interruptions sont masquées (timers, UART)
Donc par exemple si tu restes plus de 1ms dans ta routine d'interruption, la fonction millis() va commencer à déconner car elle va rater des interruptions timer.

De même l'émission sur l'UART vers le PC est effectuée sous interruptions. Quand tu fait un Serial.print( ... ); les octets sont mis dans un tampon. S'il y a suffisamment de place, la fonction rend la main au programme dès que les données sont copiées. Dès que le caractère précédant a été envoyé sur la liaison série, une interruption se produit et la routine d'interruption viens lire le prochain caractère en attente dans le tampon pour l'écrire dans l'UART, ect ... Si au moment du Serial.print(...) le tampon est plein, la fonction attaned qu'il se vide (sous interruption) pour pouvoir copier la suite du message.
Si tu est déjà sous interruption, la liaison série est bloquée, le tampon ne se vide pas et Serial.print() reste bloqué indéfiniment.

C'est pour cela qu'on évite de rester trop longtemps en interruption.

De même, puisque tu utilise une horloge (pin clk) pour lire tes données séries, tu pourrais utiliser envoyer clk sur une autre pin d'interruption et faire la désérialisation entrante bit par bit sous interruption. En utilisant si nécessaire des buffers multiples, tu peux ainsi traiter un message pendant que tu reçoit le suivant. C'est de l'entrelacement, début du multitâche.

Le comparateur fonctionne en 9600 baud mais je trouve cette solution software de gestion de l'interface série très fiable (bien qu'assez complexe), donc je ne souhaite pas repasser sur les pins TX et RX de la carte.

De toute façon vu ton code, c'est une liaison synchrone de 13 x 4 bits donc ne marche pas sur les pins TX/RX qui sont une UART (série asynchrone).
Peut être que çà pourrait marcher avec l'interface SPI si on sait la configurer esclave. Jamais essayé.

Donc à 9600 baud, tu restes au moins 5,4 ms dans ta routine d'interruption. Donc ton timer millis() ne marche plus!

Bref en gros, essentiellement tu monopolises ton CPU a ne rien faire qu'attendre que clk bouge. C'est du gaspillage :wink:

Coté mémoire, tu as une Mega2560 apparemment ?
Donc 8KO de RAM maxi
Surveille ta conso mémoire avec ce qui expliqué dans cet article : Arduino Playground - AvailableMemory

Bonjour,

je te conseille d'utiliser un compteur hardware pour ton codeur, et d'envoyer sur le port série des couples de données position/hauteur

Si tu rate des top au moins tu ne bloque pas ton programme.

Au final tu devra de toutes façons faire plusieurs tours pour avoir assez de points et faire une moyenne et un tri des point erronés, etc.

Pourquoi parlez vous d'utiliser un timer pour compter ?
Le code donné par Ervann ne comporte pas de comptage.

Il s'agit de récupérer une information sur une liaison série.
Cette information semble être un nombre BCD de 13 digits.
Il en récupère une partie, qu'il convertit en flottant pour ensuite l'envoyer sur la liaison série.

Ervann, Je vois pas a quoi ca sert de convertir la chaine de caractères en entier puis en flottant pour ensuite l'envoyer au PC.
Tu ferais mieux de laisser le PC faire le sale boulot et transmettre directement les données reçues.

Ervann:
Barbudor, je suis d'accord pour le risque de blocage, auquel j'ai déjà été confronté, mais seulement lorsque la fréquence des impulsions données par le codeur (donc la vitesse de rotation) était trop élevée, lorsque je manipulais le codeur à la main. Mon moteur étant asservi à une vitesse que j'ai calculée pour fonctionner avec mon comparateur à 9600 baud et le codeur à 1000 pptr (environ 10 tr/min, et je fonctionne en réalité à moins de 6 tr/min), je n'ai normalement plus de risque de blocage.

Bonsoir
comme evoqué par barbudor, en l’état il manque de la sécurité d’acquisition
à mon sens , il manque déjà une reference d'index (1 top par tour) = savoir et vérifier que les 1000 mesures faites correspondent bien à un tour et qu'il n'y a pas eu de loupé/manque.

certains codeur incrémentaux commerciaux dispose par construction d'une voie index , sinon comme je suppose que c'est pour de l'utilisation "en condition labo/recherche" , ajouter un "index electronique" n'est peut être pas tres difficile (l'important est d'avoir un top d'index par tour, il est peu important de savoir sous quel angle relatif il se produit) .

Oui, j'ai une Mega 2560 Rev3.

Bref en gros, essentiellement tu monopolises ton CPU a ne rien faire qu'attendre que clk bouge. C'est du gaspillage

Ok, je passerai un maximum d'instructions dans le loop().

Par contre, je ne me sens pas capable, seul, de faire la désérialisation dont tu parles en utilisant uniquement clk pour les interruptions. Ce code est une adaptation d'un code similaire trouvé sur internet pour l'acquisition par ce comparateur avec un autre microcontroleur, donc je comprends comment il marche, mais je n'ai aucune idée de pourquoi il a été fait comme ça.

il manque déjà une reference d'index (1 top par tour) = savoir et vérifier que les 1000 mesures faites correspondent bien à un tour et qu'il n'y a pas eu de loupé/manque.

Oui mon codeur a une voie d'index, mais je ne peux pas vraiment l'utiliser à moins de faire plusieurs tours consécutifs (pas sûr que je puisse le faire, ça dépend de mon maitre de stage :D). On peut dire que je travaille plutôt en condition de "prototypage", mais ce prototype fini sera celui utilisé ...

Voilà mon code légèrement modifié ... Mais je n'arrive même plus à lancer le moteur par le cmdByte, ne serait-ce qu'en passant par le moniteur série de l'IDE arduino.

int req = 13; //mic REQ line goes to pin 5 through q1 (arduino high pulls request line low)
int dat = 12; //mic Data line goes to pin 2
int clk = 11; //mic Clock line goes to pin 3
int cpt = 0; // counter for revs
int INTVR = 52; // Internal potentiometer
int ALARM_RESET = 50;
int RUN = 48;
int START = 46;
volatile int i = 0; int j = 0; int k = 0;
volatile boolean go = false;

float mm;

int cmdByte;
byte mydata[14];

void setup()
{
  pinMode(INTVR, OUTPUT);
  pinMode(ALARM_RESET, OUTPUT);
  pinMode(RUN, OUTPUT);
  pinMode(START, OUTPUT);
  digitalWrite(48, HIGH);
  Serial.begin(19200);
  pinMode(req, OUTPUT);
  pinMode(clk, INPUT);
  pinMode(dat, INPUT);
  attachInterrupt(0, pulse, RISING);
  digitalWrite(clk, HIGH); // enable internal pull ups
  digitalWrite(dat, HIGH); // enable internal pull ups
  digitalWrite(req, LOW); // set request at high
}

void loop()
{
  if ( go )
  {
    go = false;
    cpt = cpt + 1;

    long num;  // data treatment
    char buf[9];
  
    for(int lp=0;lp<6;lp++)
      buf[lp]=mydata[lp+5]+'0';
    
    buf[6]=0;
    num=atol(buf);
  
    mm = (float)num/100;
  
    if (mydata[4] < 1)
      Serial.print("+");
    else
      Serial.print("-");
     
     Serial.println(mm);
     Serial.println(cpt);
  
     digitalWrite(req,LOW); // stops set request
  }
}

void pulse()
{
  digitalWrite(req, HIGH); // generate set request
  
  for (i = 0; i < 13; i++) {
    k = 0;
    for (j = 0; j < 4; j++) {
      while(digitalRead(clk) == LOW) { } // hold until clock is high
      while(digitalRead(clk) == HIGH) { } // hold until clock is low
      bitWrite(k, j, (digitalRead(dat))); // read data bits, and reverse order
    }

    mydata[i] = k; // data received into this array
  }
}

void serialEvent()
{
  cmdByte = Serial.read(); // receive command from USB interface
  
  if (cmdByte > 48){
    digitalWrite(RUN, LOW);
  }else{
    digitalWrite(RUN, HIGH);
  }
}

Tu aurais pas oublié go = true; quelque part ? :wink:

Ervann:

il manque déjà une reference d'index (1 top par tour) = savoir et vérifier que les 1000 mesures faites correspondent bien à un tour et qu'il n'y a pas eu de loupé/manque.

Oui mon codeur a une voie d'index, mais je ne peux pas vraiment l'utiliser à moins de faire plusieurs tours consécutifs (pas sûr que je puisse le faire, ça dépend de mon maitre de stage :D). On peut dire que je travaille plutôt en condition de "prototypage", mais ce prototype fini sera celui utilisé ...

Bonjour
non,non ! :grin:
il ne s'agit pas de faire plusieurs tours consécutifs, mais seulement de t'assurer que tu a fait une rotation complète ET donc que cette rotation entre 2 top d'index (start/stop d'acquisition) te renvoie bien 1000 valeurs pour exploitation.
si tu a moins de 1000 valeurs entre 2 top , c'est que tu a de la perte d'info (chaine d'acquisition pas assez rapide) et par consequence ton profil acquis n'est pas un reflet exploitable de l'element mecanique (la came) .

Si merci Barbudor !

Oui, Artouste ça serait cool de pouvoir vérifier qu'il y a bien eu 1000 pts relevés mais si l'index de mon codeur me donne un impulsion au milieu de mon acquis (après un quart de tour, ou la moitié), il faudra que je continue jusqu'à la prochaine. Et je ne controle pas le point de départ car c'est l'opérateur qui placera l'AAC (arbre à cames) sur le mandrin et qui mettra le zéro sur le dos de came (donc position angulaire inconnue avant d'avoir serré l'AAC dans le mandrin).

Désolé, mais j'ai toujours mon problème de lancement d'acquis par le cmdByte ... Je ne comprends pas pourquoi je n'arrive pas à lancer le moteur en envoyant le char "1" ou un char supérieur ("1" = 048) ...

Ervann:
Oui, Artouste ça serait cool de pouvoir vérifier qu'il y a bien eu 1000 pts relevés mais si l'index de mon codeur me donne un impulsion au milieu de mon acquis (après un quart de tour, ou la moitié), il faudra que je continue jusqu'à la prochaine. Et je ne controle pas le point de départ car c'est l'opérateur qui placera l'AAC (arbre à cames) sur le mandrin et qui mettra le zéro sur le dos de came (donc position angulaire inconnue avant d'avoir serré l'AAC dans le mandrin).

ça se resume facilement par :
pas de début d'acquisition sans top et pas de fin d'acquisition sans top :grin:
au pire et en restant sur un seul sens de rotation pour "mesure", il y aura inévitablement moins d'un tour pour "toper" le départ entre les différents positionnements initiaux .

Invite donc ton maitre de stage ici :grin:

Je suis tout à fait d'accord que c'est une sécurité qu'il faut prendre mais pour l'instant, je dois le faire fonctionner, je verrais ça une fois que j'aurais eu ma première acquis (même mauvaise) car j'aimerais pouvoir montrer un résultat assez rapidement
En gros, j'aimerais juste pouvoir lancer le moteur grâce au PC (il suffit de pull le pin 48 à la masse => digitalWrite(RUN, LOW)) avec le cmdByte.

Serait-ce une bonne idée de remplacer le SerialEvent() par un if (Serial.available()) dans la boucle loop ???

Je rajoute un schéma du montage (désolé pour la qualité il a été fait à la va vite) ...

Ervann:
Serait-ce une bonne idée de remplacer le SerialEvent() par un if (Serial.available()) dans la boucle loop ???

Ca ne changera rien.
SerialEvent fait exactement la même chose :

int main()
{
  setup();
  while( 1 )
  {
    if ( Serial.available() )
      SerialEvent();
    loop()
  }
}

Si je comprend bien :

  • l'encodeur génère 1000 'pulse' par tour
  • sur chaque interruption 'pulse', tu envoie une 'req'uète de lecture au comparateur
  • le comparateur te renvoie la valeur de la mesure sur liaison synchrone clk+data

Tu as un lien vers la doc du comparateur avec la description du protocole ?

Merci

Tu as bien compris. Mais je n'ai pas de problème avec ça ... De plus, je ne connais pas le protocole mais j'ai trouvé ce code qui semble quasi-universel pour les transmissions synchrones.