Poco golpes paso a paso: Arduino control de LEDs RGB de WS2812B, WS2811 y WS2812 (5 / 5 paso)

Paso 5: Bitbanging una onda de pulso en un microcontrolador ATMega328p

Una de las ventajas de utilizar un microcontrolador como opuesto a, para decir una computadora CPU, es que tenemos un muy estricto control sobre el momento de las instrucciones que programa en él.  De hecho, para mostrar cómo precisa que el control puede ser, usaremos instrucciones de montaje en lugar de las típicas funciones de alto nivel como digitalWrite.  El uso de conjunto nos permite conocer exactamente cuántos ciclos de reloj se toman durante la ejecución de cada instrucción.

Desde la Junta de desarrollo de Arduino Uno R3 mantiene una señal de reloj externa de 16MHz en el ATMega328p a bordo, el microcontrolador ejecuta una ciclo de reloj 1 instrucción en exactamente 62.5ns (1/16 MHz = 62.5ns).  Ya que podemos averiguar cuántos ciclos de reloj cada instrucción toma, precisamente podemos controlar cómo muchas instrucciones que necesitamos para generan nuestra señal.

Como vimos anteriormente, con el fin de transmitir un 1 en el chip WS281X debemos transmitir una señal de que se mantiene en un valor máximo (HIGH) para 0.8μs y luego se queda en un valor mínimo (LOW) para 0.45μs.  Por lo tanto, queremos escribir una lista de instrucciones que:

-Set pin digital a alta
-Esperar 0.8μs
-Pin digital se establece en bajo
-Espera 0.45μs

En lenguaje ensamblador, esto puede lograrse por el siguiente código:

(volátiles) ASM
Instrucciones reloj Descripción fase bits transmitidos
"OSE %0, %1\n\t" / / 2 PIN alto (T = 2)
"rjmp. + 0\n\t" / / 2 nop nop (T = 4)
"rjmp. + 0\n\t" / / 2 nop nop (T = 6)
"rjmp. + 0\n\t" / / 2 nop nop (T = 8)
"rjmp. + 0\n\t" / / 2 nop nop (T = 10)
"rjmp. + 0\n\t" / / 2 nop nop (T = 12)
"nop\n\t"               // 1      nop                (T = 13)
"cbi %0, %1\n\t" / / 2 PIN bajo (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"rjmp. + 0\n\t" / / 2 nop nop (T = 19)
"nop\n\t"               // 1      nop                (T = 20)      1
::
Entrada operandos
"I" (_SFR_IO_ADDR(PORT)), //%0
"I" (PORT_PIN) //%1
);

Instrucción
La primera columna incluye las instrucciones de montaje seguida por un salto de línea y ficha caracteres, que el ensamblador final listado generado por el compilador más legible.

Reloj
La segunda columna muestra el número de ciclos de reloj que toma cada instrucción.  Para este conjunto de instrucciones simple hay sólo un valor posible, que veremos más adelante cómo algunas instrucciones (por ejemplo, condicional) pueden tener 1, 2 o 3 valores posibles.  Recuerde que cada ciclo de reloj en los 16 MHz Arduino Uno toma 62.5ns.

Descripción
La tercera columna muestra una muy breve descripción de lo que hace cada operación.

Fase
Usar el término un poco libremente, lo usamos para indicar la suma acumulativa de ciclos de reloj por las instrucciones que han sido ejecutadas hasta el momento.

Para enviar un único valor de 255: 11111111 en binario, a la WS281X tenemos que repetir este conjunto de instrucciones 8 veces.  Además, si insertamos un 50μs (o mayor) entre las transmisiones de la secuencia de 8 bits, la WS281X engancha los datos transmitidos a su registro de salida.  Una vez que los datos están bien cerrados, el primer LED (verde) de la WS281X debe encender a un nivel de brillo máximo.  El sketch de Arduino dentro de bitbang_255.zip muestra esta operación.

