kitesurfer1404 / WS2812FX

WS2812 FX Library for Arduino and ESP8266

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WS2812FX virtual strip and mixing GRB and BGR

happy77fr opened this issue · comments

Hello,

I couldn't find a way to have a virtual strip mixing GRB and BGR led strips.
The virtual strip works with only one color scheme.

Is there a way to solve this issue?

Here is the code:

`WS2812FX ws2812fx_v1 = WS2812FX(LED_COUNT_P1 + LED_COUNT_P2 + LED_COUNT_P3 + LED_COUNT_P4, LED_PIN_V1, NEO_GRB + NEO_KHZ800, 1, 1);

WS2812FX ws2812fx_p1 = WS2812FX(1, LED_PIN_P1, NEO_GRB + NEO_KHZ800, 1, 1);
WS2812FX ws2812fx_p2 = WS2812FX(1, LED_PIN_P2, NEO_GRB + NEO_KHZ800, 1, 1);
WS2812FX ws2812fx_p3 = WS2812FX(1, LED_PIN_P3, NEO_BGR + NEO_KHZ800, 1, 1);
WS2812FX ws2812fx_p4 = WS2812FX(1, LED_PIN_P4, NEO_BGR + NEO_KHZ800, 1, 1);`

Unfortunately, the virtual strip example sketch doesn't do any translation between virtual and physical strips. It just maps the virtual data array directly to the physical strip's data array.

I played around with it a little and you can do a messy data copy between virtual and physical strips that handles different RGB types. This is what I came up with:

#include <WS2812FX.h>

#define LED_PIN_V1     22  // virtual digital pin used to drive the virtual LED strip
#define LED_PIN_P1     22  // physical digital pin used to drive the first physical LED strip
#define LED_PIN_P2     21  // physical digital pin used to drive the second physical LED strip
#define LED_PIN_P3     19  // physical digital pin used to drive the second physical LED strip
#define LED_PIN_P4     17  // physical digital pin used to drive the second physical LED strip

#define LED_COUNT_P1   16  // number of LEDs on the first physical strip
#define LED_COUNT_P2   16  // number of LEDs on the second physical strip
#define LED_COUNT_P3   16  // number of LEDs on the third physical strip
#define LED_COUNT_P4   16  // number of LEDs on the fourth physical strip

#define LED_TYPE_V1    NEO_GRB + NEO_KHZ800  // LED type of the virtual strip
#define LED_TYPE_P1    NEO_GRB + NEO_KHZ800  // LED type of the first physical strip
#define LED_TYPE_P2    NEO_GRB + NEO_KHZ800  // LED type of the second physical strip
#define LED_TYPE_P3    NEO_BGR + NEO_KHZ800  // LED type of the third physical strip
#define LED_TYPE_P4    NEO_BGR + NEO_KHZ800  // LED type of the fourth physical strip

#define DATA_PIN_MOSFET 23

// create an instance of one virtual strip and four physical strips.
// (Note the instances are created with support of only one segment and one
// segment_runtime, just so the sketch fits in an Arduino's limited SRAM.)
WS2812FX ws2812fx_v1 = WS2812FX(LED_COUNT_P1 + LED_COUNT_P2 + LED_COUNT_P3 + LED_COUNT_P4, LED_PIN_V1, LED_TYPE_V1, 1, 1);

WS2812FX ws2812fx_p1 = WS2812FX(LED_COUNT_P1, LED_PIN_P1, LED_TYPE_P1, 1, 1);
WS2812FX ws2812fx_p2 = WS2812FX(LED_COUNT_P2, LED_PIN_P2, LED_TYPE_P2, 1, 1);
WS2812FX ws2812fx_p3 = WS2812FX(LED_COUNT_P3, LED_PIN_P3, LED_TYPE_P3, 1, 1);
WS2812FX ws2812fx_p4 = WS2812FX(LED_COUNT_P4, LED_PIN_P4, LED_TYPE_P4, 1, 1);

void setup() {
#ifdef DATA_PIN_MOSFET
  pinMode(DATA_PIN_MOSFET, OUTPUT);    // MOSFET GPIO
  digitalWrite(DATA_PIN_MOSFET, LOW);  // MOSFET on
  delay(10);
#endif

  // initialize the virtual strip as you would any normal ws2812fx instance
  ws2812fx_v1.init();
  ws2812fx_v1.setBrightness(255);
  ws2812fx_v1.setSegment(0, 0, ws2812fx_v1.getLength()-1, FX_MODE_COMET, RED, 2000);
  ws2812fx_v1.start();

  // init the physical strip's GPIOs
  ws2812fx_p1.init();
  ws2812fx_p2.init();
  ws2812fx_p3.init();
  ws2812fx_p4.init();

  // config a custom show() function for the virtual strip, so pixel
  // data gets copied to the physical strip's data array
  ws2812fx_v1.setCustomShow(myCustomShow);
}

void loop() {
  // update the virtual strip's pixel data by calling service() as you normally would
  ws2812fx_v1.service();
}

void myCustomShow(void) {
  uint8_t *v_ptr = ws2812fx_v1.getPixels();

  // map first physical strip
  mapLEDs(ws2812fx_p1.getPixels(), v_ptr, ws2812fx_p1.getNumBytes(), LED_TYPE_P1, LED_TYPE_V1);

  // map second physical strip
  v_ptr += ws2812fx_p1.getNumBytes();
  mapLEDs(ws2812fx_p2.getPixels(), v_ptr, ws2812fx_p2.getNumBytes(), LED_TYPE_P2, LED_TYPE_V1);

  // map third physical strip
  v_ptr += ws2812fx_p2.getNumBytes();
  mapLEDs(ws2812fx_p3.getPixels(), v_ptr, ws2812fx_p3.getNumBytes(), LED_TYPE_P3, LED_TYPE_V1);

  // map fourth physical strip
  v_ptr += ws2812fx_p3.getNumBytes();
  mapLEDs(ws2812fx_p4.getPixels(), v_ptr, ws2812fx_p4.getNumBytes(), LED_TYPE_P4, LED_TYPE_V1);

  // Call the physical strip's show() function.
  // Note: the virtual strip's show() functions are never called.
  ws2812fx_p1.Adafruit_NeoPixel::show();
  ws2812fx_p2.Adafruit_NeoPixel::show();
  ws2812fx_p3.Adafruit_NeoPixel::show();
  ws2812fx_p4.Adafruit_NeoPixel::show();
}

// map the virtual strip data to the physical strip
void mapLEDs(uint8_t *p, uint8_t *v, uint16_t byteCnt, neoPixelType p_type, neoPixelType v_type) {
  if(p_type == v_type) {
    memmove(p, v, byteCnt); // if the v and p strips are the same type, just do a memcopy
  } else {
    uint8_t rOffset_p = (p_type >> 4) & 0b11; // types are different, so do the GRB to BGR mapping
    uint8_t gOffset_p = (p_type >> 2) & 0b11;
    uint8_t bOffset_p = p_type & 0b11;

    uint8_t rOffset_v = (v_type >> 4) & 0b11;
    uint8_t gOffset_v = (v_type >> 2) & 0b11;
    uint8_t bOffset_v = v_type & 0b11;

    for(int i=0; i < byteCnt; i += 3) {
      p[rOffset_p + i] = v[rOffset_v + i];
      p[gOffset_p + i] = v[gOffset_v + i];
      p[bOffset_p + i] = v[bOffset_v + i];
    }
  }
}

The Adafruit_NeoPixel lib doesn't expose the LED type parameter, so it's a bit of a hack to make it work.

Thank you! I couldn't test this tonight but I will come back soon

It works! Thank you