Calibre/Pie de rey" gigante" y problema con visualización de la medida.

Buenas noches, me dirijo una vez mas a este foro para ver si entre todos me podéis ayudar, gracias de antemano.

Os pongo en situación, hace tiempo me venia abordando un problema para la medida de piezas grandes con precisión. El calibre que tengo llega hasta medidas de 200mm, pero claro si quieres medir algo que tenga por ejemplo 1034'45mm con bastante precisión, pues con el típico metro de toda la vida no se puede. Si que es cierto que venden incluso calibres digitales de hasta 1500mm pero a un precio de 2.000 y pico € y desde china son unos 350, mas 250 de portes, etc. Total, que decidí hacerlo yo. El sistema de los calibres es como el de las reglas métricas que muestran las cotas de las maquinas de cnc...era inviable imitar ese sistema, de modo que se me ocurrió hacerlo con un encoder de 2000 pulsos que tenia por casa. El encoder tiene montada una rueda de goma de vulkollan de 55'38mm de diámetro, el cual rueda por un perfil de aluminio que le sirve de bastidor. (Fotos).

La medida la hace correcta, pero el problema viene cuando deslizo rápido la rueda, mas que rápido, con bastante aceleración (girándolo con la mano también lo hace)....pero jamás igual de rápido que como lo haría un motor. El tema es que muestra en el monitor serie la cota que está midiendo, con una resolución de 0,03mm que para lo que quiero hacer me vale. Necesito poner la velocidad a 2.000.000 de baudios para que cuando deslizo el encoder, vaya viendo el resultado. Si lo pongo a 9600, 115200, etc, es imposible. Ni despacio puede hacerlo. Si giro la rueda mas rápido, pierde esa cota.
¿Puedo corregir esto para que no vaya tan lento abriendo y cerrando las uñas del calibre?
¿Puede ser que en una pantalla LCD vaya mejor que mostrarlo por monitor serial? ¿es lo mismo en cuanto a velocidad?

Os dejo unas fotos y los códigos. Si queréis recrearlo, os dejo también los archivos STL para la impresora 3D.

(Con este código puedo deslizarlo mas rápido pero no están preciso)

#define outputA 2
 #define outputB 3
 float counter = 0; 
 int aState;
 int aLastState;  
 void setup() { 
   pinMode (outputA,INPUT_PULLUP);
   pinMode (outputB,INPUT_PULLUP);
   
   Serial.begin (2000000);
   
   aLastState = digitalRead(outputA);   
 } 
 void loop() { 
   aState = digitalRead(outputA); 
   
   if (aState != aLastState){     
     /
     if (digitalRead(outputB) != aState) { 
       counter ++;
     } else {
       counter --;
     }
     //Serial.print("Posicion: ");
     Serial.println(counter*3.1415926*55.34/2000); //Cuenta los pulsos que lleva, lo multiplica por Pi, lo multiplica por el diametro del rodillo de vulkollan y lo dividimos entre 2000 pulsos
   } 
   aLastState = aState; 
 }

(Este código es mas preciso pero no puedo moverme nada rápido sin que pierda resolución)

//#include <LiquidCrystal.h>

//LiquidCrystal lcd(5, 6, 7, 8, 9, 10);

int pin1 = 2;
int pin2 = 3;

int Pos = 0; 
int State;
int LastState;  

const float pi = 3.14159265;

const float R = 27.67; //Radio del rodillo de vulkollan
const int N = 2000;  //pulsos del encoder

float distancia = 0;

void setup() { 
  pinMode (pin1 ,INPUT_PULLUP);
  pinMode (pin2 ,INPUT_PULLUP);
  Serial.begin(2000000);

 // lcd.begin(16, 2);
//  lcd.print("Medicion");
  
  LastState = digitalRead(pin1);    
} 

void loop() { 
  State = digitalRead(pin1);
   if (State != LastState){     
     if (digitalRead(pin2) != State) { 
       Pos ++;
     } 
     
     else {
       Pos --;
     }
   } 

  distance = ((2*pi*R)/N) * Pos ;

  Serial.println( distancia);
  
 

  //lcd.setCursor(0, 1);
  //lcd.print( distancia);

  //lcd.setCursor(5, 1);
  //lcd.print("mm  ");
   
  LastState = State;
 }