Para enviar un 0 que necesitamos cambiar el código que produce un 1 al disminuir el tiempo durante el cual la señal tiene un alto valor (máximo) y aumentar el tiempo durante el cual la señal es baja (como mínimo).  Además, debemos señalar que los valores de cada LED deben siempre especificarse usando 8 bits.  Por ejemplo, si quisiéramos enviar un valor de 105 — 1101001 en binario, tenemos que enviar los 8 bits 01101001 incluyendo el 0 inicial.  El código que produce un 0 se parece:

(volátiles) ASM
Instrucciones reloj Descripción fase bits transmitidos
"OSE %0, %1\n\t" / / 2 PIN alto (T = 2)
"rjmp. + 0\n\t" / / 2 nop nop (T = 4)
"rjmp. + 0\n\t" / / 2 nop nop (T = 6)
"cbi %0, %1\n\t" / / 2 PIN bajo (T = 8)
"rjmp. + 0\n\t" / / 2 nop nop (T = 10)
"rjmp. + 0\n\t" / / 2 nop nop (T = 12)
"rjmp. + 0\n\t" / / 2 nop nop (T = 14)
"rjmp. + 0\n\t" / / 2 nop nop (T = 16)
"rjmp. + 0\n\t" / / 2 nop nop (T = 18)
"rjmp. + 0\n\t" / / 2 nop nop (T = 20) 0
::
Entrada operandos
"I" (_SFR_IO_ADDR(PORT)), //%0
"I" (PORT_PIN) //%1
);

Podemos usar el sketch de Arduino dentro de bitbang_105.zip para generar la señal cuya imagen se puede ver en las capturas de pantalla de osciloscopio que se unen a este paso.

Ahora, para que el WS281X mostrar el color blanquecino que queremos, tenemos que enviar 255 valores no uno, sino tres, en cuyo caso la señal consiste en 24 unos — sin esperar los 50μs para los datos de cierre.  Podríamos hacer esto copiando-pegando las once instrucciones sobre 23 veces (usted puede probar modificar el bosquejo del bitbang_255.ino).  Pero el código sería poco práctico para el envío de valores a más de uno WS281X chips.  Una mejor solución sería escribir un bucle que se recorra en iteración los valores de 8 bits hasta las tres de ellos han sido enviadas.

El bosquejo dentro de bitbang_whitish.zip incluye una descripción clara de las medidas adoptadas para lograr el resultado deseado.  La sección principal, escrita en conjunto siguiendo la lógica descrita anteriormente, se ve como sigue:

