1 votos

Aproximación al golpeo de bits de 8 canales

Estoy buscando controlar unas tiras de LEDs WS2812 5050 RGB desde un microcontrolador. He jugado con éxito con la librería Neopixel de Adafruit y he escrito algo de código en un PIC18F2455 que también he conseguido que funcione para algunas cosas sencillas (cambiar progresivamente de color de rojo, a verde a azul, y viceversa, etc).

Sin embargo, todo eso fue para una sola cadena. Idealmente, ya que estoy usando PORTB en el micro PIC, sería genial usar los 8 bits para manejar hasta 8 cadenas desde un solo chip.

Sí, sé que me estoy volviendo codicioso :)

Mi pregunta es, qué enfoque me recomiendan tomar dado que tengo como máximo el tiempo involucrado para enviar un 1 o un 0 en cualquier canal individual es de unos pocos ciclos de instrucción y el protocolo de señalización es de tipo 1-hilo no estándar por lo que el PIC no tiene un periférico dedicado para descargar el trabajo (enviar un 1 implica 'escribir 1, nop, escribir 0' y enviar un 0 implica 'escribir 1, escribir 0, nop').

Además, es probable que sólo haya como mucho un centenar de ciclos de instrucción entre el final de un bit y el comienzo del siguiente antes de que llegues al "código de fin" de 50us y todo lo que has estado escribiendo se quede enganchado en los LEDs y el protocolo de datos vuelva a esperar el primer bit.

Para una sola cadena he estado tomando los tres bytes para el verde, el rojo y el azul (ese es el orden que usan estas cosas) y haciendo 24 declaraciones "if (green & 0x80) write1(); else write0();" etc. Pero está claro que ese mismo enfoque no va a funcionar para 8 bits a la vez.

Algunas opciones que consideré:

  1. Computar un byte basado en el primer bit del valor verde, luego usar un ensamblaje cuidadosamente elaborado para (a) escribir 0xff en el puerto, (b) escribir el byte computado en el puerto, y luego (c) escribir un 0x00 en el puerto. Repite 23 veces más para el primer LED de cada una de las 8 cadenas, y luego repite de nuevo durante el tiempo que sea necesario para emitir la cadena completa. El único problema es que toda esa computación toma una buena cantidad de ciclos y es muy posible que tome tanto tiempo que termine interfiriendo con su salida.

  2. En lugar de almacenar cada uno de los datos de la cadena de LEDs como una matriz de valores de bytes de PSG y luego calcularlos en el momento de la salida, almacénelos como una matriz de bits "difuminada" (por ejemplo, los datos del LED 1 de la primera cadena se almacenan a través de 24bytes de memoria en el primer bit de cada byte, los de la segunda cadena a través del segundo bit de cada byte, etc). La ventaja es que la salida es muy fácil y rápida, la desventaja es que la carga de trabajo se traslada a la parte de creación del proceso y ahora necesitas funciones para obtener o establecer valores individuales.

¿Qué opinas? ¿Alguien tiene alguna razón por la que haría o no haría alguna de las anteriores? ¿Alguien sabe de algún truco inteligente para "voltear" rápidamente una matriz de 8 bytes para que el byte 1 se convierta en el primer bit de los 8 bytes en el resultado?)

1voto

GetFree Puntos 495

Si los cambios de los valores son poco frecuentes (en relación con la ejecución del protocolo de actualización de los LEDs) el segundo enfoque es claramente más ligero para la CPU (y por lo tanto resulta en una comunicación más rápida).

Tal vez quieras buscar en Google "contadores verticales", que utiliza un enfoque similar para repartir los bits de un número de contadores 'verticalmente' en un número de bytes, con el objetivo de hacer un conjunto rápido de contadores. Creo que la primera vez que oí hablar de esto fue en http://www.dattalo.com/technical/software/pic/vertcnt.html

0voto

Kiran Puntos 320

El actual WS2812 La salida de una sola cadena es rápida de actualizar (cambia 3 bytes), entonces el tiempo para comunicar a todos los LEDs está determinado en su mayoría por el protocolo de señalización de un solo cable propietario.

