Digamos que tengo un Arduino conectado a un 8x8 LED matrix
.
En mi caso, la matriz de LED se controla mediante dos 74HC595
registros de desplazamiento (uno para las filas y otro para las columnas).
Dado que solo puede configurar el estado de 8 LED a la vez (una fila), la idea es actualizar las filas lo suficientemente rápido para que el ojo humano no note el parpadeo.
Esto generalmente se hace en el loop()
método:
int led_status[8]; //contains LED status (which is on/off) for each row
void loop() {
process_otherstuff(); //eg: key inputs,...
display(); //shift led_status[] to shift register and latch result.
}
Aquí hay un problema potencial: ¿qué pasa si la CPU tiene que hacer algún proceso que consume mucho tiempo en el método de bucle (por ejemplo, matemáticas pesadas)? Se llamará al método display() con un cierto retraso que podría notarse (el LED comenzará a parpadear o, lo que es peor: deja de actualizarse, parece estar atascado en una fila).
Una posible solución que se me ocurre es actualizar la matriz de LED en un controlador de interrupciones:
void setup()
{
analogWrite(3, 100);
attachInterrupt(1, refreshdisplay, RISING);
}
int row = 0;
void refreshdisplay()
{
//refresh one single row
refreshrow(row++);
if(row > 7) row = 0;
}
Es esta una buena idea ? De esa manera, no importa cuánto tiempo se dedique al método loop(), la pantalla se actualizará tan rápido como sea necesario. El problema potencial que puedo ver es que ahora se gasta mucho tiempo en la interrupción, lo que generalmente es algo malo (el controlador de interrupciones debe ser lo más corto posible).
Otra solución es usar un controlador de controlador LED separado (por ejemplo, conectado a Arduino usando el bus I2C), pero esto requiere cambiar la lista de componentes.
Sí, ese es el enfoque correcto: actualice la pantalla en un ISR.
Incluso los cambios de sincronización leves pueden dar lugar a artefactos visuales, por lo que es necesario mantener la sincronización bastante ajustada si desea una apariencia de alta calidad en la pantalla.
Si es posible, use hardware (por ejemplo, el periférico SPI) para escribir en los registros de desplazamiento y, por supuesto, use una velocidad de reloj relativamente alta. Si lo hace, el tiempo total empleado en la ISR debería ser solo un pequeño porcentaje del ancho de banda del procesador, y dado que se toma en "fragmentos" pequeños, el procesamiento en segundo plano procederá casi como si tuviera un procesador funcionando a, digamos, 12 MHz. en lugar de 16MHz.
Los procesos simples y (relativamente) críticos en el tiempo, como actualizar una pantalla, son exactamente para lo que sirven los ISR. También es un buen momento (mientras se encuentra en una ISR periódica) para escanear los interruptores de entrada en busca de antirrebote, por ejemplo.
Normalmente, los controladores de interrupción se usan para acciones cortas. La razón es que el programa principal se bloquea.
Sin embargo, si el controlador principal no realiza ninguna acción crítica en el tiempo, es un problema menor.
Asegúrese de que el controlador de interrupciones no tarde más que la siguiente llamada de interrupción. Entonces recibe una llamada de interrupción dentro de una llamada de interrupción, etc.
En su caso, su función de actualización probablemente siempre tome el mismo tiempo. Puede medirlo (haga una prueba con 1000 iteraciones y divida el tiempo entre 1000, o 1M es que no puede medirlo). Y conoces la frecuencia de actualización. Entonces sabe cuánto porcentaje (menos algunos gastos generales) queda para su programa principal.
Personalmente, creo que escribir 64 pines GPIO, incluso con registros de desplazamiento, debe hacerse muy rápido, pero probar es mejor que suponer.
cebador
glen_geek