(volátiles) ASM
Fase de descripción de reloj de instrucciones
"nextbit:\n\t"              // -    label                                     (T =  0)
"OSE %0, %1\n\t «/ 2 señal alta (T = 2)
"sbrc %4, 7\n\t" / / 1-2 si MSB establecida (T =?)
"mov 6 %, %3\n\t" / / 0-1 tmp te fije señal alta (T = 4)
«Dic %5\n\t» / / 1 disminución bitcount (T = 5)
"nop\n\t" / / 1 nop (ciclo de 1 reloj inactivo) (T = 6)
"st % a2, %6\n\t" / / 2 puerto para tmp (T = 8)
"mov 6 %, %7\n\t" / / 1 reset tmp para bajo (predeterminado) (T = 9)
"breq nextbyte\n\t" / / 1-2 si bitcount == 0 -> nextbyte (T =?)
"rol %4\n\t" / / 1 MSB de cambio hacia la izquierda (T = 11)
"rjmp. + 0\n\t" / / 2 nop nop (T = 13)
"cbi %0, %1\n\t" / / 2 señal baja (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"nop\n\t"                  // 1    nop                                        (T = 18)
"rjmp nextbit\n\t" / / 2 bitcount! = 0 -> nextbit (T = 20)
"nextbyte:\n\t"          // -    label                                       -
"ldi %5, 8\n\t" / / 1 reset bitcount (T = 11)
"ld   %4, %a8+\n\t" // 2    val = *p++                             (T = 13)
"cbi %0, %1\n\t" / / 2 señal baja (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"nop\n\t"                 // 1    nop                                        (T = 18)
«Dic %9\n\t» / / 1 disminución bytecount (T = 19)
"brne nextbit\n\t" / / 2 si bytecount! = 0 -> nextbit (T = 20)
::
);

La mejor manera de entender el funcionamiento de esta sección es considerar escenarios de caso y sigue el código línea por línea de la Asamblea.  Por ejemplo, sabemos que para enviar un valor de 255, necesitamos enviar 8 bits con un tiempo que corresponde a 1.  En otras palabras, el Pin Digital conectado a la WS281X debe permanecer alta para 13 ciclos (0.8125μs) y baja para 7 (0.4375μs).  ¿El código anterior lograr esto?  Vamos a ver lo que sucede cuando empieza a transmitir:

(volátiles) ASM
"nextbit:\n\t" / / Esto es sólo una etiqueta para dirigir los saltos más abajo.
"OSE %0, %1\n\t" / / la señal está establecida en alto, instrucción utiliza 2 ciclos.
"sbrc %4, 7\n\t" / / verdadero. Envío de 255 implica MSB actual es 'set' (= 1).
"mov 6 %, %3\n\t" / / Esto es ejecutado. "tmp" está establecido en alto.
«Dic %5\n\t» / / se transmite poco, disminuir el contador de bit.
"nop\n\t" / / necesidad a ralentí para llegar a los ciclos de 13 reloj.
"st % a2, %6\n\t" / / escribir el valor de "tmp" en el puerto (pin aún alta).
"mov 6 %, %7\n\t" / "Tmp" ajuste a la baja para el próximo paso a través del lazo.
"breq nextbyte\n\t" / / falso. Contador de bit no es 0, use 1 ciclo y continuar.
"rol %4\n\t" / / cambio el valor del byte MSB hacia la izquierda.
"rjmp. + 0\n\t" / / Idle durante 2 ciclos de reloj. Fase alcanzada T = 13.
"cbi %0, %1\n\t" / / señal para bajo.
"rjmp. + 0\n\t" / / Idle durante 2 ciclos de reloj.
"nop\n\t" / / Idle por ciclo de 1 reloj.
"rjmp nextbit\n\t" / / contador de Bit no salto así que 0 en el bit siguiente. T = 20.
);

Para que las instrucciones que se ejecutan realmente generan una señal en el pin de datos es 13 ciclos alto (0.8125μs) y 7 bajo (0.4375μs), así envío un poco con un valor de 1 para el WS281X.  Si seguimos a estudiar el código de lo que hace cuando el resto de los bits se envían y que lo hace cuando se utilizan los valores que no sean de 255, obtendrá una comprensión más profunda de esta aplicación particular de bitbanging.

Personalmente espero que encuentran este tutorial útil para comenzar con bitbanging su propia comunicación protocolos cuando sea necesario.

Artículos Relacionados

Arduino controla la tira RGB LED para el salón

Arduino controla la tira RGB LED para el salón

La idea detrás de este pequeño proyecto fue que alguna luz indirecta bastante humor en la sala de estar. Es controlado por el servidor de openHAB (que el proyecto todavía está en la lista que se añade a este sitio) instalado en un Raspberry Pi. Por s
Ambilight sin Arduino no direccionable LEDs RGB

Ambilight sin Arduino no direccionable LEDs RGB

Si no sabes qué Ambilight es que debe controlar vídeos de youtube en Philips AmbilightHoy en día hay muchas manera para hacer una réplica o incluso un mejor aspecto reflexiones...es la forma más fácil de hacer tal cosa con un barato RGB led que no es
Control de LEDs RGB con nuestras

Control de LEDs RGB con nuestras

hace unos días he publicado un instructivo para las nuestras, que es sólo un nombre de fantasia para un Imp leer un potenciometro y un interruptor y empujando los datos en el planificador eléctrico Imp. Si usted no ha visto todavía, puede comprobarlo
Arduino - control de leds con Joystick PS2 - KY-023

Arduino - control de leds con Joystick PS2 - KY-023

