Reglas digitales iGaging EZ VIEW-DRO Plus

No entro muy seguido al foro pero aporto algo que a alguien le puede interesar.
Como parte de un proyecto para automatizar un pequeño torno de banco, que tengo como pasatiempo, me vi en la necesidad de poder medir la posición del carro y de la herramienta del torno con la mayor exactitud posible. Me puse a investigar por internet y encontré estas reglas digitales marca iGaging a un precio bastante accesible.
También se vende un dispositivo por separado
100-700.jpg
para transferir los datos a una PC. Pulsando el botón central que se ve en la foto transfiere los datos a una PC.
Como este dispositivo no se adecua a mis necesidades; necesito que la regla permanentemente esté mandando datos a la PC para detener o arrancar los motores a tiempo, y por otro lado el precio del dispositivo es bastante alto en relación a lo que cuestan los DRO, decidí hacer una interface basado en las páginas de shumatech y Yuriy's Toys

Armé un pequeño circuito para conectar el DRO a una placa Arduino
circuito1.png
Tomé la derivación del cable que conecta la regla con la pantalla. No utilicé la salida de datos que posee la pantalla porque la ficha de conexión, al menos en Argentina, me fue imposible conseguirla. Improvisé una haciendo un impreso de 5 pistas paralelas pero no funcionó y no tenía ganas perder tiempo.
Para no cortar los cables originales del DRO, con dos cables de los que se usan para conectar un teléfono celular a una PC armé la derivación.
La pantalla se conecta con la regla a través de dos fichas micro usb. Para acceder a la ficha de la regla es necesario desarmarla.
Los pines de las fichas micro usb son los siguientes:
pin 1: +3 voltios
pin 2: linea DATA (provista por la regla)
pin 3: linea CLOCK (provista por la pantalla)
pin 4: no conectado
pin 5: masa
El soporte de la regla está conectado internamente a masa. Ojo al piojo si mezclan estos DRO iGaging con calibres chinos ya que algunos calibres chinos traen las mordazas conectas al positivo.

Como la placa Arduino que utilicé para la prueba se alimenta con 5 voltios utilicé la alimentación de las pilas del DRO (2 pilas 2032 si mal no recuerdo).
Entiendo que es muy posible alimentar la regla directamente desde Arduino desde el pin 3.3V. Por el momento no lo hice.

Interpuse entre las líneas de CLOCK y DATA dos compuertas NOR. Por un lado para elevar la salida de las líneas del DRO a 5 voltios y por otro lado para tener una alta impedancia a efectos de alterar lo menos posible las señales. La línea CLOCK la conecté al PIN 2 de Arduino para poder utilizar una interrupción.

Hechando mano a un osciloscopio tomé las señales del DRO a la entrada de los pines de Arduino
clock_y_data_apliado.png
La señal de CLOCK (trazo celeste) consiste de 21 pulsos con un período de 400 micro segundos, permaneciendo en estado alto 300 micro segundos y en estado bajo 100. Esto equivale a una frecuencia de 2.500Hz. En la página de Yuriy's Toys asumen que el período de los bits de CLOCK es de 111 micro segundos (9KHz). Supongo que lo hacen porque el reloj lo proveen desde un Arduino.
La señal de CLOCK repite la secuencia cada 5 mili segundos aproximadamente utilizando el CLOCK provisto por la pantalla.
No entro en el detalle del protocolo de 21 bits porque en la página de shumatech está suficientemente bien explicado.

Basado en el programa de la página de Yuriy's Toys hice el siguiente sketch para usar interrupciones:

const int clockxpin = 2; // Pin de entrada para la señal CLOCK del calibre
const int dataxpin = 3; // Pin de entrada para la señal DATA del calibre
unsigned long lapsoEntreClocks = 1500; // Lapso que se debe esperar a la línea de CLOCK antes de comenzar la lectura de la línea DATA expresado en microsegundos
double X0 = 0;//-1547; // valor extremo inferior de X para la ecuación de la recta de ajuste (X representa el valor leido en la linea DATA)
double X1 = 15724;//-14649; // valor extremo superior de X para la ecuación de la recta de ajuste
double K0 = 0; // valor extremo inferior del factor de correccion de la regla
double K1 = 123; // valor extremo superior del factor de correccion de la regla
boolean ok = false; // ok == true => habilita IRQ 0 del pin 2 (linea de clock) para leer los valores de la linea DATA (pin 3)
boolean sincronizarClock = true; // sincronizarClock == true => esperar a que la linea de CLOCK mantenga un valor LOW de por lo menos lapsoEntreClocks
volatile byte idx = 0; // auxiliar para hacer el offset de los bits leidos
volatile long X = 0; // valor de la coordenada X de la regla

