WS2812 ESP32 Parpadeo problema matemático

0

Bien, he buscado en casi todas partes para encontrar una respuesta a esto y personalmente he experimentado mucho para intentar encontrar una solución.

El error que estoy experimentando es el parpadeo de Neopixel (WS2812B 12ct LED ring) usando la biblioteca NeoPixel (esto es un requisito para el proyecto. De lo contrario, usaría FastLED y vería si eso tiene los mismos problemas)

El siguiente es mi configuración: ESP32s (Node mcu brand esp32) con el IDE de Arduino 3.7v LiPo o alimentación USB 2x WS2812B suena en los pines 25/26 (también he probado 16/17)

Tengo una batería LiPo conectada en paralelo con todos los componentes (ESP32 en el pin de 5v y ambas tiras por separado) con una conexión a tierra adecuada. Esta configuración de hardware funcionó perfectamente al 100% cuando uso un módulo Arduino CH340 Nano 3.3v + Adafruit BLE por separado.

Lo que descubrí es que el parpadeo SÓLO se produce en los patrones en los que hago división en el color del píxel. ES DECIR. un desvanecimiento o dos colores se desvanecen. De lo contrario, en patrones como un ciclo Rainbow o un simple Colorwipe, funciona perfectamente sin parpadeo en ningún píxel alguno. De vez en cuando, y mucho más raramente, aparece un problema similar al cambiar de color para atenuar el color. La parte más extraña es que después de que el patrón se haya ejecutado durante 3 o 4 ciclos, se "empareja" y deja de parpadear. La razón por la que esto es extraño es que no estoy reiniciando el tablero entre patrones. Tengo una aplicación de bluetooth para Android que cociné para enviar señales BLE de serie como controlador. Así que cambiando entre mis patrones, todos se ven muy bien hasta que me cambio a uno desvanecido.

void FadeUpdate()
{        
    uint16_t stepUp = (TotalSteps + 1);
    uint8_t red = ((Red(Color1) * (stepUp - Index))) / stepUp;
    uint8_t green = ((Green(Color1) * (stepUp - Index))) / stepUp;
    uint8_t blue = ((Blue(Color1) * (stepUp - Index))) / stepUp;

    ColorSet(Color(red, green, blue));
    show();
    Increment();
}

void TwoColorFadeUpdate()
{
    // Calculate linear interpolation between Color1 and Color2
    // Optimise order of operations to minimize truncation error
    uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
    uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
    uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

    ColorSet(Color(red, green, blue));
    show();
    Increment();
}
uint32_t DimColor(uint32_t color)
{
    // Shift R, G and B components one bit to the right
    uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
    return dimColor;
}

Azul, verde y rojo, todos simplemente cambian los bits en el uint32_t para capturar la representación uint8_t de esa porción de color

TotalSteps y Index son ambos uint16_t (también probé uint32_t)

Esto me lleva a creer que mi problema con el movimiento de píxeles se debe a algún tipo de error de redondeo impar

Cosas que he probado:

  • retraso (1);
  • portDISABLE_INTERRUPTS ();
  • enviar a int en lugar de uint32_t para mis colores

Los dos primeros realmente ayudaron un poco, y considerando que los píxeles parpadean son los mismos, dependiendo del patrón (los píxeles 7 y 9 de EG parpadearán con el patrón X e Y cuando se desvanezca, pero en TwoColorFade será el píxel 1 y 8) esto me lleva a creer que esto también podría ser algún tipo de error de tiempo también.

Cosas que no he probado todavía:

  • Adjuntando el vin de los píxeles al pin 3v3 en el tablero.
  • Desplazador de nivel lógico.
  • Configuración de la frecuencia de reloj del tablero

NO he intentado estas cosas todavía porque el código se ejecuta perfectamente en el nano, que también es un tablero de 3.3v. Quiero probar el cambio de la frecuencia del reloj, pero eso es lo siguiente en mi lista de cosas para probar.

También puedo publicar mi código, pero está dividido en varios archivos .ino porque soy un principiante en Arduino dev, pero aún quiero una organización en mi proyecto.

    
pregunta Mdigibou

1 respuesta

0

Después de trabajar bastante con la biblioteca NeoPixel, confirmé que se trata de un error de tiempo relacionado con el ESP32. Para aclarar, NO es nada de lo siguiente si está experimentando el mismo error (destellos de píxeles aleatorios que tienen un patrón matemático para ellos) y ha verificado todas estas cosas.

  • Resistor en la línea de datos
  • Condensador en la línea eléctrica
  • "Sus niveles de voltaje / lógica son incorrectos"

Lo que funcionó para mí fue usar subprocesos múltiples para alojar un núcleo completo (0) para ejecutar pixels.show ();

Aquí hay un ejemplo de código que usa fastLED (finalmente reescribí todo el programa porque los efectos matemáticos son TAN agradables)

//Multi-threading synchronous show operations! Kinda slick honestly
static TaskHandle_t FastLEDshowTaskHandle = 0;
static TaskHandle_t userTaskHandle = 0;

void FastLEDshowESP32()
{
if (userTaskHandle == 0) {
    userTaskHandle = xTaskGetCurrentTaskHandle();
    xTaskNotifyGive(FastLEDshowTaskHandle);
    const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 );
    ulTaskNotifyTake(pdTRUE, xMaxBlockTime);
    userTaskHandle = 0;
}
}
void FastLEDshowTask(void *pvParameters)
{
// -- Run forever...
for(;;) {
    // -- Wait for the trigger
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    // -- Do the show (synchronously)        
    FastLED.show();
    // -- Notify the calling task
    xTaskNotifyGive(userTaskHandle);
}
}

void setup() {  
delay(3000); // 3 second delay for recovery
Serial.begin(115200);    
ser.begin(DEVICE_NAME);
Serial.println("Dare you enter my magical realm?");

FastLED.addLeds<LED_TYPE,RING_1_PIN,COLOR_ORDER>(Ring1, RING_1_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,RING_2_PIN,COLOR_ORDER>(Ring2, RING_2_LEDS).setCorrection(TypicalLEDStrip);

FastLED.setBrightness(brightness);
//Set up multi-threaded execution of LED show on core 0
xTaskCreatePinnedToCore(FastLEDshowTask, "FastLEDshowTask", 2048, NULL, 2, &FastLEDshowTaskHandle, 0);
}
    
respondido por el Mdigibou

Lea otras preguntas en las etiquetas