¡Hola mundo! Hoy hice un ejemplo sencillo de cómo usar el KY-023.Vamos a controlar un módulo RGB y una de 7 colores Led módulo.Puede añadir cualquier otra cosa como Servos, relés, o lo que viene en tu mente.Los Joysticks son muy fácil de usar, y el c
Control de un LED RGB con el módulo de Bluetooth HC-06 con Android OS(Arduino)

Control de un LED RGB con el módulo de Bluetooth HC-06 con Android OS(Arduino)

Este tutorial explicará el proceso de conectarse un Arduino con un módulo de Bluetooth HC-06 y controlar el color de un LED RGB mediante la aplicación de ArduDroid en el sistema operativo Android. Esta configuración es muy probable que también trabaj
Control LED RGB con arduino y procesamiento.

Control LED RGB con arduino y procesamiento.

Hoy te diré cómo controlar un LED RGB con ayuda del lenguaje Arduino y procesamiento. Este es mi primer instructable, déjeme por favor saber si pudiera mejorar algo y si tienes cualquier tipo de preguntas les dejan en la caja de comentario, me encant
Control LED RGB utilizando Amarino Nano 1.0

Control LED RGB utilizando Amarino Nano 1.0

Qué es Amarino Nano 1.0Este es mi nuevo kit de bricolaje para Android-Arduino comunicación vía Bluetooth.Amarino Nano particularmente usa Arduino Nano, así que usé el título como 'Nano'. Es un juego muy simple para probar la mayoría de las funciones
Control de LED por teléfono y MangoCube WiFi en modo AP

Control de LED por teléfono y MangoCube WiFi en modo AP

Este Instructable muestra cómo controlar un LED (pin 13) de MangoCube WiFi con un Smart Phone (Android/iOS).Cosas necesarias para este Instructable;1. MangoCube WiFi o (placa WiFi + tablero de Arduino UNO/Leonardo)2. smart Phone (Android/iOS)3. TCP l
Arduino controla cabeza madera animatronic (lámpara)

Arduino controla cabeza madera animatronic (lámpara)

esta es una lámpara de lectura que puede ser ajustada para la dirección de la iluminación y atenuada como sea necesario.Este Instructable combina Arduino, programación, algunos electrónica simple, talla con herramientas manuales y eléctricas, control
Arduino controla colmena fumigador / ambientador de aire

Arduino controla colmena fumigador / ambientador de aire

Dentro del caos relativo de mi arreglos domésticos, tengo un pequeño oasis de orden perfecto. Una cosa que puedo llamar 'organizado' y totalmente funcional. Una cosa que puedo tocar y saber que es confiable y listo para la acción en un aviso de momen
Arduino controla el temporizador de cocina

Arduino controla el temporizador de cocina

Todos ustedes deben han experimentado esto que tienes algo cocinan sobre su cocina por el otro lado conseguir ocupado viendo la televisión o conseguir una conversación profunda que te das cuenta en la detección de un olor que completamente fue estrop
Arduino controla LEDs tira de vacaciones

Arduino controla LEDs tira de vacaciones

con los precios cayendo en tiras de LEDs, configuración de iluminación permanente de vacaciones es cada vez más factible todos los días.  Un Arduino hace un controlador de gran iluminación bricolaje.Para este proyecto utilicé unas tiras de LED RGB an
Arduino controla el árbol de Navidad de LED RGB posicional

Arduino controla el árbol de Navidad de LED RGB posicional

En este Instructable nos va creando un árbol de Navidad de LED RGB programables y construyendo (X, Y) posición de las luces en el Arduino que podemos crear diferentes patrones tanto animada como estática. Yo recomendaría esto a cualquier persona que
Control de luces RGB desde Android con Arduino y Bluetooth LE (BLE)

Control de luces RGB desde Android con Arduino y Bluetooth LE (BLE)

he visto muchos proyectos de Kickstarter con el nuevo estándar de Bluetooth 4.0 baja energía y un número de Bluetooth LE (BLE) activado Arduino clones provenientes en el mercado, pero muchos de estos proyectos parecen estar en alguna parte en el proc