5.Codificador. / 5.Encoder.

Nuestra tarea era hacer un modelo en Simulink que se conectará con un codificador real escondido dentro del Piero. La salida de este bock se contará con los impulsos generados por el codificador.

 

Our task was to make a model in Simulink which will be connected with real encoder hidden inside the Piero. The output of this bock will be counted pulses generated by the encoder.

5.1 Basic

enkoder.jpg.1Lo que está oculto dentro de Piero es EMG30 (codificador, motor, caja de cambios 30: 1) es un motor de 12 V totalmente equipado con codificadores y una caja reductora de 30: 1. Es ideal para aplicaciones robóticas pequeñas o medianas, proporcionando un impulso y retroalimentación rentables para el usuario. También incluye un condensador de supresión de ruido estándar a través de los devanados del motor.

 

What is hidden inside Piero is EMG30 (encoder, motor, gearbox 30:1) is a 12 V motor fully equipped with encoders and a 30:1 reduction gearbox. It is ideal for small or medium robotic applications, providing cost-effective drive and feedback for the user. It also includes a standard noise suppression capacitor across the motor windings.

 

La imagen real del codificador que podemos ver arriba y abajo es su medida.

 

The real picture of the encoder we can see above and below is the measurements of it.

enkoder measurements.jpg

Fuente: https://www.robot-electronics.co.uk/htm/emg30.htm

 

Source : https://www.robot-electronics.co.uk/htm/emg30.htm

 

5.2. ¿Qué es el codificador y cómo funciona? / 5.2. What is encoder and how does it work?

enkoder - model.png

Cuando el disco comenzará a girar paso a paso, los pines A y B comenzarán a hacer contacto con el pin común y las dos señales de salida de onda cuadrada se generarán en consecuencia.

 

When the disk will start rotating step by step, the pins A and B will start making contact with the common pin and the two square wave output signals will be generated accordingly.

 

Cualquiera de las dos salidas se puede usar para determinar la posición girada si solo contamos los pulsos de la señal. Sin embargo, si queremos determinar también la dirección de rotación, debemos considerar ambas señales al mismo tiempo.

 

Any of the two outputs can be used for determining the rotated position if we just count the pulses of the signal. However, if we want to determine the rotation direction as well, we need to consider both signals at the same time.

 

Podemos observar que las dos señales de salida se desplazan a 90 grados de fase una de la otra. Si el codificador está girando en el sentido de las agujas del reloj, la salida A estará por delante de la salida B.

 

We can notice that the two output signals are displaced at 90 degrees out of phase from each other. If the encoder is rotating clockwise the output A will be ahead of output B.

enkoder - model2.png

Entonces, si contamos los pasos cada vez que cambia la señal, de Alto a Bajo o de Bajo a Alto, podemos notar que en ese momento las dos señales de salida tienen valores opuestos. Viceversa, si el codificador está girando en sentido contrario a las agujas del reloj, las señales de salida tienen valores iguales. Entonces, teniendo en cuenta esto, podemos programar fácilmente nuestro controlador para leer la posición del codificador y la dirección de rotación.

 

So if we count the steps each time the signal changes, from High to Low or from Low to High, we can notice at that time the two output signals have opposite values. Vice versa, if the encoder is rotating counter clockwise, the output signals have equal values. So considering this, we can easily program our controller to read the encoder position and the rotation direction.

5.3. Modelo en Simulink. / 5.3. Model in Simulink.

Tuvimos que adaptar el modelo dado a nuestro codificador. Para hacer eso cambiamos el código en Block Encoder y ahora se ve así:

 

We had to fit the given model to out encoder. In order to do that we change the code in Block Encoder and now it looks like that :

 

# ifndef MATLAB_MEX_FILE

# include <Arduino.h>

typedef struct { int pinA; int pinB; int pos;} Encoder;
volatile Encoder Enc[2] = {{0,0,0}, {0,0,0}};

/* auxiliary function to handle encoder attachment */
int getIntNum(int pin) {
/* returns the interrupt number for a given interrupt pin
see http://arduino.cc/it/Reference/AttachInterrupt */
switch(pin) {
case 2:
return 0;
case 3:
return 1;
case 21:
return 2;
case 20:
return 3;
case 19:
return 4;
case 18:
return 5;
default:
return -1;
}
}