(Algunas fotillos del invento)

Gracias y un saludo

  1. Error: no puedes definir counter como float y luego incrementarlo como entero.
    Con un encoder de 2000 pasos seguramente a toda velocidad superas lo maximo de un entero que son 2^16 posiciones y entonces te conviene definirlo como long que contemplará valores positivos y negativoos.
    Entonces long counter en lugar de float.

  2. Ayuda al micro a no hacer cuentas innecesarias mira esto

Serial.println(counter*3.1415926*55.34/2000;)
#default  K 3.1415926*55.34/2000.0

O simplemente haz la cuenta

Luego solo usa

Serial.println(counter*K);

Yo leería el enconder con alguna librería aprovechando la opción en la que usa interrupcciones, porque al ponerlo a leer rápidamente es posible que pierdas datos en tu código.
Debes priorizar la cuenta y no la presentación. La presentación es anecdótica si me permites el termino. Claro que debes ver el valor pero que importa el valor cuando te muevs con mucha velocidad? Basta con saber que pasas determinadas posiciones.

Con las interrupcones no perderas pulsos del encoder y la cuenta será precisa siempre.

Dame mas datos de tu encoder.

En un momento te paso un código con las correcciones citadas.

Prueba este ejemplo de la libreria EnconderStepCounter disponible el en Administrador de Librerías del IDE

#include "EncoderStepCounter.h"

#define ENCODER_PIN1 2
#define ENCODER_INT1 digitalPinToInterrupt(ENCODER_PIN1)
#define ENCODER_PIN2 3
#define ENCODER_INT2 digitalPinToInterrupt(ENCODER_PIN2)

// Create instance for one full step encoder
EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2);
// Use the following for half step encoders
//EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2, HALF_STEP);

void setup() {
  Serial.begin(9600);
  // Initialize encoder
  encoder.begin();
  // Initialize interrupts
  attachInterrupt(ENCODER_INT1, interrupt, CHANGE);
  attachInterrupt(ENCODER_INT2, interrupt, CHANGE);
}

// Call tick on every change interrupt
void interrupt() {
  encoder.tick();
}

// This is an example on how to change a "long" variable
// with the library. With every loop the value is added
// and then cleared in the encoder library
signed long position = 0;
void loop() {
  signed char pos = encoder.getPosition();
  if (pos != 0) {
    position += pos;
    encoder.reset();
    Serial.println(position);
  }
}

Verifica que funciona bien el tema de los pasos y luego cambia estos por el valor en mm que deseas.

Mil gracias Surbyte por la ayuda, el código va perfecto, ya puedo leer los milímetros sin perder "pasos". El encoder es un encoder industrial Eltra EL8G1000S5, te dejo el link por aqui Eltra EL38G1000S5/28P8X3PR5 | Official Distributor

Tiene medios pasos con un total de 2000, y lo mejor de todo es poderlo alimentar con los 5v de suministra arduino.

Dejo el código modificado con las dos cosas que me has dicho:

#include "EncoderStepCounter.h"

#define ENCODER_PIN1 2
#define ENCODER_INT1 digitalPinToInterrupt(ENCODER_PIN1)
#define ENCODER_PIN2 3
#define ENCODER_INT2 digitalPinToInterrupt(ENCODER_PIN2)
#define  K 3.1415926*55.34/2000.0

// Create instance for one full step encoder
//EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2);
// Use the following for half step encoders
EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2, HALF_STEP);

void setup() {
  Serial.begin(9600);
  // Initialize encoder
  encoder.begin();
  // Initialize interrupts
  attachInterrupt(ENCODER_INT1, interrupt, CHANGE);
  attachInterrupt(ENCODER_INT2, interrupt, CHANGE);
}

// Call tick on every change interrupt
void interrupt() {
  encoder.tick();
}

// This is an example on how to change a "long" variable
// with the library. With every loop the value is added
// and then cleared in the encoder library
signed long position = 0;
void loop() {
  signed char pos = encoder.getPosition();
  if (pos != 0) {
    position += pos;
    encoder.reset();
    Serial.println(position*K);
    
  }
}

Quizás termine añadiendo un LCD para no tener que llevar el pc, pero de momento va genial.

Una vez mas, gracias.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.