void setup() {
Serial.begin(9600); // Abre el puerto serial a 9600 bps
pinMode(clockxpin, INPUT); // Pone pin de la señal CLOCK del calibre a entrada
pinMode(dataxpin, INPUT); // Pone el pin de la señal DATA del calibre a entrada
pinMode(alimentacionxpin, OUTPUT); // Pone el pin de alimentación para el calibre como salida
digitalWrite(alimentacionxpin, HIGH); // Enciende el pin de alimentación para el calibre
Serial.flush();
}

void loop() {
while (sincronizarClock == true) {
ok = false;
unsigned long tiempo0 = micros();
while ((digitalRead(clockxpin) == LOW) && (!ok)) { // lazo para sincronizar la linea de CLOCK
ok = ((micros() - tiempo0) >= lapsoEntreClocks);
}
if (ok == true) { // si ok == true se miden los 21 bits de la linea DATA mediante la IRQ 0
idx = 0; // y se interrumpe la sincronizacion de la linea CLOCK
X = 0;
sincronizarClock = !ok;
attachInterrupt(digitalPinToInterrupt(clockxpin), leerX, FALLING);
break;
}
}
}

void leerX() {
X |= (digitalRead(dataxpin) << idx);
idx++;
if (idx > 20) {
detachInterrupt(digitalPinToInterrupt(clockxpin));
enviarDatos();
}
}

void enviarDatos() {
Serial.println(getValorY());
//Serial.println(X);
sincronizarClock = true;
}

long getValorY() {
double mk = (K1 - K0) / (X1 - X0);
long k = K0 + mk * (X - X0);
long rtn = X - k;
return abs(rtn);
}

Las reglas EZ VIEW Plus son reglas absolutas. Es decir que por más que se fije el cero en cualquier lugar o se cambien las unidades de medida la línea DATA responde siempre con el mismo patrón. Obviamente el patrón cambia a medida que se mueve la regla, pero para una determinada posición el patrón es siempre el mismo.

En la primera prueba me limité a leer los primeros 20 bits del protocolo y ver los resultados (linea Serial.println(X); comentada en la función enviarDatos). Como era de esperar los datos no coincidían con la lectura de la pantalla.
Volviendo al osciloscopio busqué una posición donde la línea DATA respondiera con todos los bits en cero. Esta posición la encontré a unos 5 milímetros del extremo izquierdo de la regla. Lograda esta posición fijé el cero de la pantalla de manera que a DATA todo cero la pantalla mostrara 0.00 milímetros. Volví a leer los datos para diferentes posiciones. Tampoco coincidían pero esta vez por poca diferencia. Para una lectura en la pantalla 0.00 obviamente coincidían, pero para una lectura de 150.00 mm había una diferencia de 1.23 milímetros.
Asumí que la diferencia se debe a la propia regla y que tenía que variar linealmente con la posición. Por esa razón agregué la función getValorY().
Probé el sketch agregando esta función y la respuesta fue coincidencia casi total en todo el recorrido de la regla. En algunos puntos tengo una diferencia de una centésima de milímetro con respecto a lo que muestra la pantalla.

Conclusiones y dudas:
No pude descubrir para que sirve el último bit de la línea DATA. La función leerX() realidad lee los primeros 20 bits. El último lo descarta.
No sé qué pasará si cambio de regla. La prueba la hice con la regla de 6 pulgadas, pero vienen dos reglas más en el juego (con sus respectivas pantallas), una de 12 y otra de 24 pulgadas. Supongo que para poder usar siempre el mismo sketch con diferentes reglas lo mejor será tomar un cero arbitrario y medir diferencias de posición.
Sería bueno prescindir de la señal de CLOCK provista por la pantalla y ver que pasa usando un CLOCK de mayor frecuencia a ver si la regla responde más rápido. No lo hice porque para la aplicación que la pretendo usar la respuesta es más que suficiente en cuanto a velocidad.
Quizás alguien que haya hecho más pruebas con estos DRO, o como decimos en Argentina, "la tenga más clara", pueda aportar mejores ideas.
 
Arriba