Adafruit Neopixel Library [PORTED]

Very cool. I removed the old ones, added the new ones, it all worked. Thx a lot!

1 Like

Awexome thanks!

BTW: I have a strip of 60 WS2812Bā€™s on their way to me now from Adafruitā€¦ so hang in there you glitchy '12B users :wink:

Iā€™d have one question for you, maybe you can answer it. It might be related to the NeoPixel lib, maybe just in general an issue with libs included.

http://snipt.org/Eita1

This is an example that I posted in another Thread already, a Spark engineer just looks into the deeper issues. It seems once I start using the NeoPixel lib, it all stops working. The function ā€œlightsā€ is then no longer registered and I cannot call it. The code runs fine if you take the NeoPixel stuff all out - it will print nicely what ā€œchannelā€ (the command stirng is turned into an int, then bits are read to determine if one of 16 channels is on) is on/off.

If you have an idea, please let me know.

I believe if thatā€™s your whole program, you are missing this in your setup()

strip.begin(); strip.show(); // Initialize all pixels to 'off'

and at the end of your lights() function after the for() loop you need

strip.show();

Anyone tried to port this https://github.com/x893/stm-ledstrip ?
I think itā€™s the best way to drive NeoPixelsā€¦

FYI: I just started looking at the timing of the adafruit neopixel library on an arduinoā€¦ going to capture the 800kHz and 400kHz timingā€¦

EDIT: this is the easy partā€¦

// 800kHz
BIT 1 = 812ns high, 436ns low
BIT 0 = 312ns high, 938ns low

// 400kHz
BIT 1 = 1.25us high, 1.25us low
BIT 0 = 500ns high, 2us low

Now comes the screwing around with reprogramming the Spark Core with ASM delays over and overā€¦ -_- One day Iā€™ll see if a timer works, or maybe get the code fully done in assembly.

@shocku992 @hansamann and everyone else with 800kHz neopixelsā€¦ check out the library now, I matched the adafruit timing as best I couldā€¦ it was quite a bit different, and actually some of the numbers donā€™t seem to make sense to be between the timing of the WS2812 and WS2812B, but if it works better on your arduinoā€¦ letā€™s give this a try!

https://github.com/technobly/SparkCore-NeoPixel

Hi @BDub - you were right, those calls were definitely missing. I added them now but it still does not work. By now I separated the code that updates which channel is on from the code that executes the channel/light setup. But it does not work :frowning: Somethign seems to hang the device. The function is initially in the response of the device config, then goes awayā€¦

Could it be the lib is broken right now? I just went back to a basic program that ā€œjustā€ operates the RGB123 board, no fancy functions, so I used all the code I found on Github and try to do a basic LED walkā€¦ but no successā€¦

@hansamann Iā€™m working with my latest code and your snipt from above and the recommendations I suggestedā€¦ I see it hanging tooā€¦ Iā€™m working on figuring out why. Will report back soon.

BTW what are you sending as arguments, and what is the desired operation of the lights function?

Ok @hansamann I fixed up your code :smile:

This will toggle one of the 16 leds on or off. You just send a argument value of 0 through 15 to toggle the targeted LED. So if I sent the argument as 0, it would turn on the first LED in the strip. If I sent it again it would turn it off.

I know you have 64 leds, so Iā€™m guessing this is not the exact action you wantedā€¦ maybe you want to turn on 4 leds at a time? I think if you put your code back in instead of my one line, it will probably work just fine like that :smile:

Iā€™m guessing there was a math error somewhere that was causing your NeoPixel class to try and manipulate memory in a bad way. This is something Iā€™ll look into further to see if I can put some traps in the library to prevent it from blocking under these conditions.

#include "Spark_NeoPixel.h"
 
int lights(String command);
 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(64, D2);
 
uint16_t channels = 0x0000; // All lights off
bool s = false;

