« Comparateur Numérique » : différence entre les versions

De knowledge
Aller à la navigation Aller à la recherche
m (cleanup)
 
(6 versions intermédiaires par le même utilisateur non affichées)
Ligne 159 : Ligne 159 :
[[Fichier:Comparateur-doc.png|sans_cadre|440x440px]]  
[[Fichier:Comparateur-doc.png|sans_cadre|440x440px]]  


Déjà "Porta A" je ne comprends pas bien ce que ça veut dire mais '''RS232 c'est archi faux'''. Les signal est pas du tout compatible UART et pas non plus en niveaux -12/+12V (ni 0/5V).
Déjà "Porta A" je ne comprends pas bien ce que ça veut dire mais '''RS232 c'est archi faux'''. Le signal n'est pas du tout compatible UART et pas non plus en niveaux -12/+12V du RS 232 (ni 0/5V).
 
Si ça ressemble a quelque chose de standard ce serait plutôt de l'I2C.


En revanche "Porta B" c'est bien un emplacement pour une pile LR44 !
En revanche "Porta B" c'est bien un emplacement pour une pile LR44 !
Ligne 166 : Ligne 168 :


=== Les niveaux ===
=== Les niveaux ===
On a vu que les signaux si=ont entre 0 et1.6 V max (si le pile est neuve mais à 1.2V le comparateur marche encore).
On a vu que le signal varie entre 0 et1.6 V max (si le pile est neuve mais à 1.2V le comparateur marche encore).


Pour un microcontrôleur classique (ex [[ESP32]]) on a les valeurs limites haut bas suivantes:
Pour un microcontrôleur classique (ex [[ESP32]]) on a les valeurs limites haut bas suivantes:
Ligne 176 : Ligne 178 :
[[Fichier:SIGNAL COMARATEUR VS ESP32.png|sans_cadre|443x443px]]  
[[Fichier:SIGNAL COMARATEUR VS ESP32.png|sans_cadre|443x443px]]  


On voit bien que le niveau "haut" du signal reste bien en dessous du minimum du niveau bas de l'ESP 32. (1.6 < 2.4).
On voit bien que le niveau "haut" du signal du comparateur reste bien en dessous du minimum du niveau bas de l'ESP 32. (1.6 < 2.4).


Il faut donc amplifier ce signal. Certains utiliseraient des transistor MOSFET mais, je maitrise mal le sujet, je n'en ai pas en stock. En revanche j'ai des [[Le transistor bipolaire|transistors bipolaires]] et c'est assez facile a gérer.
Il faut donc amplifier ce signal. Certains utiliseraient des transistor MOSFET mais, je maitrise mal le sujet, je n'en ai pas en stock. En revanche j'ai des [[Le transistor bipolaire|transistors bipolaires]] et c'est assez facile a gérer.
Ligne 233 : Ligne 235 :
[[Fichier:Logic diagram.png|sans_cadre|534x534px]]
[[Fichier:Logic diagram.png|sans_cadre|534x534px]]


Logic 1 = clock inversée par un transistor NPN
Logic 1 = clock inversée par un [[Le transistor bipolaire|transistor NPN]]


Logic 0 = data inversée par un transistor NPN
Logic 0 = data inversée par un transistor NPN
Ligne 371 : Ligne 373 :
''Les constantes''
''Les constantes''


* Lignes 5 à 10 définitions des broches GPIO
* Lignes 10 à 13 définitions des broches GPIO
* Ligne 14 on défini REVERSE si le signal est inversé en entrée ce qui est la cas avec notre montage à transistors NPN.  
* Ligne 15 on défini REVERSE si le signal est inversé en entrée ce qui est la cas avec notre montage à transistors NPN.


''Les variables''
''Les variables''


* Lignes 18 à 25 des entiers non signés sur 32 bits qui servent a mémoriser les "timestamps en microsecondes" des derniers événements (rise, fall, change) et la durée des états HAUTS BAS et la dernière période.
* Lignes 17 à 22 des entiers non signés sur 32 bits qui servent a mémoriser les "timestamps en microsecondes" des derniers événements (''RISE'' et  ''FALL'') et la durée des états ''HAUTS'' BAS.