/* Interrupt Service Routine: change on pin A for Encoder 0 */
void irsPinAEn0(){

/* read pin B right away */
int drB = digitalRead(Enc[0].pinB);

/* possibly wait before reading pin A, then read it */
int drA = digitalRead(Enc[0].pinA);

/* this updates the counter */
if (drA == HIGH) { /* low->high on A? */

if (drB == LOW) { /* check pin B */
Enc[0].pos++; /* going clockwise: increment */
} else {
Enc[0].pos--; /* going counterclockwise: decrement */
}

} else { /* must be high to low on A */

if (drB == HIGH) { /* check pin B */
Enc[0].pos++; /* going clockwise: increment */
} else {
Enc[0].pos--; /* going counterclockwise: decrement */
}

} /* end counter update */

} /* end ISR pin A Encoder 0 */

 

/* Interrupt Service Routine: change on pin B for Encoder 0 */
void isrPinBEn0(){

/* read pin A right away */
int drA = digitalRead(Enc[0].pinA);

/* possibly wait before reading pin B, then read it */
int drB = digitalRead(Enc[0].pinB);

/* this updates the counter */
if (drB == HIGH) { /* low->high on B? */

if (drA == HIGH) { /* check pin A */
Enc[0].pos++; /* going clockwise: increment */
} else {
Enc[0].pos--; /* going counterclockwise: decrement */
}

} else { /* must be high to low on B */

if (drA == LOW) { /* check pin A */
Enc[0].pos++; /* going clockwise: increment */
} else {
Enc[0].pos--; /* going counterclockwise: decrement */
}

} /* end counter update */

} /* end ISR pin B Encoder 0 */

/* Interrupt Service Routine: change on pin A for Encoder 1 */
void irsPinAEn1(){

/* read pin B right away */
int drB = digitalRead(Enc[1].pinB);

/* possibly wait before reading pin A, then read it */
int drA = digitalRead(Enc[1].pinA);

/* this updates the counter */
if (drA == HIGH) { /* low->high on A? */

if (drB == LOW) { /* check pin B */
Enc[1].pos++; /* going clockwise: increment */
} else {
Enc[1].pos--; /* going counterclockwise: decrement */
}

} else { /* must be high to low on A */

if (drB == HIGH) { /* check pin B */
Enc[1].pos++; /* going clockwise: increment */
} else {
Enc[1].pos--; /* going counterclockwise: decrement */
}

} /* end counter update */

} /* end ISR pin A Encoder 1 */


/* Interrupt Service Routine: change on pin B for Encoder 1 */
void isrPinBEn1(){

/* read pin A right away */
int drA = digitalRead(Enc[1].pinA);

/* possibly wait before reading pin B, then read it */
int drB = digitalRead(Enc[1].pinB);

/* this updates the counter */
if (drB == HIGH) { /* low->high on B? */

if (drA == HIGH) { /* check pin A */
Enc[1].pos++; /* going clockwise: increment */
} else {
Enc[1].pos--; /* going counterclockwise: decrement */
}

} else { /* must be high to low on B */

if (drA == LOW) { /* check pin A */
Enc[1].pos++; /* going clockwise: increment */
} else {
Enc[1].pos--; /* going counterclockwise: decrement */
}

} /* end counter update */

} /* end ISR pin B Encoder 1 */


# endif

 

 

Como podemos ver, está hecho para dos codificadores, uno derecho y uno izquierdo.

 

As we can see it is made for two encoders - right and left one.

5.3. Resumen. / 5.3. Summary.

Completamos la tarea y ahora podemos usar el codificador en otros ejercicios. También ahora sabemos las respuestas a esas preguntas:

  • ¿Qué es el codificador?
  • ¿Cuál es su tarea?
  • ¿Como funciona?

 

We completed the task and now we are able to use the encoder in other exercises. Also now we know the answers to those questions :

  • What is the encoder?
  • What is its task?
  • How does it work?