Bonjour,
Sur mon tour Optimum, j’ai affichage DRO 3 axes qui utilise des règles digital qui on des signaux analogiques en forme de sinus.
J’aimerais récupérer un comptage de ces signaux avec un ESP32.
Malheureusement, je ne trouve que des exemples pour des règles à signaux carré (TTL) !
Extrait de mode d’emplois de l’afficheur:
Affichage_DRO_notice1 001.pdf (449.6 KB)
Explication codeur sinusoïdal que j’ai trouvé :Voir à 28:30
J’ai mesurer au multimètre : entre 0° et 0V tension entre ~2.5v et ~3.4v ; entre 0° et 180° stable à 0.015v.
J'ai ensuite testé le code si-dessous avec un Nano et SérialPlot:
EDIT: Code mis à jour le 04.02.24
// Pour Arduino Nano:
/////////////////////
#define Version V1
// Change: - new brochage (pin) pour isoler le boutton; - Ajout serialPrint compteur et distance; -Add dévérouillage du Setup par boutton
/* Petit code pour lire les règles digitals Optimum sinusoïdale 1Vpp (Utilisable uniquement à très faible vitesse)
********************************************************************
* Simule un trigger de shmitt sur les canaux A = 0° et B = 90°
* Compte en quadrature les signaux ainsi transformé.
* - printGraph() est paramètrée pour une utilisation avec le logiciel SerialPlot (séparateur virgule)
* - Pour imprimer le graphique sur SerialPlot déconecter la pin "pinMode1" (pull-up = Vcc)
* - Pour imprimer le compteur sur le moniteur série relier la pin "pinMode1" à GND
*
* connection à la règle:
* A6 à la pin 0°
* A7 à la pin 90°
* GND à la pin 0V
* - Ajouter un switch entre GND et A0 de l'Arduino
******************
* MODE D'EMPLOIS *
******************
* IMPORTANT : il faut que la règle soit allimenté avant l'Arduino, si ce n'est pas le cas faire un RESET de l'Arduino pour qu'il démarre avant les bonnes tension minU et maxU.
*
* Au lancement du programme ou après un reset; quand la led de la carte est allumée presser bièvement sur le boutton pour valider le Setup() et lancer le programme
- ceci sert de témoins. Si la led s'allume pendant une mesure (en dehors du calibrage), c'est que l'Arduino à "Reseté".
*
* Au premier démarrage, il faut initialiser l'Eeprom avec un calibrage.
*
* Calibrage : Pressé le switch (et le garder pressé pendant tous le calibrage) et déplacer l'axe pour étalonner les valeurs min et max fournie par la règle (attendre au minimum que la led s'allume = 2.5 secondes)
- Après plus de 2.5 secondes, quand vous lâchez le boutton, les nouvelles valeurs sont écrite dans l'Eeprom et aussi utilisées dans le programme. (Pas de retour en arrière possible).
* en suite une courte pression (< 2.5s) sur le switch remet le compteur à zéro // Longue pression (> 2.5s) refait une callibration
******************************************************* */
// A définire selon votre utilisation:
const int pinA = A6; // Broche analogique pour la mesure de tension A = 0° de la règle digitale
const int pinB = A7; // Broche analogique pour la mesure de tension B = 90° de la règle
const int pinSwitch = A0; // Broche de l'intérrupteur (pour calibration ou remise à zéro du compteur)
const int pinMode1 = 12; // Broche pour choisir le mode de fonctionnement "printGraph()" OU "printCompteur()"
const int pinLED = 13; // LED de la carte Arduino "LED Bulting"
const int hysteresis = int(0.1 * 1024.0 / 5.0); // hystérésis de 0.1 vlot (Remplace le trigger de shmitt)
const int timeCalbr = 2500; // Durée minimum pour une calibration valide
const int umPoint = 5; // Nombre de microns par point
#include <EEPROM.h>
const int hystHalf = (hysteresis > 1) ? hysteresis / 2 : 1;
bool chanelA = false; // Signal carré du canal A (signal numérique)
bool chanelB = false; // Signal carré du canal B (signal numérique)
bool lastA = false; // Variable pour remise en place de la position après remise à zéro du compteur
bool lastB = false; // Idem à [lastA]
int32_t compteur = 0; // Compteur bi-directionnel du nombre de pulses A-B
// Valeur réinitialisée dans le Setup(), puis dans calibriation()
int minU = 0; // Tension mim pour la sinus
int maxU = 1024; // Tension max pour la sinus
int tempMinU = minU; // Variable de comparaison temporaire pour la calibration
int tempMaxU = maxU; // Variable de comparaison temporaire pour la calibration
int topU = 510; // Tension au-delà de laquelle le canal passe à haut : High trigger voltage
int bottomU = 514; // Tension en-deçà de laquelle le canal passe à bas : Low trigger voltage
int valUa = topU; // Valeur lue du pinA (Sinus)
int valUb = topU; // Valeur lue du pinB (Cosinus)
float Ua = 2.5; // Tension lue au pinA (en volts)
float Ub = 2.5; // Tension lue au pinB (en volts)
bool valSw = true; // Dernier état connu de l'interrupteur
bool mode1Sw = true; // Mode d'utilisation des données sur port série
uint32_t timeStartCalibre = millis(); // Timer pour valider la calibration
void setup() {
Serial.begin(115200); // Initialisation de la communication série
pinMode(pinA, INPUT); // Déclaration de la broche A0 comme entrée analogique
pinMode(pinB, INPUT); // Déclaration de la broche A1 comme entrée analogique
pinMode(pinSwitch, INPUT_PULLUP); // Déclaration du switch
pinMode(pinMode1, INPUT_PULLUP); // Déclaration du pin
pinMode(pinLED, OUTPUT); // Déclare la broche 13 comme sortie (Led de l'arduino)
// Charger les valeurs de minU et maxU depuis l'EEPROM
minU = readEEPROM(713, 714);
maxU = readEEPROM(715, 716);
// Validation : vérifier si les valeurs lues sont valides
if (minU < 0 || minU > analogRead(pinA)) {
minU = analogRead(pinA);
}
if (maxU < analogRead(pinA) || maxU > 1024) {
maxU = analogRead(pinA);
}
topU = (maxU - minU) / 2 + minU + hystHalf; // Tension au-delà de laquelle le canal passe à haut : High trigger voltage
bottomU = (maxU - minU) / 2 + minU - hystHalf; // Tension en-deçà de laquelle le canal passe à bas : Low trigger voltage
//delay(800); // Remplacer par le code si-dessous:
{ // attendre un pression sur le boutton avant de démarrer le programme (ce qui permet d'initialiser le moniteur série par exemple)
digitalWrite(pinLED, HIGH); // Allume la LED
bool _start = false;
// Attendre que le bouton soit pressé avec une gestion de debounce
while (!_start) {
if (digitalRead(pinSwitch) == LOW) { // Si le bouton est pressé
delay(20); // Débounce
_start = digitalRead(pinSwitch) == LOW; // Vérifie si le bouton reste pressé après le délai
}
}
// Attendre que le bouton soit relâché
while (digitalRead(pinSwitch) == LOW) {} // On attend ici que le bouton soit relâché
delay(80); // Débounce
digitalWrite(pinLED, LOW); // Eteindre la LED à la fin du setup()
}
Serial.print("SETUP: min sinus = ");Serial.print(minU);Serial.print(" // max sinus = ");Serial.println(maxU);
// DEBUG :
// Serial.print(readEEPROM(713, 714));Serial.print(" || ");Serial.print(readEEPROM(715, 716));
// Serial.println();Serial.println("------");Serial.println();
// Réinitialisation des variable pour éviter une autocalibration au démarrage
valSw = (digitalRead(pinSwitch) == HIGH);
timeStartCalibre = millis();
}
void loop() {
if (digitalRead(pinMode1) == HIGH){mode1Sw = true;} else {mode1Sw = false;}
if ((digitalRead(pinSwitch) == HIGH) != valSw){
delay(20); // Debounce
valSw = (digitalRead(pinSwitch) == HIGH);
// Remettre au bonne endroit chanelA et chanelB
// Restauration des position d'avant la mise à zéro
if(valSw){ // Passe en mode comtage
chanelA = lastA;
chanelB = lastB;
if (millis() - timeStartCalibre > timeCalbr){ // n'enregistre les nouvelles valeurs dans l'Eeprom et le programme que si le calibrage à duré plus que "timeCalbr" 2.5 secondes
bool change = false;
if (minU != tempMinU || maxU != tempMaxU) change = true;
minU = tempMinU;
maxU = tempMaxU;
// Sauvegarde les nouvelles valeurs dans l'EEPROM
// change = updateEEPROM(713, 714, minU) || change;
// change = updateEEPROM(715, 716, maxU) || change;
bool Eepmin = updateEEPROM(713, 714, minU);
bool Eepmax = updateEEPROM(715, 716, maxU);
if (Eepmin || Eepmax) change = true;
// Adapte la valeur centrale est l'hystérésis haut et bas
if (change){
topU = (maxU - minU) / 2 + minU + hystHalf;
bottomU = (maxU - minU) / 2 + minU - hystHalf;
}
if (!mode1Sw){
Serial.print("- Nouveau calibrage OK ! ==> ");
}
}
else if (!mode1Sw){ Serial.print("- Reset compteur de distance ("); }
if (!mode1Sw){Serial.print("min sinus = ");Serial.print(minU);Serial.print(" // max sinus = ");Serial.println(maxU);}
digitalWrite(pinLED, LOW); // Eteindre la LED
} else { // passe en mode calibration
timeStartCalibre = millis();
lastA = chanelA;
lastB = chanelB;
tempMinU = analogRead(pinA);
tempMaxU = tempMinU;
}
}
valUa = analogRead(pinA); // Lecture de la valeur analogique 1
valUb = analogRead(pinB); // Lecture de la valeur analogique 2
if (valSw == true){
compte();
} else {
calibrate();
}
if (mode1Sw){
printGraph();
}
else {
printCompteur();
}
} // END loop()
void calibrate(){
bool change = false;
compteur = 0; //Réinitalise le compteur à zéro
if (valUa > tempMaxU) {
tempMaxU = valUa;
change = true;
} else if (valUa < tempMinU){
tempMinU = valUa;
change = true;
}
if (valUb > tempMaxU) {
tempMaxU = valUb;
change = true;
} else if (valUb < tempMinU){
tempMinU = valUb;
change = true;
}
if (millis() - timeStartCalibre > timeCalbr){
digitalWrite(pinLED, HIGH); // Allume la LED
if (change){
chanelA = !chanelA; // le chanelA change lorsqu'une nouvelle valeur remplace celle de minU ou maxU
//chanelB = false; // le chanelB passe à false pour mieux distinguer les changement sur le chanelA
}
}
Ua = (tempMinU * 5.0) / 1024.0; // Conversion de la valeur analogique en tension 1
Ub = (tempMaxU * 5.0) / 1024.0; // Conversion de la valeur analogique en tension 2
}
void compte(){
Ua = (valUa * 5.0) / 1024.0; // Conversion de la valeur analogique en tension 1
Ub = (valUb * 5.0) / 1024.0; // Conversion de la valeur analogique en tension 2
if (chanelA == true && valUa <= bottomU){
chanelA = false;
if (chanelB == false){
compteur ++;
} else { compteur --;}
}
else if (chanelA != true && valUa >= topU){
chanelA = true;
if (chanelB == true){
compteur ++;
} else { compteur --;}
}
if (chanelB == true && valUb <= bottomU){
chanelB = false;
if (chanelA == true){
compteur ++;
} else { compteur --;}
}
else if (chanelB != true && valUb >= topU){
chanelB = true;
if (chanelA == false){
compteur ++;
} else { compteur --;}
}
}
void printGraph(){
Serial.print(Ua, 3);
Serial.print(", "); // ==>> Séparateur de canaux pour SerialPlot
Serial.print(Ub, 3);
Serial.print(", ");
if (chanelA) {Serial.print("1.800");} else {Serial.print("1.000");}
Serial.print(", ");
if (chanelB) {Serial.print("0.800");} else {Serial.print("0.000");}
//Centre
Serial.print(", ");
float centre = (topU - hystHalf) * 5.0 / 1024.0;
Serial.println(centre, 3);
}
void printCompteur(){
static int32_t lastCompte = -10;
if (compteur != lastCompte){
// Imprime la distance pour un inter-points de 5 microns
Serial.print("Distance : ");Serial.print(float(compteur * umPoint) / 1000.0 , 3);
lastCompte = int32_t(abs(compteur) / 1000);
Serial.print("\t Compteur : ");
if(compteur < 0) Serial.print("-");
if(lastCompte != 0) {
Serial.print(lastCompte);Serial.print(" ");
}
Serial.println(abs(compteur) - lastCompte*1000);
lastCompte = compteur;
}
}
int readEEPROM(int address1, int address2) {
int value = (EEPROM.read(address1) << 8) | EEPROM.read(address2);
return value;
}
bool updateEEPROM(int address1, int address2, int value) {
int eepromValue = readEEPROM(address1, address2);
bool _raiponce = false;
if (eepromValue != value) {
EEPROM.write(address1, (value >> 8) & 0xFF);
EEPROM.write(address2, value & 0xFF);
_raiponce = true;
}
// DEBUG :
// Serial.println();Serial.println("------");
// Serial.print("Eeprom_Save: min sinus = ");Serial.print(minU);Serial.print(" // max sinus = ");Serial.println(maxU);
// Serial.print(readEEPROM(713, 714));Serial.print(" || ");Serial.print(readEEPROM(715, 716));
// Serial.println();Serial.println("------");Serial.println();
return _raiponce;
}
En connectant l'entrée A: entre 0° et 0v et l'entrée B: entre 180° et 0v, les courdes ce supperposent. pour l'image ci-dessous j'ai rajouter un ofset pour distinger les deux courbes.
Je ne comprend pas pourquoi il n’y a pas de variation entre 0° et 180° quand je déplace l’axe !
En connectant l'entrée A: entre 0° et 0v et l'entrée B: entre 270° et 0v
Comment pourrais-je faire pour acquérir ces signaux ? un module de conversion ? un module de comptage ?
Salutations, bonne journée.
















