Wish NeoPixels Library

JordiCP

Expert
Licensed User
Longtime User
Well, all of this is theory but I think it should work . Also, if a neopixel library for ESP already exists, the only advantage would be that you free resources for the user program since you are giving the control to a hardware resource

What I mean is that, if for instance, for WS2812 the timings are
symbol "1" --> 660nsec High + 330 nsec low --> 2 basic period HIGH + 1 basic period LOW (let's define a "basic" as a 330nsec period)
symbol "0" --> 330nsec high + 660 nsec low --> 1 basic period HIGH + 2 basic period LOW

Suppose we have N leds. For each one we need 24 bits (as in APA102). The trick is to convert these 24*N "WS2812 bits" to 3*24*N SPI bits

For instance, if the sequence to be sent is
11010011....
We previously prepare the frame buffer converting them to (each 3 bits here will correspond to one original bit)
110 110 100 110 100 100 110 110 ..... ---> grouping them into bytes --> 0xDA 0x69 0x36 ....

Then we set up the HSPI clock to 3MHz we give it the buffer and it automatically sends it. When it finishes we send the following bytes.

As the HSPI in ESP8266 can be, as much, 20bytes, I would limit it to 18 bytes, which would allow us for 2 "complete" leds
18 [bytes]*8 [spi_bits/byte]/3[spi_bits/neopixel_bit])/24 [neopixel_bit/led] --> 2 leds

I am preparing my ESP-Jorduino since I broke my previous one so I can't test it yet. Will do it when ready.


 

freedom2000

Well-Known Member
Licensed User
Longtime User

Yes it should work
 

Cableguy

Expert
Licensed User
Longtime User
so if I am to emulate the serial protocol needed, a simple timer with flag to determine if its a "1" or a "0", or make use of the delay keyword will do the trick?!
 

freedom2000

Well-Known Member
Licensed User
Longtime User
so if I am to emulate the serial protocol needed, a simple timer with flag to determine if its a "1" or a "0", or make use of the delay keyword will do the trick?!
yes should work.
But possibly slow ?
 

Cableguy

Expert
Licensed User
Longtime User
why slow? I guess the trick will be to build the complete "image" string before hand, and send all the bytes with a timer...
I'm thinking of animated gifs that could be played in a "screen" of addressable leds...
 

freedom2000

Well-Known Member
Licensed User
Longtime User
slow... just depending how fast your timer loop can run to emulate the serial protocol and handle the image to prepare the next buffer.
 

Cableguy

Expert
Licensed User
Longtime User
I'm guessing that, even with a fresh rate of 500Hz(2ms) will be fast enough to refresh about 100Leds (10x10) and still have fluidity...this, using a timer...
But there are other ways to get shorter delays, I think
 

Toley

Active Member
Licensed User
Longtime User
why slow? I guess the trick will be to build the complete "image" string before hand, and send all the bytes with a timer...
I'm thinking of animated gifs that could be played in a "screen" of addressable leds...
Unfortunately this is not so simple! At least not with Arduino. This protocol is very tricky the data must be send at a very high rate (800 kHz or 1.25 us). If there is a delay longer than around 10us it reset and start over to the first LED. So your solution won't be able to address more than 1 LED. Look at this timing table.



Don't worry many peoples (including me) have experimented with those LED strips and the only way found so far with Arduino is NeoPixel which is not a perfect solution either.
 

Cableguy

Expert
Licensed User
Longtime User
even with a looper?
 

Cableguy

Expert
Licensed User
Longtime User
Hi guys, my board should be arriving in a week or so, and i have a question... Imagine i have a single led... To light it I send the 24bit signal to set its color, and the pwm to set its brightness (?)... So now I have lit a Led.. But for how long?... To keep it alive do I have to keep cycling data>reset ?
 

JordiCP

Expert
Licensed User
Longtime User
I think the led should keep its color until you power cycle it or program it again
 

Cableguy

Expert
Licensed User
Longtime User
So, to create an image, I only need to send the data once, and only send if I need to change?
Another question... In an array of say 20 leds... and I only want to change a middle one, like the 11th led... is it possible?
 

JordiCP

Expert
Licensed User
Longtime User
So, to create an image, I only need to send the data once, and only send if I need to change?
I think so: unless I am totally wrong about these leds , the only thing you should take care of, is the timing between pixels so that you can send a whole "array" correctly. Once sent, you can wait as long as you want till the next refresh
Another question... In an array of say 20 leds... and I only want to change a middle one, like the 11th led... is it possible?
If you want to change whatever pixel, you must refresh the whole array