{| class="wikitable"
{| class="wikitable"
|+
|+
|[[Fichier:Attention.png|sans_cadre|47x47px]]
|[[Fichier:Attention.png|sans_cadre|47x47px]]
|Attention dans ce code on ne gère pas le cas ou la valeur du timestamp en microsecondes va repasser à zéro. Apres 4 294 967 296 µs soit 1h11 notre programme va planter!
|Attention dans ce code on ne gère pas le cas ou la valeur du timestamp en microsecondes va repasser à zéro.  
Apres 4 294 967 296 µs soit 1h11 notre programme va planter! (d'où le commentaire en début de fichier)
|}
|}


* Ligne 29 et 30 le cadre de décodage (buffer et pointeur)
* Ligne 24 et 25 le cadre de décodage (buffer et pointeur)
* Ligne 31 la variable décodée (double buffering)
* Ligne 26 la variable décodée (double buffering)
* Ligne 33 l'état de la ligne à un instant donné.
* Ligne 28 l'état de la ligne à un instant donné.


''Le code''
''Le code''


* Lignes 35 à 49 gestion de la lecture de la valeur des deux lignes. Prends en compte la constante REVERSE (gestion du transistor NPN)
* Lignes 30 à 44 gestion de la lecture de la valeur des deux lignes. Prends en compte la constante REVERSE (gestion du transistor NPN)
* '''Lignes 51 à 66 : C'est l'une des deux fonctions primordiales.''' C'est une interruption matérielle appelée à chaque changement d'état de CLK.  
* '''Lignes 46 à 61 : C'est l'une des deux fonctions primordiales.''' C'est une interruption appelée à chaque front montant (le NPN est géré).  
** Elle "remplis" le buffer bit après bit à chaque front montant du signal du comparateur (attention NPN)
** Elle "remplis" le buffer bit après bit à chaque front montant du signal du comparateur (attention NPN)
** Lorsque une "frame" est pleine on la transfère dans le buffer de lecture
** Lorsque une "frame" est pleine on la transfère dans le buffer de lecture
** Accessoirement (lignes 64 et 65) on mets a disposition les signaux décodés sur des deux GPIO
** Accessoirement (lignes 59 et 61) on mets à disposition les signaux décodés sur des deux GPIO
* Lignes 63 à 66 : Gestion des fronts descendants (juste pour calculer la longueur de l'état haut)
* Lignes 69 à 76 : C'est l'interruption matérielle. Elle ne sert qu'a tester l'état de la clock (gestion du REVERSE) et a appeler la fonction rise ou fall.
* Ligne 78 à 98 : C'est la seconde fonction importante. On décode la valeur rangée dans le buffer de lecture.
** Les bits 0 à 11 représentent la valeur
** Le bit 20 le signe (si = 1 c'est un nombre négatif)
** Le bit 23 représente l'unité ("mm" ou "inches")
** Ligne 90 on passe en flotant et on ajuste l'échelle en fonction de l'unité lignes 90 à 97.
* La fonction setup (lignes 100 à 121) n'a rien de grandiose. On initialise les GPIO. La seule chose est le '''while''' de la ligne 115 qui attends un état haut > 100ms pour commencer la mesure.
* Les lignes 123 à 126 (le loop) est un exemple d'affichage de la valeur mesurée a intervalle régulier (asynchrone par rapport à la mesure)
La sortie UART de l'ESP 32 nous donne:<syntaxhighlight lang="text">
8.61
10.65
14.06
14.06
10.83
10.83
8.64
8.64
7.44
7.44
6.19
4.23
4.23
0.00
0.00
0.00
 
</syntaxhighlight>Qui sont les valeurs en mm mesurées (identique a celle affichées sur l'écran LCD du comparateur). Je n'ai pas ajouté l'unité pour pouvoir utiliser le "plotter" de l'IDE Arduino.
 
[[Fichier:Arduino IDE plotter.png|sans_cadre|665x665px]]
 
Nous avons donc une méthode pour connaitre la valeur mesurées de façon logicielle.
 
On pourra par exemple brancher notre montage sur l'entrée série de l'ordinateur de l'atelier ou modifier le programme ci dessus pour mettre à disposition la valeur mesurée au travers d'un web service ou un message [[MQTT]] sur le réseau.
 
Il est amusant de constater que, même éteint, le comparateur continue à envoyer la valeur sur ses sorties numérique mais surtout de la mettre à jour. Seuls les  boutons "Unités" et "Zéro" arrêtent de fonctionner.


== Les étapes suivantes... ==
== Les étapes suivantes... ==
Maintenant il faut écrire un programme pour un microcontrôleur quelconque (Arduino, ESP32... je ne sais pas encore) pour décoder ce signal et l'envoyer sur un écran et surtout sur l'UART.
Il faudra usiner un connecteur "maison" pour pas être obligé de démonter un comparateur à chaque fois.
 
Ensuite il faudra usiner un connecteur "maison" pour pas être obligé de démonter un comparateur à chaque fois.


Et... le top du top, écrire une programme pour piloter une [[CNC 3018]] et sortie un fichier "heigth" pour corriger les erreurs de planéité.
Et... le top du top, écrire une programme pour piloter une [[CNC 3018]] et sortir un fichier "heigth" pour corriger les erreurs de planéité.

Version actuelle datée du 7 octobre 2024 à 15:59

Analyse hardware

Comparateur numérique sans marque

J'ai acheté un comparateur numérique sur Amazon. Il est donné pour avoir une sortie RS232.

En revanche la connectique est "exotique" (un trou dans le boitier et 4 traces sur le PCB de l'appareil) et aucune explication dans la doc. La majorité des vendeurs disent que le "kit connectique" est disponible séparément mais aucun de mes messages aux distributeurs ni question sur le site Amazon ne m'a donné de réponses.

Il n'y a pas de marque sur ce modèle donc pas de fabricant à contacter. Alors je sors mon oscilloscope, mon multimètre et mes pointes de touches maisons pour comprendre de quoi il en retourne "à la main".

Si on ouvre le cache du connecteur (le petit, le grand c'est celui de la pile) on voit qu'on a accès directement au PCB de la carte et que 4 conducteurs sont présents.

Connecteur comparateur.png

On nommera ces broches de 1 à 4 de gauche à droite. Les couleurs donnent déjà un indication de ce que j'ai déduit de mes mesures.

A priori la broche 4 est la masse et la 1 est la tension d'alim de la pile (1,17V avec une pile... pas toute neuve mais 1.6 avec une pile neuve).

En 2 et en 3 on voit passer des données.

En 2 on voit passer un signal qui ne ressemble pas à un signal UART!

Comparateur broche 3.png

Mon "GND" était pas parfait mais ce ressemble a un message aussi et c'est moins régulier.

Définitivement, avec mes pointes de touches je n'arrive à rien de propre. Je décide d'ouvrir la bête. Je soude trois fils sur les broches 2, 3 et 4 et je rebranche mon oscilloscope.

Il faut être très prudent lors de cette opération. L'écran LCD est relié au circuit imprimé par un connecteur qui est un sandwich de couches conductrices et isolantes en plastique souple. C'est impossible à remettre en place correctement. Au bout de 50 essais j'ai un affichage "a peu près" correct. Faut se mettre bien en face!. Quand j'aurais terminé je penses que j'en achèterais un neuf!

Analyse du signal de sortie

Voie 1 (rouge) sur 3

Voie 2 (jaune) sur 2

Les deux masses à 4

On visualise:

Comparateur-messages-multiples.png

Je n'ai pas mis d'échelle mais mes mesures donnent :

  • Un message toutes les 110 ms
  • Le message lui même dure 8ms

Regardons de près le signal pour une mesure à 0mm:

Comparateur-message-zero mm.png

Intuitivement :

  • La voie 1 (broche 3) semble être un horloge (elle ne change jamais quel que soit la mesure)
  • La voie 2 (broche 2) semble être la mesure dans un format étrange.

Après une après midi de creusage de tête j'ai compris plusieurs choses:

  1. Le signal de la voie 2 est un signal logique dont il faut lire l'état à chaque front montant de l'horloge.
  2. Le message contient 6 groupes de 4 bits. (24 bits)
  3. Le bit 23 indique l'unité (0="mm" et 1="in")
  4. Le bit 20 c'est le signe (0="+" et 1="-")
  5. Seul les 3 premiers quartets (12 premiers bits) semblent significatifs les 2 suivants sont toujours à zéro
  6. Pour le reste la seule chose que je vois c'est que le bit 0 est l'unité car il est à 0 pour les nombres paire et à 1 pour les impairs.

Décodage en mode métrique (unité ="mm")

Signal décodé Mesure affichée Valeur binaire

12 premiers bits

Valeur décimale

bit0 = lsb

0000 0000 0000 0000 0000 0000 0mm 000000000000 0
0100 0000 0000 0000 0000 0000 0,02mm 010000000000 2
0111 0100 1000 0000 0000 0000 3.02mm 011101001000 302
0101 0111 1100 0000 0000 0000 10,02mm 010101111100 1002
1111 0110 1000 0000 0000 0000 3,67mm 111101101000 367
0111 1110 1010 0000 0000 0000 14,06mm 011111101010 1406
1010 0100 0100 0000 0000 1000 -05,59mm 101001000100 549
1110 0101 0010 0000 0000 1000 -11,91mm 111001010010 1191

On voit rapidement que la valeur binaire correspond à la mesure *100. On à le nombre de centièmes de mm.

On est donc précis à 0.01 mm près soit 10µm.

Décodage en mode impérial (US ?)

Le décodage est acquis je me focalise sur les correspondance entre l'entier transmis et la valeur affichée.

Mesure affichée Valeur binaire

12 premiers bits

0 in 0
0.1445 in 289
0.0025 in 5
0.1715 in 343
0.277 in 554
0.0245 in 49
0.267 in 534

C'est moins évidant (c'est toujours bizarre avec les unités impériales).

La représentation "XY" nous donne l'équation : mesure=valeur*0,0005

Comparateur-regression-pouce.png

En gros on divise par 2000. on a le nombre de 1/2000 de pouces de la mesure. Quand je vous disais que les anglais étaient bizarres dans leurs unités.

On est précis à 1/2000 de pouces soit 25,4/2000 soit 0.0127 mm ou 12.7 µm. Il vaut mieux travailler en mm car les unités impériales semblent être des interpolations!

Conclusion

Dans la doc sur Amazon on a :

Comparateur-doc.png

Déjà "Porta A" je ne comprends pas bien ce que ça veut dire mais RS232 c'est archi faux. Le signal n'est pas du tout compatible UART et pas non plus en niveaux -12/+12V du RS 232 (ni 0/5V).

Si ça ressemble a quelque chose de standard ce serait plutôt de l'I2C.

En revanche "Porta B" c'est bien un emplacement pour une pile LR44 !

Le hardware nécessaire

Les niveaux

On a vu que le signal varie entre 0 et1.6 V max (si le pile est neuve mais à 1.2V le comparateur marche encore).

Pour un microcontrôleur classique (ex ESP32) on a les valeurs limites haut bas suivantes:

ESP32LEVELS.png

Si on compare ça avec le signal issue du comparateur on à

SIGNAL COMARATEUR VS ESP32.png

On voit bien que le niveau "haut" du signal du comparateur reste bien en dessous du minimum du niveau bas de l'ESP 32. (1.6 < 2.4).

Il faut donc amplifier ce signal. Certains utiliseraient des transistor MOSFET mais, je maitrise mal le sujet, je n'en ai pas en stock. En revanche j'ai des transistors bipolaires et c'est assez facile a gérer.

L'électronique

J'ai fait le petit schéma :

Schema Interface Comparateur.png

Riens de complexe, deux transistors NPN montés utilisé en mode saturé/bloqué.

On fait un PCB:

PCB interface compatateur.png

J'ai fais des grosses traces et des pads éloignés car je veux utiliser ma CNC pour faire le travail.

Le PCB termine.png

Le PCB usiné (il faudrait que j'affine mes paramètres de coupe car c'est un peu brutal)

Avec les composants.png

Avec les composants.

Les mesures

L'interface comparateur en test.png

Si on compare l'entrée à la sortie

Interface comparateur entrée-sortie.png

Le signal d'entrée (0-1,6V) est bien transformé en signal entre 0 et 3.3V.

Attention.pngAttention cependant on a utilisé un transistor NPN le signal est inversé. Il faudra en tenir compte dans le logiciel!

Visualisation clock + data

En entrée

Entree .png

En sortie

clock-data out:

On a bien une mise à niveau et une inversion du signal.

Logiciel

J'ai choisi de développer une application simple pour ESP32 (avec l'IDE Arduino).

On à trois tâches à réaliser :

  1. Détecter le début d'une "frame" sur la "clock"
  2. Lire la valeur de la broche "data" pour chaque front montant de clock.
  3. Décodage des bits acquis en en données réelles.

Logic diagram.png

Logic 1 = clock inversée par un transistor NPN

Logic 0 = data inversée par un transistor NPN

Logic 2 = Décodage de la "frame"

Logic 3 = Lecture de la valeur "data" sur chaque front montant de la clock (le front descendant de la clock à travers le NPN)

// Analyse comparator signal
// processing in µs on uint32_t integer
// 4 294 967 296 µs
// 4 294.967296 sec
// 1:11:34 so after 1 hour needs to reboot
// Related to https://knowledge.pinon-hebert.fr/index.php/Comparateur_Num%C3%A9rique



const int clk = 32;
const int dat = 33;
const int frame_out = 22; /// frame detection
const int dat_out=21; // data decode

#define REVERSE     // Defined if input signal needs to be inverted (needed if level adaptation done with NPN)

// ANALYSE THE CLOCK SIGNAL
uint32_t event_fall;   // timestamp of the last falling edge
uint32_t time_low;    // duration of last low level (between falling and rising edge)

uint32_t event_rise;  // tlmestamp of the last rising edge
uint32_t time_high;   // duration of the last high levet (between rising and fallin edge)

int bit=-1;
uint8_t bitFrame[24];
uint8_t measure[24];

int state;

inline int getClkState(){ 
  #ifdef REVERSE
    return (!digitalRead(clk));
  #else
    return (digitalRead(clk));
  #endif
}

inline int getDatState(){ 
  #ifdef REVERSE
    return (!digitalRead(dat));
  #else
    return (digitalRead(dat));
  #endif
}

void IRAM_ATTR clk_rise(){
  state=HIGH;
  event_rise=micros();
  int value=getDatState();
  time_low=event_rise-event_fall;
  if (bit>=0){
    bitFrame[bit]=value;
    bit++;
    bit%=24;
  }
  if (bit==0){
    memcpy(measure,bitFrame,24);
  }
  digitalWrite(frame_out,(bit==0));
  digitalWrite(dat_out,value); 
}

void IRAM_ATTR clk_fall(){
  state=LOW;
  event_fall=micros();
  time_high=event_fall-event_rise;  
}

void IRAM_ATTR clk_CHANGE() {
  uint32_t ti=micros();
  if(getClkState()){
    return clk_rise();
  }else{
    return clk_fall();
  }
}

void printMeasure(){
  int i;
  // Décode mesured value
  int val=0;
  for (i=11; i>=0; i--){
    val<<=1;
    val+=measure[i];
  }
  if (measure[20]==HIGH){
    val=-val;
  }
  // convert regarding the system (metric vs US)
  float fval;
  if (measure[23]==HIGH){
    fval=float(val)/2000.0;
    Serial.println(fval,4);
  }else{
    fval=float(val)/100.0;
    Serial.println(fval,2);
  }
}

void setup() {
  
  Serial.begin(115200);
  pinMode(clk, INPUT_PULLUP);
  pinMode(dat,INPUT_PULLUP);
  pinMode(frame_out,OUTPUT);
  pinMode(dat_out,OUTPUT);
  digitalWrite(frame_out,LOW);
  digitalWrite(dat_out,HIGH);
  
  Serial.println("\nInit interuption");

  state=getClkState();
  attachInterrupt(clk,clk_CHANGE,CHANGE);
  Serial.println("Sync");
  while (time_high<100000){

  }
  bit=0;
  Serial.println(getClkState());
  Serial.println("Ready");
}

void loop() {
  delay(100);
  printMeasure();
}

Explication :

Les constantes

  • Lignes 10 à 13 définitions des broches GPIO
  • Ligne 15 on défini REVERSE si le signal est inversé en entrée ce qui est la cas avec notre montage à transistors NPN.

Les variables

  • Lignes 17 à 22 des entiers non signés sur 32 bits qui servent a mémoriser les "timestamps en microsecondes" des derniers événements (RISE et FALL) et la durée des états HAUTS BAS.
Attention.png Attention dans ce code on ne gère pas le cas ou la valeur du timestamp en microsecondes va repasser à zéro.

Apres 4 294 967 296 µs soit 1h11 notre programme va planter! (d'où le commentaire en début de fichier)

  • Ligne 24 et 25 le cadre de décodage (buffer et pointeur)
  • Ligne 26 la variable décodée (double buffering)
  • Ligne 28 l'état de la ligne à un instant donné.

Le code

  • Lignes 30 à 44 gestion de la lecture de la valeur des deux lignes. Prends en compte la constante REVERSE (gestion du transistor NPN)
  • Lignes 46 à 61 : C'est l'une des deux fonctions primordiales. C'est une interruption appelée à chaque front montant (le NPN est géré).
    • Elle "remplis" le buffer bit après bit à chaque front montant du signal du comparateur (attention NPN)
    • Lorsque une "frame" est pleine on la transfère dans le buffer de lecture
    • Accessoirement (lignes 59 et 61) on mets à disposition les signaux décodés sur des deux GPIO
  • Lignes 63 à 66 : Gestion des fronts descendants (juste pour calculer la longueur de l'état haut)
  • Lignes 69 à 76 : C'est l'interruption matérielle. Elle ne sert qu'a tester l'état de la clock (gestion du REVERSE) et a appeler la fonction rise ou fall.
  • Ligne 78 à 98 : C'est la seconde fonction importante. On décode la valeur rangée dans le buffer de lecture.
    • Les bits 0 à 11 représentent la valeur
    • Le bit 20 le signe (si = 1 c'est un nombre négatif)
    • Le bit 23 représente l'unité ("mm" ou "inches")
    • Ligne 90 on passe en flotant et on ajuste l'échelle en fonction de l'unité lignes 90 à 97.
  • La fonction setup (lignes 100 à 121) n'a rien de grandiose. On initialise les GPIO. La seule chose est le while de la ligne 115 qui attends un état haut > 100ms pour commencer la mesure.
  • Les lignes 123 à 126 (le loop) est un exemple d'affichage de la valeur mesurée a intervalle régulier (asynchrone par rapport à la mesure)

La sortie UART de l'ESP 32 nous donne:

8.61
10.65
14.06
14.06
10.83
10.83
8.64
8.64
7.44
7.44
6.19
4.23
4.23
0.00
0.00
0.00

Qui sont les valeurs en mm mesurées (identique a celle affichées sur l'écran LCD du comparateur). Je n'ai pas ajouté l'unité pour pouvoir utiliser le "plotter" de l'IDE Arduino.

Arduino IDE plotter.png

Nous avons donc une méthode pour connaitre la valeur mesurées de façon logicielle.

On pourra par exemple brancher notre montage sur l'entrée série de l'ordinateur de l'atelier ou modifier le programme ci dessus pour mettre à disposition la valeur mesurée au travers d'un web service ou un message MQTT sur le réseau.

Il est amusant de constater que, même éteint, le comparateur continue à envoyer la valeur sur ses sorties numérique mais surtout de la mettre à jour. Seuls les boutons "Unités" et "Zéro" arrêtent de fonctionner.

Les étapes suivantes...

Il faudra usiner un connecteur "maison" pour pas être obligé de démonter un comparateur à chaque fois.

Et... le top du top, écrire une programme pour piloter une CNC 3018 et sortir un fichier "heigth" pour corriger les erreurs de planéité.