Мерцание либо пульсация RGB ленты, устранение.

vestmar
Offline
Зарегистрирован: 20.05.2017

Добрый день уважаемые специалисты!

Собрал фоновую подстветку аналог ambilight по инструкции mysku. ru/blog/aliexpress/28820.html

использовал Arduino nano, БП 8A - https://ru.aliexpress.com/item/5V-2A-3A-4A-5A-8A-10A-12A-20A-30A-40A-60A-Switch-LED-Power-Supply/32670505021.html и ленту https://ru.aliexpress.com/item/1m-4m-5m-WS2812B-Smart-led-pixel-strip-Bl... 60LED/1м

Использовал данный скетч-

// Slightly modified Adalight protocol implementation that uses FastLED
// library (http://fastled.io) for driving WS2811/WS2812 led stripe
// Was tested only with Prismatik software from Lightpack project
 
#include "FastLED.h"
 
#define NUM_LEDS 110 // Max LED count
#define LED_PIN 8 // arduino output pin
#define GROUND_PIN 10
#define BRIGHTNESS 255 // maximum brightness
#define SPEED 115200 // virtual serial port speed, must be the same in boblight_config 
 
CRGB leds[NUM_LEDS];
uint8_t * ledsRaw = (uint8_t *)leds;
 
// A 'magic word' (along with LED count & checksum) precedes each block
// of LED data; this assists the microcontroller in syncing up with the
// host-side software and properly issuing the latch (host I/O is
// likely buffered, making usleep() unreliable for latch).  You may see
// an initial glitchy frame or two until the two come into alignment.
// The magic word can be whatever sequence you like, but each character
// should be unique, and frequent pixel values like 0 and 255 are
// avoided -- fewer false positives.  The host software will need to
// generate a compatible header: immediately following the magic word
// are three bytes: a 16-bit count of the number of LEDs (high byte
// first) followed by a simple checksum value (high byte XOR low byte
// XOR 0x55).  LED data follows, 3 bytes per LED, in order R, G, B,
// where 0 = off and 255 = max brightness.
 
static const uint8_t magic[] = {
  'A','d','a'};
#define MAGICSIZE  sizeof(magic)
#define HEADERSIZE (MAGICSIZE + 3)
 
#define MODE_HEADER 0
#define MODE_DATA   2
 
// If no serial data is received for a while, the LEDs are shut off
// automatically.  This avoids the annoying "stuck pixel" look when
// quitting LED display programs on the host computer.
static const unsigned long serialTimeout = 150000; // 150 seconds
 
void setup()
{
  pinMode(GROUND_PIN, OUTPUT); 
  digitalWrite(GROUND_PIN, LOW);
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
 
  // Dirty trick: the circular buffer for serial data is 256 bytes,
  // and the "in" and "out" indices are unsigned 8-bit types -- this
  // much simplifies the cases where in/out need to "wrap around" the
  // beginning/end of the buffer.  Otherwise there'd be a ton of bit-
  // masking and/or conditional code every time one of these indices
  // needs to change, slowing things down tremendously.
  uint8_t
    buffer[256],
  indexIn       = 0,
  indexOut      = 0,
  mode          = MODE_HEADER,
  hi, lo, chk, i, spiFlag;
  int16_t
    bytesBuffered = 0,
  hold          = 0,
  c;
  int32_t
    bytesRemaining;
  unsigned long
    startTime,
  lastByteTime,
  lastAckTime,
  t;
  int32_t outPos = 0;
 
  Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!
 
  Serial.print("Ada\n"); // Send ACK string to host
 
    startTime    = micros();
  lastByteTime = lastAckTime = millis();
 
  // loop() is avoided as even that small bit of function overhead
  // has a measurable impact on this code's overall throughput.
 
  for(;;) {
 
    // Implementation is a simple finite-state machine.
    // Regardless of mode, check for serial input each time:
    t = millis();
    if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) {
      buffer[indexIn++] = c;
      bytesBuffered++;
      lastByteTime = lastAckTime = t; // Reset timeout counters
    } 
    else {
      // No data received.  If this persists, send an ACK packet
      // to host once every second to alert it to our presence.
      if((t - lastAckTime) > 1000) {
        Serial.print("Ada\n"); // Send ACK string to host
        lastAckTime = t; // Reset counter
      }
      // If no data received for an extended time, turn off all LEDs.
      if((t - lastByteTime) > serialTimeout) {
        memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
        FastLED.show();
        lastByteTime = t; // Reset counter
      }
    }
 
    switch(mode) {
 
    case MODE_HEADER:
 
      // In header-seeking mode.  Is there enough data to check?
      if(bytesBuffered >= HEADERSIZE) {
        // Indeed.  Check for a 'magic word' match.
        for(i=0; (i<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
        if(i == MAGICSIZE) {
          // Magic word matches.  Now how about the checksum?
          hi  = buffer[indexOut++];
          lo  = buffer[indexOut++];
          chk = buffer[indexOut++];
          if(chk == (hi ^ lo ^ 0x55)) {
            // Checksum looks valid.  Get 16-bit LED count, add 1
            // (# LEDs is always > 0) and multiply by 3 for R,G,B.
            bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L);
            bytesBuffered -= 3;
            outPos = 0;
            memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB));
            mode           = MODE_DATA; // Proceed to latch wait mode
          } 
          else {
            // Checksum didn't match; search resumes after magic word.
            indexOut  -= 3; // Rewind
          }
        } // else no header match.  Resume at first mismatched byte.
        bytesBuffered -= i;
      }
      break;
 
    case MODE_DATA:
 
      if(bytesRemaining > 0) {
        if(bytesBuffered > 0) {
          if (outPos < sizeof(leds))
            ledsRaw[outPos++] = buffer[indexOut++];   // Issue next byte
          bytesBuffered--;
          bytesRemaining--;
        }
        // If serial buffer is threatening to underrun, start
        // introducing progressively longer pauses to allow more
        // data to arrive (up to a point).
      } 
      else {
        // End of data -- issue latch:
        startTime  = micros();
        mode       = MODE_HEADER; // Begin next header search
        FastLED.show();
      }
    } // end switch
  } // end for(;;)
}
 
