Aproximación a bit de 8 canales

1

Estoy tratando de controlar algunas tiras de LED WS2812 5050 RGB desde un microcontrolador. He jugado con éxito con la biblioteca Adafruit Neopixel y he escrito un código en un PIC18F2455 en el que también he empezado a trabajar para algunas cosas simples (cambian progresivamente de color de rojo a verde, y de nuevo, etc.). p>

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

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

Mi pregunta es, qué enfoque recomendaría tomar, dado que a lo sumo tengo el tiempo necesario para enviar un 1 o un 0 en cualquier canal individual; algunos ciclos de instrucción y el protocolo de señalización no es estándar de 1 cable. escriba el protocolo para que el PIC no tenga 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 solo haya como máximo cien ciclos de instrucción entre el final de un bit al comienzo del siguiente antes de que llegue al "código final" de los 50us y todo lo que ha estado escribiendo se engancha a los LED y al el protocolo de datos vuelve a esperar al primer bit de nuevo.

Para una sola cadena, acabo de tomar los tres bytes para verde, rojo y azul (ese es el orden en que se usan estas cosas) y hacer 24 "si (verde y 0x80) write1 (); else write0 () " declaraciones etc. Pero claramente ese mismo enfoque no funcionará para 8 bits a la vez.

Algunas opciones que consideré:

  1. Calcular un byte basado en el primer bit del valor verde, luego usar un ensamblaje cuidadosamente diseñado para (a) escribir 0xff en el puerto, (b) escribir el byte calculado en el puerto, y luego (c) escribe un 0x00 en el puerto. Enjuague y repita 23 veces más para el primer LED en cada una de las 8 cadenas, luego repítalo nuevamente por el tiempo que demore la salida de toda la cadena. El único problema es que la computación toma una buena cantidad de ciclos y es muy posible que demore tanto que termine interfiriendo con su salida.

  2. En lugar de almacenar cada uno de los datos de la cadena de led como una matriz de valores de bytes GRB y luego calcularlos en el tiempo de salida, almacénelos 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 primer bit de cada byte, la segunda cadena en el segundo bit de cada byte, etc. La ventaja es que la salida es fácil y rápida, la desventaja es que la carga de trabajo se transfiere a la parte de creación del proceso y ahora necesita funciones para obtener o establecer valores individuales.

¿Pensamientos? ¿Alguien tiene alguna razón por la que harías o no harías algo de lo anterior? ¿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? :)

    
pregunta Jon Kloske

3 respuestas

1

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

Es posible que desee buscar "contadores verticales" en Google, que utiliza un enfoque similar para difundir los bits de varios contadores 'verticalmente' sobre varios bytes, con el objetivo de hacer un conjunto rápido de contadores. Creo que escuché esto por primera vez en enlace

    
respondido por el Wouter van Ooijen
0

El WS2812 existente es rápido de actualizar (cambia 3 bytes), entonces la hora La comunicación a todos los LED está determinada principalmente por el protocolo de señalización de un solo cable patentado.

Al considerar dividir los LED entre 8 cadenas, ha seleccionado dos enfoques:

  1. Actualización RGB rápida (cambio de 3 bytes), la mayoría de los trabajos se imprimen (se ensamblan bits para crear un valor de puerto de 8 bits), y
  2. La mayoría de los trabajos para la actualización 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 primer bit de cada byte, segunda cadena a través del segundo bit de cada byte, etc.) ")," La salida de Advantage es muy fácil y rápida "

Las suposiciones integradas en ambos enfoques no son necesariamente ciertas.

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

Creo que hay suficiente tolerancia en el protocolo para permitir que un cero o uno use la misma duración. Pero eso es empujar las tolerancias y eliminar la flexibilidad, lo que dificulta el código; específicamente, hay menos flexibilidad para agregar o eliminar instrucciones.

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

El protocolo de un cable WS2812 es en tiempo real. Los tiempos de transición son microsegundos secundarios, con una fluctuación especificada menor a +/- 1 / 6th µs. Entonces, construir la salida con un 12 MIPS PIC18F2455 se traduce en un jitter de menos de +/- 2 instrucciones , si es para mantenerse dentro de las especificaciones.

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

Entonces, si se ejecutan ocho cadenas en paralelo, el montaje de la salida debe realizarse 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 LED, un solo cambio de LED solo requiere que se actualice 1/8 de los LED. Por lo tanto, siempre que se pueda cumplir con la temporización del protocolo, el tiempo entre la actualización del valor del LED y la finalización de la salida puede requerir casi 8 veces más trabajo que la cadena única existente, y aún es más rápido.

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

Sin embargo, intentar manejar todas las 8 cadenas simultáneamente puede estar muy por encima de la capacidad del PIC18F2455; La única forma sencilla de almacenar el patrón de bits correcto es usar mucha más memoria, y hay muy pocas instrucciones disponibles para ensamblar los patrones de la marcha.

Comenzaría con un 'martillo' mucho más grande que un PIC18F2455 si esto es importante.

    
respondido por el gbulmer
0

Si uno está ejecutando 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 calculé las cosas bien, un "1" será 700ns + 500ns, mientras que un cero será 400ns + 800ns. Todos los tiempos estarán dentro de 150 ns de nominal, que es la tolerancia especificada.

Por cierto, sería más útil si la hoja de datos especificara la tolerancia de entrada y salida por separado, ya que es probable que si uno maneja el primer dispositivo en una cadena con una señal cercana al límite de la tolerancia especificada, algunos aspectos de la salida los tiempos tienden a estar fuera de la banda de tolerancia especificada, pero la hoja de datos no dice qué tan precisa sería la salida.

    
respondido por el supercat

Lea otras preguntas en las etiquetas