Al considerar la división de los LEDs en 8 cadenas, se han seleccionado dos enfoques:

  1. Actualización rápida de RGB (cambio de 3 bytes), la mayor parte del trabajo a la salida (ensamblando bits para crear un valor de puerto de 8 bits), y
  2. La mayoría de los trabajos para la actualización de RGB ("almacenarlos como una matriz de bits "manchada" (por ejemplo, los datos del LED 1 de la primera cadena se almacenan en 24 bytes de memoria en el de memoria en el primer bit de cada byte, la segunda cadena en el segundo bit de cada byte, etc.)". cada byte, etc)"), "La ventaja es que la salida es muy fácil y rápida"

Las suposiciones incorporadas en ambos enfoques no son necesariamente ciertas.

En teoría, la duración total de la comunicación de un cero o un uno son diferentes . Así que, en teoría, una cadena de ceros toma menos tiempo transmitir que el mismo número de unos .

Creo que hay suficiente tolerancia en el protocolo para permitir que un cero o un uno utilicen la misma duración. Pero eso es forzar las tolerancias y eliminar la flexibilidad, lo que dificulta la codificación; concretamente hay menos flexibilidad para añadir o eliminar instrucciones.

Sin embargo, la cosa empeora. La primera parte del protocolo tiene la salida de la señal para cero alto durante 2 veces más que uno . Simplemente copiando 8bits a la vez al puerto de salida no funcionará, a menos que todo el puerto sea todo '0' o todo '1'. Para cualquier otra combinación, se necesita más trabajo para manipular la parte correcta del patrón de bits para representar el tiempo más corto '0'.

El protocolo de un solo cable WS2812 es en tiempo real. Los tiempos de transición son inferiores al microsegundo, con un jitter especificado inferior a +/- 1/6 de µs. Así que la construcción de la salida con un 12 MIPS PIC18F2455 se traduce en una fluctuación de menos de +/- 2 instrucciones, si se mantiene dentro de las especificaciones.

Cero tiene el tiempo de señal más corto de 1/3 de µs, con un jitter que significa entre 2 y 6 instrucciones.

Por lo tanto, si se manejan ocho cadenas en paralelo, el ensamblaje de la salida debe ocurrir en menos de 8 instrucciones. Así que creo que ensamblar el patrón de bits de los puertos sobre la marcha no es factible.

Cuando hay 8 cadenas de LEDs, un solo cambio de LEDs sólo requiere la actualización de 1/8 de los LEDs. Por lo tanto, siempre que se cumpla el protocolo, el tiempo entre la actualización del valor del LED y la finalización de la salida podría llevar casi 8 veces más trabajo que la cadena única existente, y aún así es más rápido.

Así que dividir la cadena única en 8 cadenas, y poner cada cadena en un pin del puerto puede tener beneficios significativos, porque la latencia para comunicar las actualizaciones sería 1/8 de una sola cadena, y por lo tanto puede liberar una gran cantidad de ciclos de CPU adicionales.

Sin embargo, tratar de manejar las 8 cuerdas simultáneamente podría estar más allá de la capacidad del PIC18F2455; la única forma sencilla de almacenar el patrón de bits correcto utiliza mucha más memoria, y hay muy pocas instrucciones disponibles para ensamblar patrones sobre la marcha.

Yo empezaría con un "martillo" mucho más grande que un PIC18F2455 si esto es importante.

0voto

Alex Andronov Puntos 178

Si se ejecutan diez instrucciones por microsegundo (40MHz), creo que se podrían cumplir los tiempos requeridos utilizando un bucle como:

    movlw 0xFF
LP:
    movwf PORTB,c
    nop
    nop
    nop
    movff POSTINC0,PORTB
    nop
    clrf  PORTB,c
    infsnz Ctr1,f,c
    incfsz Ctr2,f,c
     goto LP

Si he calculado bien las cosas, un "1" será 700ns+500ns, mientras que un cero será 400ns+800ns. Todos los tiempos estarán dentro de los 150ns del nominal, que es la tolerancia especificada.

Por cierto, sería más útil que la hoja de datos especificara la tolerancia de entrada y de salida por separado, ya que es probable que si uno acciona el primer dispositivo de una cadena con una señal que está cerca del borde de la tolerancia especificada, algunos aspectos de la sincronización de salida son aptos para estar fuera de la banda de tolerancia especificada, pero la hoja de datos no dice cuán precisa sería la salida.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X