Arduino Avago LedDisplay Bug, Fixed
Comentaba en un post anterior mis desventuras con una pantallita de leds en la que tenía que usar un hack para poder visualizar lo que queria.
La librería LedDisplay tiene un contador de posición del ‘cursor’ en la pantalla que al crear el objeto se fija a cero. Una pantalla de 8 caracteres tendría posiciones de la cero a la siete mientras que una de 4 caracteres tendría posiciones de la cero a la tres; al crear el objeto de pantalla se fija el cursor en la posición cero y según vamos escribiendo en la pantalla el cursor va incrementando. Usando el método objeto.home() volvemos a la posición cero, pero a mi no me funcionaba, me mostraba la pantalla en blanco, por lo que tras unas cuantas pruebas descubrí que tenía que usar como cero la posición 4 con objeto.setCursor(4); en otras palabras, no conseguía visualizar nada si no empezaba a escribir desde la posicion 4 hasta la 7 definiendo el display de longitud 8.
El trabajo interno de la librería consiste en traducir los carácteres en cinco columnas de información de un byte cada una (recordemos que cada posicion de la pantalla es una matriz de leds de cinco columnas por siete filas) de forma que si tenemos una pantalla de ocho caracteres tendríamos que enviar cinco por ocho bytes, es decir, cuarenta.
Basandose en este razonamiento el desarrollador de la librería la programó con un array de longitud cuarenta en donde la posición del cursor se calcula multiplicandola por cinco, así si queremos escribir un carácter en la posición 4 de la pantalla, la multiplicamos por 5 y obtenemos como índice del array 20, posición a partir de la que empezamos a escribir.
Tras pensarlo detenidamente y estudiar el uso de registros de desplazamiento para crear conversores serie-paralelo se me ocurrió que la pantalla actuaba tal cual como un registro de desplazamiento y que al enviarle 40 bytes (para pantalla de 8) en lugar de 20 bytes realizaba un desbordamiento que en teoría saldría por la patilla ’data out’ de la pantalla (empleada para el montaje en cascada de varias pantallas).
La solución vino con limitar la cantidad de bytes enviados a través del bus de datos en función de la longitud de la pantalla. El parche para la librería es este:
--- LedDisplay_orig/LedDisplay.cpp 2009-04-17 22:12:49.000000000 +0200 +++ LedDisplay/LedDisplay.cpp 2009-10-06 18:05:14.000000000 +0200 @@ -250,12 +250,14 @@ // this method sends 320 bits to the dot register: void LedDisplay::loadDotRegister() { + // define max data to send, patch for 4 length displays by KaR]V[aN + int maxData = displayLength * 5; // select the dot register: digitalWrite(registerSelect, LOW); // enable writing to the display: digitalWrite(chipEnable, LOW); // shift the data out: - for (int i = 0; i < 40; i++) { + for (int i = 0; i < maxData; i++) { shiftOut(dataPin, clockPin, MSBFIRST, dotRegister[i]); }
Happy Hacking