Escenario
Tengo 4 ACZ16 codificadores rotatorios en cuadratura conectados al GPIO Port D en un ATMega168P . Sólo estoy tratando de extraer la dirección de rotación de ellos. La posición es irrelevante, y se garantiza que solo un codificador girará en un momento dado. El anuncio se maneja en hardware utilizando el filtro de rebote recomendado en la hoja de datos y no hay un rebote del conmutador visible en el alcance.
Problema
La diferenciación entre los codificadores no es un problema. Donde me encuentro con obstáculos es extrayendo la dirección. Mi primer pensamiento después de un poco de Google fue una interrupción de cambio de pin.
ISR resultante:
ISR(PCINT2_vect)
{
unsigned static char int_count = 0;
unsigned char pins = PIND;
unsigned char send;
if(int_count == 0)
{
switch(pins)
{
case 0x7F: send = MIRROR_X_L; break;
case 0xBF: send = MIRROR_X_R; break;
case 0xDF: send = MIRROR_Y_D; break;
case 0xEF: send = MIRROR_Y_U; break;
case 0xF7: send = LASER_X_L; break;
case 0xFB: send = LASER_X_R; break;
case 0xFD: send = LASER_Y_D; break;
case 0xFE: send = LASER_Y_U; break;
default: send = NOTHING; break;
}
if(send != NOTHING)
{
sendSPI(send);
}
int_count++;
}
else
{
if(int_count == 3)
{
int_count = 0;
}
else
{
int_count++;
}
}
}
Esto detectó rotación en el codificador rotatorio correcto, pero solo en una dirección. Una rotación en el sentido de las agujas del reloj se decodifica correctamente, una rotación en el sentido contrario a las agujas del reloj aún se decodifica como una rotación en el sentido de las agujas del reloj.
Después de seguir con Google, probé un enfoque de sondeo, usando un código similar.
Bucle principal resultante:
while(1)
{
switch(PIND)
{
case 0x7F: send = MIRROR_X_L; break;
case 0xBF: send = MIRROR_X_R; break;
case 0xDF: send = MIRROR_Y_D; break;
case 0xEF: send = MIRROR_Y_U; break;
case 0xF7: send = LASER_X_L; break;
case 0xFB: send = LASER_X_R; break;
case 0xFD: send = LASER_Y_D; break;
case 0xFE: send = LASER_Y_U; break;
default: send = NOTHING; break;
}
if(send != NOTHING)
{
sendSPI(send);
_delay_ms(40);
}
}
Jugué con varios valores de retardo después de mi transmisión SPI, pensando que eso solucionaría el problema (el tiempo de ciclo real es de aproximadamente 20 ms), pero este enfoque muestra un comportamiento idéntico al del ejemplo de interrupción de cambio de pin. Una rotación en el sentido de las agujas del reloj se decodifica correctamente, una rotación en el sentido contrario a las agujas del reloj aún se decodifica como una rotación en el sentido de las agujas del reloj.
La mayoría de los métodos que he encontrado, como las tablas de búsqueda, no se pueden escalar más allá de uno, quizás dos codificadores rotatorios. ¿Cuál es la mejor manera de hacerlo con varios codificadores rotatorios?