I made this some months ago, but it was with APA102 + ESP . Even thogh the text seems only to displace, the whole screen is written each time

 

Robert Gately

Member
Licensed User
I need to get my Arduino board up and running but here's my simplified Arduino code for testing a LED strip consisting of 66 WS2812Bs...

B4X:
#include <Adafruit_NeoPixel.h>
#define PIN 5
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(66, PIN, NEO_GRB + NEO_KHZ800); // number of WS2812B LEDs on strip, green-red-blue, 800khz

void setup() {
  // init serial
  Serial.begin(9600);

  // init WS2812B LED strips                
  strip1.begin();
  strip1.setBrightness(127);
  strip1.show();
}

void loop() {
  for (int i = 0; i < 67; i++){
    strip1.setPixelColor(i,255,0,0); // sets the color of each LED
    delay(40); strip1.show();       
  }
}
 

Cableguy

Expert
Licensed User
Longtime User
I have found an interesting video and piece of code, NO LIBRARY NEEDED to control the NeoPixel!
Here's the Video:

And here is the Function used to control the neo-pixels
B4X:
//WS2812 Driver Function
void RGB_update(int LED, byte RED, byte GREEN, byte BLUE) {
  // LED is the LED number starting with 0
  // RED, GREEN, BLUE is the brightness 0..255 setpoint for that LED
  byte ExistingPort, WS2812pinHIGH;//local variables here to speed up pinWrites

  if(LED>=0){//map the REG GREEN BLUE Values into the RGB[] array
  RGB[LED * 3] = GREEN;
  RGB[LED * 3 + 1] = RED;
  RGB[LED * 3 + 2] = BLUE;
  }

  noInterrupts();//kill the interrupts while we send the bit stream out...
  ExistingPort = PORTB; // save the status of the entire PORT B - let's us write to the entire port without messing up the other pins on that port
  WS2812pinHIGH = PORTB | 1; //this gives us a byte we can use to set the whole PORTB with the WS2812 pin HIGH
  int bitStream = numberOfLEDs * 3;//total bytes in the LED string

//This for loop runs through all of the bits (8 at a time) to set the WS2812 pin ON/OFF times
  for (int i = 0; i < bitStream; i++) {

    PORTB = WS2812pinHIGH;//bit 7  first, set the pin HIGH - it always goes high regardless of a 0/1
 
    //here's the tricky part, check if the bit in the byte is high/low then right that status to the pin
    // (RGB[i] & B10000000) will strip away the other bits in RGB[i], so here we'll be left with B10000000 or B00000000
    // then it's easy to check if the bit is high or low by AND'ing that with the bit mask ""&& B10000000)"" this gives 1 or 0
    // if it's a 1, we'll OR that with the Existing port, thus keeping the pin HIGH, if 0 the pin is written LOW
    PORTB = ((RGB[i] & B10000000) && B10000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//these are NOPS - these let us delay clock cycles for more precise timing
    PORTB = ExistingPort;//okay, here we know we have to be LOW regardless of the 0/1 bit state
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//minimum LOW time for pin regardless of 0/1 bit state

    // then do it again for the next bit and so on... see the last bit though for a slight change

    PORTB = WS2812pinHIGH;//bit 6
    PORTB = ((RGB[i] & B01000000) && B01000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 5
    PORTB = ((RGB[i] & B00100000) && B00100000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 4
    PORTB = ((RGB[i] & B00010000) && B00010000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 3
    PORTB = ((RGB[i] & B00001000) && B00001000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 2
    PORTB = ((RGB[i] & B00000100) && B00000100) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 1
    PORTB = ((RGB[i] & B00000010) && B00000010) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 0
    __asm__("nop\n\t");//on this last bit, the check is much faster, so had to add a NOP here
    PORTB = ((RGB[i] & B00000001) && B00000001) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;//note there are no NOPs after writing the pin LOW, this is because the FOR Loop uses clock cycles that we can use instead of the NOPS
  }//for loop


  interrupts();//enable the interrupts

// all done!
}//void RGB_update

Since this C code uses inline Assembler (" __asm__ "), I wonder if we can use this function as an inline C in B4R or must this be converted to a wrapper(?)

I Just received my board, but it still need some header soldering, so I'll be playing with this maybe later today or tomorrow...
Hope to get some interesting results!
 
Last edited:

Cableguy

Expert
Licensed User
Longtime User
Firsts Results:

I have tried to use InLine C with B4R, But I get a bunch of error concerning the C code Block...
Since the function expects 4 args (1 int and 3 bytes) I am not sure how to pass them to the function...

So I tried the code on Arduino IDE and It works as expected!!!! so this should be doable!!!!
 

Cableguy

Expert
Licensed User
Longtime User
SUCCESS!!!!

I just got it working!!!!!!

Here's the code!
B4X:
#IgnoreWarnings: 9
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 300
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
   
    Public Serial1 As Serial
    Public pin8 As Pin
    Private LED As Int
    Private RED,GREEN,BLUE As Byte
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    LED = 20
    RED = 255
    GREEN = 255
    BLUE = 0
    pin8.Initialize(8,pin8.MODE_OUTPUT)
'    pin8.Mode = pin8.MODE_OUTPUT
    RunNative("RGB_update", Null)
End Sub

#if C
//VARIABLES AND DEFINES HERE - NEEDED BY THE WS2812 DRIVER CODE
//#define WS2812_pin 8 // only digital pin 8 works right now //Defined in B4R
#define numberOfLEDs 40// total number of RGB LEDs
byte RGB[120];//take your number of LEDs and multiply by 3

// FUNCTIONS HERE
//void RGB_update(int LED, byte RED, byte GREEN, byte BLUE);//function to drive LEDs //I don't think we need this here(?)

//void setup() {
  //pinMode(WS2812_pin, OUTPUT); //Defined in B4R
//}//setup


//void loop() {


//RGB_update(0,0,0,0);//LED#, RED, GREEN, BLUE
//delay(1000);

//}//loop



//WS2812 Driver Function
//void RGB_update(int LED, byte RED, byte GREEN, byte BLUE) {
void RGB_update(B4R::Object* o) {
  // LED is the LED number starting with 0
  // RED, GREEN, BLUE is the brightness 0..255 setpoint for that LED
  byte ExistingPort, WS2812pinHIGH;//local variables here to speed up pinWrites
 
  if(b4r_main::_led>=0){//map the RED GREEN BLUE Values into the RGB[] array
  RGB[ b4r_main::_led * 3] =  b4r_main::_green;
  RGB[ b4r_main::_led * 3 + 1] = b4r_main::_red;
  RGB[ b4r_main::_led * 3 + 2] = b4r_main::_blue;
  }
 
  noInterrupts();//kill the interrupts while we send the bit stream out...
  ExistingPort = PORTB; // save the status of the entire PORT B - let's us write to the entire port without messing up the other pins on that port
  WS2812pinHIGH = PORTB | 1; //this gives us a byte we can use to set the whole PORTB with the WS2812 pin HIGH
  int bitStream = numberOfLEDs * 3;//total bytes in the LED string

//This for loop runs through all of the bits (8 at a time) to set the WS2812 pin ON/OFF times
  for (int i = 0; i < bitStream; i++) {

    PORTB = WS2812pinHIGH;//bit 7  first, set the pin HIGH - it always goes high regardless of a 0/1
   
    //here's the tricky part, check if the bit in the byte is high/low then right that status to the pin
    // (RGB[i] & B10000000) will strip away the other bits in RGB[i], so here we'll be left with B10000000 or B00000000
    // then it's easy to check if the bit is high or low by AND'ing that with the bit mask ""&& B10000000)"" this gives 1 or 0
    // if it's a 1, we'll OR that with the Existing port, thus keeping the pin HIGH, if 0 the pin is written LOW
    PORTB = ((RGB[i] & B10000000) && B10000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//these are NOPS - these let us delay clock cycles for more precise timing
    PORTB = ExistingPort;//okay, here we know we have to be LOW regardless of the 0/1 bit state
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//minimum LOW time for pin regardless of 0/1 bit state

    // then do it again for the next bit and so on... see the last bit though for a slight change

    PORTB = WS2812pinHIGH;//bit 6
    PORTB = ((RGB[i] & B01000000) && B01000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 5
    PORTB = ((RGB[i] & B00100000) && B00100000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 4
    PORTB = ((RGB[i] & B00010000) && B00010000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 3
    PORTB = ((RGB[i] & B00001000) && B00001000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 2
    PORTB = ((RGB[i] & B00000100) && B00000100) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 1
    PORTB = ((RGB[i] & B00000010) && B00000010) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 0
    __asm__("nop\n\t");//on this last bit, the check is much faster, so had to add a NOP here
    PORTB = ((RGB[i] & B00000001) && B00000001) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;//note there are no NOPs after writing the pin LOW, this is because the FOR Loop uses clock cycles that we can use instead of the NOPS
  }//for loop

 
  interrupts();//enable the interrupts

// all done!
}//void RGB_update

#end if

Now I am able to set any LED's color from my 40 LEDs array...
I will keep on working on this so that I can Lit all of them, with different colors!
 

Cableguy

Expert
Licensed User
Longtime User
OK, so after a few hours trying to simplify this code to a bare minimum, I came up with this simple Code Module:

B4X:
'Original Function Creator : Kevin Darrah
'B4R Code Module Adaptation : Cableguy

'Usage:

'I Think it could not be simpler...
'Initialize it passing the amout of LEDs in your array
'In this Module, down in the C code block, change "byte RGB[120];", changing the size of this array to be 3 times the amount of leds passed in the initializer
'Call "SetLed" passing the Led number and the RGB values to set it to

'That's it!!!

Sub Process_Globals
    Private PIN8 As Pin
    Private LED As Int
    Private RED As Byte
    Private GREEN As Byte
    Private BLUE As Byte
    Private NLEDs As Int

End Sub

Public Sub Initialize(NumberOfLEDS As Int)
    PIN8.Initialize(8, PIN8.MODE_OUTPUT)
    NLEDs = NumberOfLEDS
End Sub

Public Sub SetLed(LEDNumber As Int, R As Byte, G As Byte, B As Byte)
    RED = R
    GREEN = G
    BLUE = B
    LED = LEDNumber
    If LED = -1 Then
        Log("all lit")
        Log(NLEDs)
        For n = 0 To NLEDs-1
            LED=n
            RunNative("RGB_update", Null)
        Next
    Else
        RunNative("RGB_update", Null)
    End If
End Sub


#if C
#define numberOfLEDs b4r_ws2812b::_nleds
byte RGB[120];//take your number of LEDs and multiply by 3 ! THIS IS VERY IMPORTANT!!!
void RGB_update(B4R::Object* o) {
byte ExistingPort, WS2812pinHIGH;
 
  if(b4r_ws2812b::_led >=0){
  RGB[ b4r_ws2812b::_led * 3] =  b4r_ws2812b::_green;
  RGB[ b4r_ws2812b::_led * 3 + 1] = b4r_ws2812b::_red;
  RGB[ b4r_ws2812b::_led * 3 + 2] = b4r_ws2812b::_blue;
  }
 
  noInterrupts();
  ExistingPort = PORTB;
  WS2812pinHIGH = PORTB | 1;
  int bitStream = numberOfLEDs * 3;

  for (int i = 0; i < bitStream; i++) {

    PORTB = WS2812pinHIGH;//bit 7  first, set the pin HIGH - it always goes high regardless of a 0/1
   
    PORTB = ((RGB[i] & B10000000) && B10000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
   
    PORTB = WS2812pinHIGH;//bit 6
    PORTB = ((RGB[i] & B01000000) && B01000000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 5
    PORTB = ((RGB[i] & B00100000) && B00100000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 4
    PORTB = ((RGB[i] & B00010000) && B00010000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 3
    PORTB = ((RGB[i] & B00001000) && B00001000) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 2
    PORTB = ((RGB[i] & B00000100) && B00000100) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 1
    PORTB = ((RGB[i] & B00000010) && B00000010) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");

    PORTB = WS2812pinHIGH;//bit 0
    __asm__("nop\n\t");
    PORTB = ((RGB[i] & B00000001) && B00000001) | ExistingPort;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTB = ExistingPort;
  }
 
  interrupts();
}

#end if

In the calling Module, all you need to do is to call Initialize(NumberOfLeds), Change the size of the RGB byte array in the C code Block of the Code Module, as noted inside it, and call SetLed(......)

It can't get simpler than this!!!
As a Bonus, Two features are implemented... One by me, another by the creator of the C code:
1 - If -1 is passed in the SetLed, as the Led Number, ALL LEDS will be lit using the RGB passed values
2 - Each time you call SetLed and pass a Led Number other than -1, ONLY THE PASSED LED WILL CHANGE!

This way, you can create very fun animations!!!

OBS, I'm not much of a maths guy, so I ask if someone can come up with a nice 2 or 3 colored lines bouncing around in my 8x5 Led Array as a sample using this Code Module
 

Robert Gately

Member
Licensed User
I put together a simple Arduino Uno platform to test 3 WS2812B LEDs arranged serially. I tried out the first set of code that you posted and was able to get it working fine. Now I will test your latest code. Thank you for your efforts. Are there any drawbacks for using a code module versus a library?
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…