Arduino en español
Circuitos con Arduino - Juan Antonio Villalpando
-- Tutorial de iniciación a Arduino --
Volver al índice del tutorial
___________________________
42.- Rotary Encoder.
- Es un elemento que puede funcionar como potenciómetro, aunque no contiene ninguna resistencia variable.
- Funciona con pulsos en cuadratura, pero no emite pulsos.
|
Interior del Rotary, imagen de aquí.
Se observa contactos separados en pasos. La pieza movible tiene dos lenguetas de contactos, al moverla van haciendo o no contactos con las partes metálicas.
Fíjate la parte izquierda de la pieza azul hay contactos separados, en cambio en la parte derecha es un contacto contínuo.
En la imagen vemos a la izquierda 10 contactos, pero como pasa una lengueta y luego pasa otra, actúa como 20 contactos. |
- No tienen tope a la derecha ni a la izquierda, por lo cual puede dar todas las vueltas que queramos.
- En su círculo interior hay contactos separados. Al girar el eje un par de pestañas van haciendo o no contacto.
- Cuando gira 360º ha realizado 20 contactos o 20 pasos (step), el usuario percibe ligeramente esos pasos cuando gira el eje.
- Se utilizan en equipos de audio, para controlar servos, control de iluminación,...
- Tiene dos formas de trabajas, una en loop o otra mediante interrupciones.
Imágenes de http://www.electroschematics.com/12012/rotary-encoder-arduino/
- Para evitar rebotes (bounce) se suele poner un grupo RC en cada terminal A y B.
- En esta web podemos estudiarlo medinate un script:
https://www.pjrc.com/teensy/td_libs_Encoder.html
____________________________________
1.- Rotary Encoder. Cuenta a derecha e izquierda.
- Este es el mejor ejemplo para aprender a utilizarlo.
|
- Nuestro primer ejemplo lo he adaptado de:
http://playground.arduino.cc/Main/RotaryEncoders
- Cuando movemos el Rotary en el sentido del reloj, aumenta la cuenta de Posicion.
- Cuando movemos el Rotary en el sentido contrario, disminuye la cuenta de Posicion.
- Si pulsamos el eje del Rotary, actúa como botón, el contador de Posicion vuelve a 0.
CLK y DT son los terminales que en la mayoría de los tutoriales llaman PinA y PinB.
SW es el botón, el eje del Rotary actúa como botón, lo podemos pulsar.
La cuenta será hasta +-32767 que es el margen de int.
Visualiza los valores en el Serival Monitor.
- Hay otra forma de utilizar los Rotar, es mediante interrupciones.
|
Código |
// Read Quadrature Encoder
// Sketch by max wolf / www.meso.net
// Modificado por Juan A. Villalpando
// kio4.com
int val;
int PinCLK = 3;
int PinDT = 4;
int PinSW = 8;
int Posicion = 0;
int PinCLKanterior = LOW;
int n = LOW;
void setup() {
pinMode (PinCLK,INPUT);
pinMode (PinDT, INPUT);
pinMode (PinSW, INPUT);
Serial.begin (9600);
}
void loop() {
n = digitalRead(PinCLK);
if ((PinCLKanterior == LOW) && (n == HIGH)) {
if (digitalRead(PinDT) == LOW) {Posicion--;}
else {Posicion++;}
Serial.println (Posicion);
}
PinCLKanterior = n;
if ((digitalRead(PinSW) == LOW)) {Posicion = 0; }
}
|
____________________________________
Con interrupciones
- Cuando hay movimiento en el Rotary, se envía una interrupción al procesador para que realice lo que hay en el loop.
- Puede fallar debido al uso del Serial Monitor.
- Para evitar ese fallo comentamos la línea: // Serial.println (encoder0Pos, DEC);
- Al trabajar con interrupciones, dejamos libre el bucle loop, para que el microcontrolador no tenga que estar continuamente consultando si se ha movido el potenciómetro.
- El bucle loop, solo se ejecutará cuando llegue una interrupción.
Código |
// http://playground.arduino.cc/Main/RotaryEncoders#Example2
#define encoder0PinA 2
#define encoder0PinB 3
volatile unsigned int encoder0Pos = 0;
void setup() {
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin (9600);
}
void loop(){
//Do stuff here
}
void doEncoderA(){
// look for a low-to-high on channel A
if (digitalRead(encoder0PinA) == HIGH) {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}}
else // must be a high-to-low edge on channel A
{
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}}
Serial.println (encoder0Pos, DEC);
// use for debugging - remember to comment out
}
void doEncoderB(){
// look for a low-to-high on channel B
if (digitalRead(encoder0PinB) == HIGH) {
// check channel A to see which way encoder is turning
if (digitalRead(encoder0PinA) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
} else {
encoder0Pos = encoder0Pos - 1; // CCW
}}
// Look for a high-to-low on channel B
else { // check channel B to see which way encoder is turning
if (digitalRead(encoder0PinA) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
} else {
encoder0Pos = encoder0Pos - 1; // CCW
}}
}
|
____________________________________
Semáforo
Semáforo, debemos mantener pulsado el eje del Rotary para ver como cambian las luces del semáforo.
No es un ejemplo muy didáctico.
Consta de tres LED en 2, 3 y 4.
Código |
int redPin = 2;
int yellowPin = 3;
int greenPin = 4;
int aPin = 6;
int bPin = 7;
int buttonPin = 5;
int state = 0;
int longPeriod = 5000; // Time at green or red
int shortPeriod = 700; // Time period when changing
int targetCount = shortPeriod;
int count = 0;
void setup()
{
pinMode(aPin, INPUT);
pinMode(bPin, INPUT);
pinMode(buttonPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(greenPin, OUTPUT);
}
void loop()
{
count++;
if (digitalRead(buttonPin))
{
setLights(HIGH, HIGH, HIGH);
}
else
{
int change = getEncoderTurn();
int newPeriod = longPeriod + (change * 1000);
if (newPeriod >= 1000 && newPeriod <= 10000)
{
longPeriod = newPeriod;
}
if (count > targetCount)
{
setState();
count = 0;
}
}
delay(1);
}
int getEncoderTurn()
{
// return -1, 0, or +1
static int oldA = LOW;
static int oldB = LOW;
int result = 0;
int newA = digitalRead(aPin);
int newB = digitalRead(bPin);
if (newA != oldA || newB != oldB)
{
// something has changed
if (oldA == LOW && newA == HIGH)
{
result = -(oldB * 2 - 1);
}
}
oldA = newA;
oldB = newB;
return result;
}
int setState()
{
if (state == 0)
{
setLights(HIGH, LOW, LOW);
targetCount = longPeriod;
state = 1;
}
else if (state == 1)
{
setLights(HIGH, HIGH, LOW);
targetCount = shortPeriod;
state = 2;
}
else if (state == 2)
{
setLights(LOW, LOW, HIGH);
targetCount = longPeriod;
state = 3;
}
else if (state == 3)
{
setLights(LOW, HIGH, LOW);
targetCount = shortPeriod;
state = 0;
}
}
void setLights(int red, int yellow, int green)
{
digitalWrite(redPin, red);
digitalWrite(yellowPin, yellow);
digitalWrite(greenPin, green);
}
|
________________
Librerías
Existen varias librería con ejemplos, entre ellas:
Encoder.zip
Encoder_Polling-master.zip
RotaryEncoder-master.zip
Detrás tiene 3 resistencia de 10K llevadas a positivo.
____________________________________
|