Cómo detener la fuga de corriente en la matriz LED

Sé que este tema se ha discutido en este foro, pero soy un principiante en electrónica y no pude encontrar una solución a mi problema leyendo los hilos relacionados.
Estoy haciendo una matriz Led de 3x5 (los cátodos están conectados en fila):

ingrese la descripción de la imagen aquí

Usé una raspberry Pi B+ con un expansor GPIO MCP23017, resistencias de 1000 ohmios y LED de 5 mm (20 mA, 3,2 V). Usé 1000 ohmios solo porque esto es lo que tenía. Enciendo un LED a la vez (creo que esto se llama multiplexación). Este es mi código para mostrar el dígito 2:

import smbus
import time

bus = smbus.SMBus(1)
bus.write_byte_data(0x20, 0x00, 0x00)#setting GPIOs of bank A as outputs
bus.write_byte_data(0x20, 0x01, 0x00)#setting GPIOs of bank B to outputs

MATRIX = [[1, 1, 1], [0, 0, 1], [1, 1, 1], [1, 0, 0], [1, 1, 1]]

for k in range(100):
   for irow, valr  in enumerate(MATRIX):
       for icol, valc in enumerate(valr):

           A = [0, 0, 0, 0, 0, 0, 0, 0] #the 8 bits to send to bank A of MCP23017
           A[7-icol] = 1 #anode of LED to light up set to HIGH

           B = [1, 1, 1, 1, 1, 1, 1, 1] #the 8 bits to send to bank B of MCP23017
           B[7-irow]=0   #cathode set to LOW

           bus.write_byte_data(DEVICE, 0x12, append(int(''.join(str(e) for e in A), 2))) #bank A

           bus.write_byte_data(DEVICE, 0x13, append(int(''.join(str(e) for e in B), 2))) #bankB

           time.sleep(0.001)

Algunos LED se encendieron a pesar de que no se les 'indicó'. Por lo que leí en línea, esto se debe a una fuga de corriente. Por ejemplo, este es un dos:

ingrese la descripción de la imagen aquí

¿De dónde viene el problema? :
- el código?
- La forma en que conduzco los LED (¿debo agregar transistores? (¿y por qué?), ¿debo cambiar el valor de las resistencias? ¿debo agregar resistencias pull-up/down?)

Intenté alternar entre un LED ENCENDIDO y luego todos los LED APAGADOS (configuré todos los GPIO en '0'), pero eso no resolvió el problema.

Respuestas (4)

Con ese expansor, se requieren 2 transacciones de bus I2C para cambiar los bancos A y B. Suponiendo que el I2C se ejecuta a 100 kHz, cada escritura tomará al menos 26 mS (dirección de 8 bits, datos de 8 bits, 2 bits ACK, inicio y parada). Agregue la sobrecarga de código de la ejecución de Python, supongo que está más cerca de 50 mS por escritura.

Parece que tiene un retraso de bucle de 1000 mS, por lo que durante aproximadamente 1/20 del tiempo de bucle, ha cambiado el banco A pero aún no ha cambiado el banco B. Supongo que los LED están produciendo suficiente luz durante el 1/20 para ser visibles.

Intente agregar una escritura más al ciclo: gire todo el banco B primero, antes de configurar los bits en A y luego en B. Esto debería apagar los LED mientras el banco A está cambiando.

Está utilizando i2c para comunicarse con el expansor GPIO.

I2C es relativamente lento, por lo que habrá cientos de microsegundos entre los comandos para escribir en el dispositivo 0x12 y 0x13.

Durante ese tiempo, la salida del expansor GPIO en 0x12 se establecerá en los nuevos datos, pero 0x13 seguirá siendo de los datos anteriores; esto puede provocar que se enciendan LED no deseados.

Una forma de resolver esto es escribir cero en 0x12 para apagar los LED, luego escribir 0x13 con nuevos datos y luego escribir el valor deseado en 0x12.

A menudo, cuando se utilizan LED multiplexados, puede haber problemas causados ​​por retrasos en el software o simplemente por el tiempo que tardan las señales del hardware en estabilizarse y requerirán enfoques similares para evitar el problema.

No debería haber fugas: los diodos en la fila 'apagado' tienen polarización inversa. Prueba a comprobar estas cosas:

  • Asegúrate de tener el pull-up deshabilitado

  • Intente generar las filas una a la vez, lentamente, para ver si la secuencia es correcta.