void setup() {
  pinMode(D7,OUTPUT);
  digitalWrite(D7,HIGH);
  strip.begin();
  strip.show();
  Serial.begin(9600);
  while(!Serial.available());
  Spark.function("lights", lights);
  Serial.println("Ready.");
}
 
void loop() {
    s = !s;
    digitalWrite(D7,s);
    delay(100);
}
 
int lights(String command) 
{
    Serial.println("lights called with command " + command);
    delay(100);
    if(command.length() == 0)
      return -1;
    
    uint16_t number = command.toInt();
    if(number > 15)
      return -2;
      
    uint32_t c_on = strip.Color(255, 255, 255);
    uint32_t c_off = strip.Color(0, 0, 0);
 
    channels ^= (1 << number); // toggle the bit (0 - 15)
 
    for (int i = 0; i < 16; i++)
    {
        uint16_t val = (channels & (1 << i)) ? 1 : 0; // is bit set or clear?
        Serial.print(i, DEC);
        Serial.print("->");
        Serial.println(val, DEC);
        delay(50);
        
        strip.setPixelColor(i, (val == 1) ? c_on : c_off);
        //int base = i * 4;
        //strip.setPixelColor(base, (val == 1) ? c_on : c_off);
        //strip.setPixelColor(base+1, (val == 1) ? c_on : c_off);
        //strip.setPixelColor(base+2, (val == 1) ? c_on : c_off);
        //strip.setPixelColor(base+3, (val == 1) ? c_on : c_off);      
    }
    strip.show();
 
  return 200;
}

BTW, above while(!Serial.available()); will wait for you to open your serial terminal and press ENTER. Then you should see the on-board blue LED toggling on and off to show Alive status.

Donā€™t forget to update your Spark_NeoPixel.cpp with the latest from the repo and let me know if it glitch has vanished. Thanks!

1 Like

Holy shit, your code works :slight_smile: I am forever thankful. I am indeed trying to do someting slightly different, but that does not matter. Worst case I can somehow use that code.

So the input to the lights function was meant to contain the state of ALL 16 channels at once. This means with calling lights(ā€˜3ā€™) it would turn on channels 0 and 1 (2^0+2^1). All other channels, which val will return a 0 for, are turned off.

On the server side I have a script that creates this command value:
//groovy code
def channels = [0,1]
def channelInteger = channels.unique().inject(0, {sum, val -> sum + 2**val})
println ā€œchannelInteger: ${channelInteger}ā€

Soā€¦ there must have been an issue with my former code and the NeoPixel lib. I really think this must be the case, as I was running that code standalone successfully. Then, once I was able to get the repeatet output over Serial, I was adding the pixel calls.

One big difference: being a java guy, I never cared working with uint16_t - I just used int for example. Could that be the issue?

All right, as I seem to be incompetent to work with bitwise operations, I just sketched this here in Arduino and it seems to work:

String input = ā€œ0111111111111110ā€;

