WS2811 se puede dirigir a 800 kHz por reloj de 8 MHz

Óscar Soto
Óscar Soto

La sincronización lo es todo y es por eso que la mayoría de los protocolos de comunicación requieren una fuente de reloj muy precisa. Los controladores LED WS2811 no son diferentes. Pero [Danny] descubrió una manera de manejarlos de manera confiable a través de una fuente de reloj de 8MHz.

El WS2811 se ha convertido en uno de los controladores más populares para píxeles y rayas RGB. Vimos varios trucos utilizados para tratar con ellos, incluida la técnica AVR de 16 MHz que inspiró [Danny] asumir este proyecto. Planeaba usar esa biblioteca, pero el tiempo de envío de 25 días para un cristal de 16MHz condujo a casa para encontrar una manera de usar el oscilador interno en su lugar.

La esencia del truco es que escribió código ensamblador para manejar pares de valores de bits binarios. Con un bloque de código para cada una de las cuatro combinaciones posibles en la mano, tuvo que encontrar una manera de crear los saltos condicionales para mantener una sincronización precisa. Después de chocar contra la pared mientras trataba de resolver este rompecabezas a mano, escribió un programa en C ++ para resolverlo en casa. La prueba está en este video, que muestra un chip que maneja varios escáneres Larson en una tira.

  • Paul Stoffregen dice:

    Es una buena escritura.

    Supongo que probablemente no haya notado que la biblioteca Neopixel de Adafruit ya admite tiras WS2811 en Arduinos basados ​​en AVR de 8 y 16 MHz. Usan casi el mismo enfoque. Pero no escribieron una página wiki tan hermosa con los detalles técnicos …

    También vi su página de salida paralela. Para que lo sepas ahora, la biblioteca OctoWS2811 (que escribí y mencioné ayer aquí en HaD) hace esto, con casi cero uso de CPU por parte del controlador DMA en una parte ARM de 32 bits. OctoWS2811 utiliza el formato de transmisión que describió. Mi código basado en ARM probablemente no sirva de nada en AVR, ya que no hay un controlador DMA … pero escribí un buen programa de procesamiento para transmitir un video al mismo tiempo a cualquier número de placas en ese formato transmitido. Incluso si no transmite videos, ese código podría ayudarlo a obtener algunos datos en el formato transmitido.

    • Dhavenith dice:

      Gracias Paul,
      De hecho, he visto su OctoWS2811 y tengo la intención de estudiarlo detenidamente.
      No sabía que la biblioteca de Neopixel también admite 8Mhz, mientras tanto me golpearon 🙂

    • cpldcpu dice:

      De hecho creo que os gané a los dos 🙂

      Trabajé en la biblioteca lws2812 para el AVR durante un tiempo después de no estar satisfecho con las soluciones existentes. La mayoría de las implementaciones dependen de las bibliotecas de plantillas creadas c ++ (fastspi lib) o de bucles no envueltos. Ambos conducen a una gran huella de memoria. Además, las instrucciones que no son compatibles con todos los AVR se utilizan comúnmente (como MUL o CBI / SBI).

      Puede encontrar mi implementación aquí: https://github.com/cpldcpu/light_ws2812

      Hasta 8 MHz, todas las rutinas se enlazan con una huella de memoria inferior a 50 bytes. Como bono especial, logré implementar una versión de 4 MHz, que desafortunadamente tiene que depender del desenrollado del bucle.

      Ayer también se envió soporte desde ws2812 a little-wire, lo que permite controlar las tiras WS2812 a través de USB en el humilde ATTiny85.

      http://littlewire.cc/
      Experimental v1.2 aquí:
      https://github.com/kehribar/Little-Wire/tree/danger/v1.2

      • Dhavenith dice:

        Miré la función ws2812_sendarray_mask bajo el ifdef ws2812_8MHz. El tiempo de bytes me parece correcto y en realidad es agradable y compacto, aunque el bucle while introduce retrasos entre bytes y eso está fuera de las especificaciones. Cómo [Alan Burlison] escribió en su entrada de 16Mhz, que puede funcionar en algunas tiras de led y fallar en otras.

        • cpldcpu dice:

          Hola,
          gracias por tus comentarios! Según mis experimentos, la parte crítica del tiempo es entre el borde ascendente y el descendente. Supongo que el controlador hace que dispare un monoflope en el borde ascendente y luego prueba la entrada después de ~ 0.5µs. El tiempo entre el borde descendente y el ascendente activa el estado de restauración, que parece ocurrir en cualquier lugar entre 5 µs y 50 µs. Eso significa que hay un poco de tolerancia con el tiempo de la última parte.

          Sería posible lograr fácilmente una sincronización perfecta para la versión de 8Mhz con desenrollado de bucle como en la versión de 4Mhz. Pero eso cuesta mucho espacio de código. Hasta ahora no he visto ningún problema, pero hasta ahora solo lo he probado en tiras cortas. Me interesaría recibir sugerencias si hay algún problema.

          Lograr una sincronización perfecta para la versión de 4Mhz es casi imposible, ya que solo queda un ciclo por bit, y algún día tendrás que hacer ese molesto salto de 2 ciclos …

    • Dhavenith dice:

      Acabo de ver mejor a Neopixel. [Paint Your Dragon] logró hacer lo mismo con menos código. Simplemente desenvolvió el bucle de bits y eso es todo, realmente no necesita la entrada extensa porque es muy simple.

      ¡Maldita seas, Lady Ada y tus brillantes amigos!

      (quién hubiera pensado que alguien podría pronunciar esa frase en el siglo XXI).

    • Champiñón dice:

      Supongo que nadie me dijo que se suponía que eso era difícil. 🙂

      Tenía mis WS2811 funcionando en ATtiny85 de 8 MHz aproximadamente una hora después de que llegara mi tira de LED. No se requiere lenguaje ensamblador excepto NOP.

      Todavía uso el mismo código hoy (aunque ahora también es compatible con 16 MHz …)

      Bosquejo de demostración: http://www.artlum.com/arduino/WS2811_demo.7z

      Escribí una versión en lenguaje ensamblador porque quería reproducir una muestra de sonido de 8kHz mientras actualizaba los LED (un poco más difícil a 8MHz).

      • Dhavenith dice:

        Su tiempo de bits parece estar bien, pero hay una gran brecha entre los bits con “b = b + b”, “if (* b & 0x80) …” y “while (–i! = 0)” y todo. Tal vez esto funcione para sus LED, pero el tiempo no es específico y esto puede (y supongo) fallar en otros casos.

        [Alan Burlison]La entrada destacada dedica un texto a por qué le gustaría permanecer en horarios específicos

        • Champiñón dice:

          AFAIK, la hoja de datos no dice nada sobre el tiempo entre bits. El chip busca un borde ascendente al comienzo de un bit y comienza a contar desde allí. El tiempo de bits anterior no parece crítico. En las pruebas agregué el bucle for () contando hasta 7 entre bits y el chip todavía estaba contento.

          Usé este código en tiras LED largas, algunas WS2811 de montaje en superficie, incluso WS2811 en el paquete DIP8. Siempre funcionó.

          • cpldcpu dice:

            Estoy de acuerdo con ésto. Es casi seguro que el chip sea un diseño asincrónico, que se mide por el margen creciente de datain. Así que toda la charla sobre “jitter” es bastante inútil …

          • Champiñón dice:

            El chip * debe * ser capaz de detectar un flanco ascendente y usarlo para procesar un bit; no funcionaría de otra manera porque el primer bit de los 24 siempre llega en un momento desconocido.

            Si el chip tiene esa capacidad, entonces no tiene mucho sentido que aplique repentinamente una sincronización estricta a todos los bits posteriores. Lo más fácil es utilizar la misma lógica que para el primer bit.

  • Chris C. dice:

    Una forma ordenada de graficar y desarrollar el código, disfruté viéndolo. Aunque se trata de 4 escáneres Larson en la demostración, con la tira en un semicírculo me recuerda a Upcoming Encounters.

  • mikeelectricstuff dice:

    ¿25 días para un oscilador? en que planeta Estas?

    • topógrafo dice:

      Su comentario sobre “25 días es mucho tiempo” fue simplemente un humor seco e ingenioso. En ese contexto, su sarcasmo sardónico es irónicamente trágico.

      ¿Eres el Mike Harrison “real” o simplemente un pretendiente?
      http://www.theamphour.com/get-your-questions-in-for-mike-harrison-of-mikes-electric-stuff/

      • Dhavenith dice:

        De hecho, 20-25 días parece ser una entrega máxima ligeramente estándar de un vendedor de Hong Kong en eBay a Europa continental. Normalmente, los productos llegan mucho antes, pero en este caso, los osciladores tardaron semanas en llegar. Lo cual fue algo bueno, porque realmente solo necesitaba una buena excusa.

        Pero ahora tengo 10 osciladores sin usar por ahí …

        • Taniwha dice:

          ¿25 días? Pedí algo a Digikey hace unos meses, pagué por fedex, una maldita cosa el mes pasado en una instalación de clasificación en Memphis, de regreso a Mouser, que al menos se enviará a Nueva Zelanda desde Hong Kong, los pedidos llegarán en 2-3 días. .

      • pretendiente dice:

        Ja, ¿quién es sarcástico, sarcástico y trágico ahora? 🙂

        • Dhavenith dice:

          Y de nuevo, mi _comentario_ sobre los 25 días _fue_ una prueba de ingenioso humor seco.

          Ahora juega bien, querido 🙂

  • Champiñón dice:

    ¿Lo es? He estado usando estos a 8MHz ATtiny85 desde aproximadamente una hora después de que obtuve mi primera tira, no se necesita lenguaje ensamblador.

    • Erik Johnson dice:

      ¿A 800 MHz o 400 MHz de vapor de datos?

      • Champiñón dice:

        800 MHz

        • Erik Johnson dice:

          Hz *, lo siento. ¿Tiene que usar bucles desenrollados enormes si no usa ASM …?

          • Champiñón dice:

            El código está aquí: http://www.artlum.com/arduino/WS2811_demo.7z

            Sin bucles desenrollados (grandes u otros) y no se requiere ASM.

          • Paul Stoffregen dice:

            Ese comentario podría ser sobre qué tan rápido sería 800 MHz, 1000 veces más rápido que 800 kHz, o más bien 800 kbits / seg que requiere el chip WS2811.

          • Erik Johnson dice:

            1 bit = 1 Hz. Semántica.

          • Erik Johnson dice:

            Necesita echar un vistazo más de cerca a su archivo ws2811.h …
            #define NOP __asm ​​__ (“nop n t”)
            y varios usos de su declaración NOP para respaldar ese problema de tiempo que el nativo C tiende a encontrar.

          • cpldcpu dice:

            Mushroom: Lo que haces en ws2812.h es la definición de desenrollado de bucle. Su código es enorme y puede romperse con cualquier cambio en las condiciones del compilador. Este es un truco limpio.

            Pero oh, mira dónde estamos … 🙂

          • Champiñón dice:

            Puedo cambiar el “NOP” a “LED_PIN = 0” si a los pedantes les agrada … me da lo mismo.

          • Champiñón dice:

            El único punto que traté de notar es que conducir un WS2811 con un chip AVR de 8 MHz no es particularmente difícil. Cuando apareció aquí como una especie de milagro, me hizo levantar una ceja.

          • Erik Johnson dice:

            Jaja, no, estoy de acuerdo con eso

          • Champiñón dice:

            Sin embargo, * ES * una buena optimización. Esos pocos ciclos de reloj adicionales podrían ser útiles si está tratando de manejar grandes cadenas de LED.

  • Zac dice:

    Esto ya está hecho.

    Y luché mucho para revisar la reunión en línea.

    ¿Dónde estabas cuando te necesitaba? 🙁

    • cpldcpu dice:

      Bueno, no estoy seguro de si a alguien todavía le importa en este momento. PERO: Actualicé mi biblioteca ligera WS2812. Casi todas las rutinas cumplen ahora especificaciones de tiempo específicas, hasta un reloj de procesador de 4 MHz. También estoy seguro de que la biblioteca ofrece
      la traza de tamaño de código más pequeña de todas las soluciones disponibles.

      Encuentra v0.7 aquí:

      https://github.com/cpldcpu/light_ws2812/tree/master/light_ws2812

  • Victor Påsse dice:

    Comencé ws2812 con uart a 4Mbps, puede dejar usar SPI a 3.2Mbps.
    Conduje el ws2812 desde una imagen de 8 pines, la imagen puede tener un framebuffer de 68 unidades para color de 24 bits y 100 leds para color de 16 bits, esto es con RAM de 256 bytes, la RAM es el único límite.

    • Stanko Stankov dice:

      Hola
      Estoy tratando de escribir un programa para pic16f877a que ejecute WS2812B, estoy usando un oscilador de 20 MHz, ¿pueden ayudarme por favor?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *