Uso de codificadores rotatorios sin pines de interrupción

Primero, un poco de información.
Tengo 4 ruedas separadas en mi robot y un codificador en cada rueda. Estoy usando un arduino mega 2560 que solo tiene 6 pines de interrupción, cada código que he visto usa 2 líneas de interrupción por codificador o 1, pero no es tan preciso.

Mi idea:
mi idea aquí es que los codificadores marquen alrededor de 300 Hz a la velocidad máxima para mi robot, por lo que estoy usando una interrupción de desbordamiento del temporizador para leer todas las entradas a las que están conectados los codificadores a aproximadamente 1 kHz, lo que también me da mucho tiempo. (1 ms) para verificar si las entradas cambiaron y hacer mis cálculos y luego regresar de la interrupción.

Mi pregunta:
¿Es correcto mi pensamiento? ¿Podré leer correctamente la posición y los cambios del codificador? ¿Hay algo mejor que pueda hacer? ¿Hay alguna advertencia que deba tener en cuenta al tratar con esto?

Actualización: de la discusión en los comentarios y respuestas, actualmente tengo las dos alternativas siguientes:

  1. Cíñete a la idea de la encuesta (aumenta la frecuencia cuando sea necesario)
  2. Use una interrupción "compartida" disponible en cada pin (no sabía que era posible)
Si no recuerdo mal, en realidad puede obtener una interrupción de cualquier pin ATmega, el problema es que, aparte de los "pines de interrupción", no obtendrá una interrupción única sino una compartida "cualquiera de las habilitadas". Aún así, esto podría ser preferible a las encuestas periódicas.
Eso es a lo que apunto. Quiero un evento compartido para todos los codificadores que me permita verificarlos todos a la vez, pero el problema es que mis motores giran a diferentes velocidades (distribución de peso, diferencias entre ellos, etc.) así que necesito captarlo todo, por lo que creo que usar una interrupción "activada" de uno de los codificadores no funcionará.
El límite de 6 pines es para las interrupciones "externas" únicas. Pero la "interrupción de cambio de pin" de cada puerto puede incluir cualquier combinación de pines en ese puerto como disparador.
Gracias, no entendí completamente tu primer comentario, pero ahora sí. Gracias por su paciencia. Yo no sabía acerca de esto.
agregue su comentario como respuesta para que pueda aceptarlo como la solución a mi problema

Respuestas (4)

Si realmente sondea mucho más rápido de lo que se mueve el codificador, esto funcionará. Que sea una buena idea depende de la rapidez con la que se mueva el codificador y de la importancia de no perder clics. Ciertamente odio cuando giro un dial para desplazarme por una larga lista de UI y se mueve lentamente hacia atrás, aunque no hay daño real. Si el codificador recibe retroalimentación de un motor, la falta de clics podría causar problemas mayores, como daños mecánicos.

Puede usar una lógica dedicada para hacer un contador, o puede usar un microcontrolador diferente que tenga un codificador periférico incorporado, pero para la mayoría de los propósitos, el sondeo probablemente esté bien si lo hace lo suficientemente rápido.

Gracias por su respuesta, experimentaré con la tasa de sondeo y veré qué tan rápido puedo ejecutar la "lectura" antes de la próxima interrupción.
Por supuesto, debe tener en cuenta el tiempo de procesamiento requerido para evaluar un estado de entrada modificado, además de las implicaciones programáticas más grandes de un cambio, ya que hasta que se resuelva no puede volver a sondear las entradas.

¿Ha considerado sondear muy rápido y activar un par de 71451 con cuatro direcciones separadas para obtener el par de entradas que necesita, de manera rotativa (pero muy rápida)? Luego podría leer un bit de cada chip, uno por salida de codificador que se está direccionando en este momento.

Esto reducirá el número de pines de entrada necesarios a dos.

todo está bien

Debe sobremuestrear cada codificador, lo que significa muestrear más rápido de lo que se mueven. asumiendo que 300Hz es correcto. 1kHz es bastante rápido, suficiente headroom por si acaso. ¿Suponiendo un codificador de 2 pines? Solo hay dos próximos estados válidos desde el estado actual, ¿sí? Actualizó su posición según el estado actual y el siguiente estado (incremente una posición o disminuya, o cualquiera que sea su solución). Para cada rueda. valor almacenado en un global utilizado por la tarea en primer plano

si puede tenerlo para que cualquiera de los pines gpio cambie de estado provoque una interrupción que también funcione, menos sobrecarga de interrupción, pero si hay algún rebote en el cambio de estado, puede obtener múltiples interrupciones (con valores falsos). (el sobremuestreo también puede tener problemas de rebote).

Debe tener cuidado con las interrupciones y su código. Compruebe la salida del compilador. Rusty en AVR pero los registros son de 8 bits, ¿sí? Las cargas y las tiendas parecen ser de 8 bits. Entonces, si tiene un contador de posición de 16 bits, su tarea principal es leer ese contador, lo que significa que tiene que hacer al menos dos instrucciones para obtener las dos partes de la variable global escritas por el isr y leídas por la aplicación. La posición actual es 0x0FFF. Usted lee 0x0F, obtiene una interrupción, la posición cambia a 0x1000, regresa de la interrupción, la tarea principal lee la segunda mitad 0x00 y cree que la posición es 0x0F00. 255 cuenta mal. para un bucle de la tarea de primer plano. Por lo tanto, debe tener cuidado de que esto no suceda, muchas formas generales de evitarlo, pero específicas para este objetivo, no recuerdo de antemano. o puede hacer los cálculos de manera que su posición por rueda quepa en un byte.

el sondeo, siempre que lo haga lo suficientemente rápido, funciona bien (bueno, el rebote si hay algo en su codificador no está bien, supongamos que no tiene ninguno). a veces tiene que sondear más de una vez a través del ciclo, convertirlo en una función

while(1)
{
  do stuff
  poll_wheels();
  do stuff
  poll_wheels();
  ...
  poll_wheels();
}

o tal vez el ciclo del peor de los casos es lo suficientemente rápido

while(1)
{
   poll_wheels();
   do stuff.
}

debe lidiar con los estados no válidos de alguna manera, tal vez durante el desarrollo, si alguna vez ve un estado no válido, configure una variable de pánico, simplemente detenga los motores y todo, o configure un led o algo así para indicar visualmente que esto sucedió. no es mucho lo que puede hacer, pero aún debe tener un código adicional que si el estado actual de un codificador no es un estado siguiente válido al último estado de ese codificador, entonces aparte de configurar la variable de alarma/led/bit/contador, no actualice el pero use el estado actual como el último estado para la próxima prueba. simplemente finja desde una perspectiva de posición que no ocurrió ningún movimiento pero que se encuentra en una nueva posición del codificador. si tiene codificadores de tres bits o más, puede ver si se perdió uno y saltó dos, pero si es solo un codificador de dos bits, no necesariamente puede hacer eso.

Gracias a la sugerencia de Chris Stratton, conseguí que esto funcionara correctamente. He usado interrupciones de cambio de pin... con el enmascaramiento adecuado funcionó de maravilla :)

Gracias a todos por todas las sugerencias y experiencia.