Closed happy77fr closed 7 months ago
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
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);`