void loop()
{
  // Not used.  See note in setup() function.
}

Всё получилось хорошо, 110 диодов лента подключена только с одной стороны, но есть мерцание глазу не заметно, видит камера смартфона

Ну и соответствено после длительного включения есть легкая усталость глаз. Как сглать ток, либо поднять частоту, подскажите пожалуста?

Я в этом деле новичек, но буду всеми силами вникать в кажды ваш совет.

Заранее спасибо!

vestmar
Offline
Зарегистрирован: 20.05.2017

Вот схема подключения

Только у меня Arduino nano

kasper007
Offline
Зарегистрирован: 23.05.2016

Наверное с этой лентой вы уже ничего не сделать лучше не сможете. Мерцание из-за того, что яркость светодиода регулируется ШИМом. Т.е. чтобы меньше мерцало нужно ограничивать диапазон регулировки яркости.

https://www.youtube.com/watch?v=flEm-wQpx90

Вот мой пример именно на этой ленте, разворачивать рисунок на врашающемся колесе. Чем меньше яркость я ставил, тем больше было видно дискретность включения светодиодов.

 

vestmar
Offline
Зарегистрирован: 20.05.2017

Спасибо Вам за ответ!

Заменял ногу Ардуино, тоже не помогло... и тогда до меня дошло, прочита дадашит на контроллер WS2812, действительно ничего не сделать, единственн вариант замены ленты на WS2811 хотя по данным там тоже в пределах 400герц.

Я так понимаю, ambilight хороший выйдет не на ардуино, а на отрезках светодиодных RGB лент, без контролеров на них, управление которым берёт на себя микросхема более продвинутая...

В общем сложно всё это) особенно мне, единственное буду ждать может кто-нибудь на этом форуме собирал нечто подобное и поделится советом)

vestmar
Offline
Зарегистрирован: 20.05.2017

Я правильно понял, у ленты https://cdn-shop.adafruit.com/datasheets/WS2801.pdf ШИМ на частоте 2.5 Кгц?

Sanyaba
Sanyaba аватар
Offline
Зарегистрирован: 27.07.2015

А может пульсации от источника питания?

Я бы поробовал запитать Ардуино и ленту через небольшой фильтр на дросселе и конденсаторе с низким ESR

vestmar
Offline
Зарегистрирован: 20.05.2017

Мне нужно будет схему показать специалисту) А пока может есть готовое решение на Али? (если можно - ссылку) по данной схеме.

Arduino питается от USB, а вот на ленту можно поставить.

kasper007
Offline
Зарегистрирован: 23.05.2016

Первым делом, чтобы исключить пульсацию, я запитывал ленту от АКБ, ситуация абсолютно такая же, так что наличие фильтра хорошо, но ситуацию координально не исправит.

 

vestmar
Offline
Зарегистрирован: 20.05.2017

kasper007 - согласен. Замена ленты на ws2801 пока идея одна.