Biblioteca "light_ws2812" 10 veces más lenta de lo requerido (AVR C, ATMega328p int. 8Mhz)

Así que estoy tratando de ejecutar algunos SK6812 (clones WS2812) en un ATMega328p independiente.

¡La señal de salida es demasiado lenta! Defino F_CPU como 8000000 (8Mhz), tanto en el código como en los símbolos de Atmel Studio, pero mi señal es lenta por un factor de 10. El LED siempre es blanco, en lugar de rojo como pretende el código.

#ifndef F_CPU
#define F_CPU 8000000UL // 8 MHz clock speed
#endif

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include "light_ws2812.h"

struct cRGB led[1];

int main(void)
{


    while(1)
    {
        led[0].r=25;led[0].g=00;led[0].b=0;    // Write red to array
        ws2812_setleds(led,1);
        _delay_ms(500);                         // wait for 500ms.

        //led[0].r=0;led[0].g=25;led[0].b=0;            // green
        //ws2812_setleds(led,1);
        //_delay_ms(500);

        //led[0].r=0;led[0].g=00;led[0].b=25;       // blue
        //ws2812_setleds(led,1);
        //_delay_ms(500);
    }
}

Los fusibles son l:0xA2, h:0xD9, e:0x07 . Esto debería corresponder a un reloj interno de 8Mhz (verificado en B0 con osciloscopio). Esto es lo que obtengo para una señal de datos en B4:

ingrese la descripción de la imagen aquí

Los datos se ven bien (00000000 para verde, luego 00011001 (25d) para rojo). Sin embargo, el período es de unos 12 µs, pero según la hoja de datos SK6812, el período debe ser de 1,25 µs ± 150 ns:

ingrese la descripción de la imagen aquí

No hay mucho que mostrar en el esquema, pero para ser exhaustivo:ingrese la descripción de la imagen aquí

Y como dije antes, el encabezado previsto para los datos (D6) no generó nada, así que tuve que usar B4 ya que también se dividió en un encabezado. (Problema de conectividad, lo descubrí)

¡Cualquier ayuda es apreciada!

Estoy un poco confundida. ¿Está utilizando el código de la biblioteca? ¿O está programando directamente el chip usted mismo para configurar el hardware y que funcione correctamente? Esta frase, "según la hoja de datos", me molesta. Una hoja de datos es sobre la MCU. No te dice nada sobre una biblioteca.
@jonk Estoy usando un código de ejemplo de la biblioteca, ligeramente modificado para simplificar la resolución de problemas (solo comentando esas pocas líneas). La hoja de datos es para el LED SK6812, lo siento si eso no quedó claro, lo editaré. La biblioteca está hecha para controlar el tiempo específico de esos LED.
La configuración de #define F_CPU 8000000UL solo calibra los bucles ocupados de la biblioteca estándar. Debe voltear los fusibles al programar el AVR para seleccionar la fuente y la frecuencia del reloj (¡además, no olvide el fusible CLKDIV8!)
@Janka Tengo los fusibles configurados para 8Mhz: "Los fusibles son l: 0xA2, h: 0xD9, e: 0x07. Esto debería corresponder a un reloj interno de 8 Mhz (verificado en B0 con osciloscopio)" ¿Me estoy perdiendo algo más?
Para el problema del pin: ¿Intentó configurar manualmente el pin como salida y establecer su nivel de salida en alto (es decir, DDRD |= (1<<PD6); PORTD |= (1<<PD6); )? Para el problema de la velocidad, debe verificar que el símbolo que definió en atmel studio esté realmente configurado en F_CPU = 8000000UL y que no haya un cero adicional (80 MHz). Los fusibles parecen estar bien.
¿Te das cuenta de que 1.25usec son solo 10 ciclos de máquina a 8MHz? Es posible que tenga dificultades para lograr un cambio a ese ritmo, incluso con un ensamblaje hecho a mano.

Respuestas (1)

En Atmel Studio, hacer un
#define F_CPU 8000000UL
al principio main.cno fue suficiente. Me deshice de ese código y creé un símbolo definido
F_CPU=8000000UL
en

Cadena de herramientas>Compilador AVR/GNU C>Símbolos.

Todavía no estoy seguro de por qué definir F_CPUantes incluso de llamar a las bibliotecas fue erróneo; incluso util/delay lanzó algunas advertencias a veces (si tuviera F_CPUun símbolo Indefinido, creo).

Un #define se aplica solo al archivo en el que se encuentra. Para que algo se aplique a un proyecto completo, normalmente se colocaría en un archivo de encabezado que todos los archivos de origen #incluyen explícitamente, ya sea directamente o como resultado de haber sido incluido por otro archivo de encabezado.
@ChrisStratton Esto no es correcto. #define A Bsignifica "De ahora en adelante, reemplace cualquier A por B en el siguiente código". Dado que #include foosignifica "Pegar el contenido del archivo foo aquí", a definetambién es válido en los archivos incluidos después, y defineslos archivos incluidos dentro son válidos en el archivo actual debajo de la includedirectiva.
En realidad, es correcto: como acaba de aceptar, solo se aplica en los archivos donde se indica o incluye (un proceso que, como explica, incluye literalmente el contenido de ese archivo, heredando así todo lo definido o incluido antes). El supuesto problema del autor de la pregunta se debe a que no se aplica a otros archivos fuente de C/C++ que no lo indican ni lo incluyen. En el reino de Arduino, sin embargo, hay algunas tonterías ocultas, como la concatenación de todos los archivos .ino en una sola fuente para alimentar el preprocesador del compilador, lo que puede generar expectativas de comportamiento no estándar.
Sin embargo, el comentario anterior de Peter Smith hace que sea cuestionable que esta sea incluso la causa del comportamiento lento; si es la solución, puede ser que provoque que la demora se convierta en un no-op. Pero sería interesante cuál es la frecuencia de salida real alcanzada ahora. Mi conjetura es que todavía estaría mal, pero tal vez lo suficientemente cerca como para que ahora funcione.
@ChrisStratton Sí, la biblioteca que estoy usando produce una sincronización no exacta. Este sitio en realidad describe el proceso, más de lo que he investigado, pero explican una relación de ciclo de reloj de 7:3 para un '1' y 3:7 para un '0' a 8MHz (1.25us). No he conectado un alcance para confirmar, pero funciona de todos modos.