« Comparateur Numérique » : différence entre les versions
mAucun résumé des modifications |
m (→Conclusion) |
||
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'''. | 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). | ||
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 ! |
Version du 26 septembre 2024 à 12:23
Analyse hardware
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.
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!
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:
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:
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:
- Le signal de la voie 2 est un signal logique dont il faut lire l'état à chaque front montant de l'horloge.
- Le message contient 6 groupes de 4 bits. (24 bits)
- Le bit 23 indique l'unité (0="mm" et 1="in")
- Le bit 20 c'est le signe (0="+" et 1="-")
- Seul les 3 premiers quartets (12 premiers bits) semblent significatifs les 2 suivants sont toujours à zéro
- 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
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 :
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).
En revanche "Porta B" c'est bien un emplacement pour une pile LR44 !
Le hardware nécessaire
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).
Pour un microcontrôleur classique (ex ESP32) on a les valeurs limites haut bas suivantes:
Si on compare ça avec le signal issue du comparateur on à
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).
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 :
Riens de complexe, deux transistors NPN montés utilisé en mode saturé/bloqué.
On fait un PCB:
J'ai fais des grosses traces et des pads éloignés car je veux utiliser ma CNC pour faire le travail.
Le PCB usiné (il faudrait que j'affine mes paramètres de coupe car c'est un peu brutal)
Avec les composants.
Les mesures
Si on compare l'entrée à la sortie
Le signal d'entrée (0-1,6V) est bien transformé en signal entre 0 et 3.3V.
Attention 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
En sortie
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 :
- Détecter le début d'une "frame" sur la "clock"
- Lire la valeur de la broche "data" pour chaque front montant de clock.
- Décodage des bits acquis en en données réelles.
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.
- 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.
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é.