for (int i=0; i<16; i++)
{
boolean on = (input.charAt(i) == ā€˜1ā€™);
Serial.print("Channel ā€œ);
Serial.print(i, DEC);
Serial.print(ā€ is ");
Serial.println(on);
}

So the command will be a String of length 16, each single char in that String will be an 0 or 1 which I compare to turn on or off the channels.

Nowā€¦ Iā€™ll have to do this math here to calculate the 4 consecutive LEDs:

int base = i * 4;
LED 1 = base
LED 2 = base + 1, etc.

I will feed that into the strip.setPixelColor function
strip.setPixelColor(i, (val == 1) ? c_on : c_off);

Let me try that out laterā€¦

This is getting interesting. Before I wanted to try out my new channel code I copied your code again, the code that worked. But I wanted to turn on 4 LEDs in a row instead of just one of the first 16.

//strip.setPixelColor(i, (val == 1) ? c_on : c_off);
int base = i * 4;
strip.setPixelColor(base, (val == 1) ? c_on : c_off);

So I just commented out the first line - see above - and added the lines below. After I could not believe that it does not work anymore I reduced the line to the first one working with base. Now - I can have a value between 0 and 15, 15*4=60, so no out of bounds or so here. itā€™s just an int between 0 and 60 passed into the setPixelColor() - and it halts the spark. I can run this once and then the spark reports function not found.

Is this the same for you?

Yeah it was the sameā€¦ and I know there was some other issue before that was blocking immediately. Now I think the problem was just that we might have been running up against the other timeout that occurs when you block the function call from the web for too long. Itā€™s hard to keep these all in memory sometimesā€¦ tends to get a little annoying :smile:

But once I remembered thisā€¦ I changed the code to the following:

#include "Spark_NeoPixel.h"
 
int lights(String command);
 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(64, D2);
 
uint16_t channels = 0x0000; // All lights off
bool updateTime = false; // Time to update flag
bool s = false;

void setup() {
  pinMode(D7,OUTPUT);
  digitalWrite(D7,HIGH);
  strip.begin();
  strip.show();
  Serial.begin(9600);
  while(!Serial.available());
  Spark.function("lights", lights);
  Serial.println("Ready.");
}
 
void loop() {
  s = !s;
  digitalWrite(D7,s);
  delay(100);
  if(updateTime) updateLights();
}
 
void updateLights() 
{
  updateTime = false;
  const uint32_t c_on = strip.Color(255, 255, 255);
  const uint32_t c_off = strip.Color(0, 0, 0);
    
  for (uint16_t i = 0; i < 16; i++)
  {
    uint16_t val = (channels & (1 << i)) ? 1 : 0; // is bit set or clear?
    Serial.print(i, DEC);
    Serial.print("->");
    Serial.print(val, DEC);
    Serial.print(" BASE: ");
       
    //strip.setPixelColor(i, (val == 1) ? c_on : c_off);
    uint16_t base = i * 4;
    Serial.println(base, DEC);
    delay(50);
    strip.setPixelColor(base, (val == 1) ? c_on : c_off);
    strip.setPixelColor(base+1, (val == 1) ? c_on : c_off);
    strip.setPixelColor(base+2, (val == 1) ? c_on : c_off);
    strip.setPixelColor(base+3, (val == 1) ? c_on : c_off);      
  }
  strip.show();
}

int lights(String command) 
{
  Serial.println("lights called with command " + command);
  delay(100);
  if(command.length() == 0)
    return -1;
    
  uint16_t number = command.toInt();
  if(number > 15)
    return -2;
 
  channels ^= (1 << number); // toggle the bit (0 - 15)
  updateTime = true;
  return 200;
}

Now it runs the longer delayed stuff from the loop(), and letā€™s the lights() function call return quickly.,. which works!

All, the Spark Core NeoPixel Library now supports 800 KHz and 400kHz bitstream NeoPixels! WS2812, WS2812B and WS2811. See the example for how to select between these different LEDs. Technically there are two timing schemes, both the WS2812 and WS2812B are the same unified 800kHz timing. WS2811 uses the slower 400kHz timing.

https://github.com/technobly/SparkCore-NeoPixel

1 Like

@BDub Iā€™m sorry, but even the decoupled version that I also tried before stops to work for me after the first request. I can toggle one channel for 4 LEDS once, then the same call again will report at timed out. :frowning: Did this really work for you with multiple calls?

Iā€™m wondering if someone from Spark, @zach, would have some input. It seems to be a really hard to understand problem.

Yeah I can toggle on and off LEDs with the decoupled version no problem.

Iā€™ve just tried the latest code from Github - and it least with my 8x8 RGB123 board it does not work any more. I set the mode to WS2812B PIN to my D0 and the count to 64 - but I seem to see some random 3 pixels.

On an arduino it works all fine, could there be an issue with the latest code on Github?

There shouldnā€™t be, I tested it in all modes. Can you post a link to your current code so I can have a look?