¿Cómo verifico que el pull-up esté deshabilitado (¿pull-up del MCP23017?). En cuanto a la salida de las filas, sí, me aseguré de emitir un LED a la vez y la secuencia es correcta (en realidad, enciendo un LED a la vez, quiero decir: por ejemplo, para la primera fila del dígito 2 que mostré allí, No encendí los 3 LED al mismo tiempo, sino un LED a la vez))
Los bits de habilitación de extracción están en GPPUA. Asegúrate de que estén apagados. En cuanto a la secuencia de LED, hacer 3 a la vez debería estar bien. Desde una perspectiva de E/S, poner las 8 señales en el mismo conjunto GPIO sería aún más eficiente.
Establecí todos los bits de extracción en 0: bus.write_byte_data(0x20, GPPUA, 0x00), con GPPUA=0x06, pero esto no resolvió el problema. Hice lo mismo para GPPUB, pero el problema persiste.
¿Quizás algo de corrupción en tu I2C? Intente encender 3 a la vez y vea si las cosas son diferentes.
Gracias por sus prontas respuestas. Encendí una fila completa sin problemas, luego encendí una columna completa sin problemas, no creo que haya un problema con I2C.
Este enlace puede ser útil. Mismo IC, matriz más grande, R-pi. electronicsforu.com/electronics-projects/hardware-diy/…

Doyxlover y Kevin White tienen razón sobre la causa y su sugerencia funcionará.

Pero una mejor solución sería algo como:

for k in range(100):
   for irow, valr  in enumerate(MATRIX):

       # Enable the output for this row
       B = [1, 1, 1, 1, 1, 1, 1, 1] #the 8 bits to send to bank B of MCP23017
       B[7-irow]=0   #cathode set to LOW
       bus.write_byte_data(DEVICE, 0x13, append(int(''.join(str(e) for e in B), 2))) #bankB

       for icol, valc in enumerate(valr):

           A = [0, 0, 0, 0, 0, 0, 0, 0] #the 8 bits to send to bank A of MCP23017
           if valc:
               A[7-icol] = 1 #anode of LED to light up set to HIGH
           bus.write_byte_data(DEVICE, 0x12, append(int(''.join(str(e) for e in A), 2))) #bank A

           time.sleep(0.001)

       # Disable the output
       A = [0, 0, 0, 0, 0, 0, 0, 0] #the 8 bits to send to bank A of MCP23017
       bus.write_byte_data(DEVICE, 0x12, append(int(''.join(str(e) for e in A), 2))) #bank A

Este código está optimizado para evitar escrituras innecesarias. Solo necesita configurar el banco B y borrar el banco A una vez para cada fila, no una vez para cada píxel.

De hecho, si su IC es lo suficientemente potente como para conducir una fila completa a la vez (no lo he comprobado), entonces puede hacer lo siguiente:

for k in range(1000):
   for irow, valr  in enumerate(MATRIX):

       # Enable the output for this row
       B = [1, 1, 1, 1, 1, 1, 1, 1] #the 8 bits to send to bank B of MCP23017
       B[7-irow]=0   #cathode set to LOW
       bus.write_byte_data(DEVICE, 0x13, append(int(''.join(str(e) for e in B), 2))) #bankB

       A = [0, 0, 0, 0, 0, 0, 0, 0] #the 8 bits to send to bank A of MCP23017
       for icol, valc in enumerate(valr):
           if valc:
               A[7-icol] = 1 #anode of LED to light up set to HIGH

       # Light up all the wanted LEDs in this entire row.
       bus.write_byte_data(DEVICE, 0x12, append(int(''.join(str(e) for e in A), 2))) #bank A

       time.sleep(0.001)

       # Disable the outputs
       A = [0, 0, 0, 0, 0, 0, 0, 0] #the 8 bits to send to bank A of MCP23017
       bus.write_byte_data(DEVICE, 0x12, append(int(''.join(str(e) for e in A), 2))) #bank A

Si funciona, debería ser significativamente más brillante ya que cada LED puede estar encendido hasta 1/5 del tiempo en lugar de 1/15 del tiempo.

Tenga en cuenta que habilitar varios LED a la vez en el banco A está bien, ya que las resistencias están conectadas a los pines del banco A, por lo que tiene una resistencia por LED encendido. No puede habilitar varios LED a la vez en el banco B, o más bien, si lo hiciera, habría una resistencia compartida entre varios LED que haría que esos LED fueran más tenues que el resto.

(Y sé que esta es una vieja pregunta, pero ocupa un lugar destacado en los motores de búsqueda, por lo que dejo una mejor respuesta aquí para ayudar a los futuros buscadores).