Dynamically determine length of WS2812B LED strands

arduinodlb:
At the end of the day, it's not magic. Not even Chinese magic.

WS2812B chips do not remember their state. If you eliminate the impossible, what remains must be the truth (paraphrased from Sherlock Holmes).

If what you are saying is true, and I understand it correctly, when you plug the leds back in the controller chip must re-send the LED data. It is a test setup, so it's plausible they may have done this.

^^ well said. a test setup would make sense to check each led and verify if one exists. I am impressed that they have done this, and being that each chip was setup to function a certain way I don't doubt that a return line is impossible from them. I still have yet to test the octows2811 stuff yet...maybe that will help. :confused: I dunno.

V1x0r:
^^ well said. a test setup would make sense to check each led and verify if one exists. I am impressed that they have done this, and being that each chip was setup to function a certain way I don't doubt that a return line is impossible from them. I still have yet to test the octows2811 stuff yet...maybe that will help. :confused: I dunno.

Well that's what I'm basically saying to do. Yes, the WS2812 "remembers" whatever the last block of data was, but it can't send that back out again. It will hold that color forever though, until power cycles and then it forgets. I plan to take advantage of that to reduce the need to do updates, so my Arduino can handle some other stuff while it runs the lights. If the controller can measure the current draw even in a simple on/off way, it could easily run a test on the currently connected light strip - when you turn it on, is there any visible flashing or anything before it starts the pattern?

The only data that ever comes 'out' of a WS2812 is the 'extra' data that it passes on after it eats 24 bits for itself - that 'out' signal is just the input signal, re-transmitted - there is no logic on that line, just an amplifier. The WS2812 never transmits the color it lighted up with, it eats that and keeps it.

It makes sense that these don't have a 'read' function, because theoretically, you're the one who sent the data in the first place, and there's no other way to change the values unless you send them. It's not functional as any kind of input device, so there's no reason to read it. Since these are intended to be used in large arrays, the component itself must be cheap - so they aren't gonna add some redundant feature like "give me the numbers I just sent you" which would just increase the cost and nobody would use that feature - it would be hard to compete with other chips that don't have that feature and thus, are cheaper.

BTW - you said you didn't like Pololu library - can you say why and give me some links to better ones then? To me, it's a one-function library, how much better can it be?

http://waitingforbigo.com/ FastSpi2 is one of my favorites, along with https://github.com/adafruit/Adafruit_NeoPixel.

I hope those are helpful and fun for you. I haven't tested the recent additions of the Adafruit NeoPixel library yet but those should be pretty awesome! faster pwm for multiple strips at once. (for Teensy...but w/e)

as for being able to read...if you are sending the data as an array then you naturally wouldn't need to know the color of the strip. unless your code tells the strips what to do more mathematically.

#include "Adafruit_NeoPixel.h"
#include <avr/power.h>
#define PIN 6
#define NUM_PIXELS 45
#define HALF_PIXELS (NUM_PIXELS/2)

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
    if(F_CPU == 16000000) clock_prescale_set(clock_div_1);
    strip.begin();
    strip.show();
}

void loop() {int i = 0;
  int nexti = 0;
  int spacing = 3;
  int colorcount = 0;
   int color = 0x00FF00;
  while (1) {
   nexti++;
   if (nexti >= spacing) {
     nexti = 0;
   } 
   int variance = 8;
   colorcount += variance;
   if (colorcount >= 253) {
     colorcount = 0;
   }
   int numlight = 1;
   while (i < NUM_PIXELS) {
     int tmpcolor = colorcount + ( numlight * variance);
     while (tmpcolor > 255) {
       tmpcolor -= 255;
     }
     color = colorWheel(tmpcolor);
   strip.setPixelColor(i, color); strip.show(); 
   i += spacing;
   numlight++;
   }
   delay (90);
   i = nexti;
  strip.setBrightness(0);
  strip.setBrightness(255);
  }
}

uint32_t colorWheel(byte WheelPos) {
  byte state = WheelPos / 21;
  switch(state) {
    case 0: return strip.Color(255, 0, 255 - ((((WheelPos % 21) + 1) * 6) + 127)); break;
    case 1: return strip.Color(255, ((WheelPos % 21) + 1) * 6, 0); break;
    case 2: return strip.Color(255, (((WheelPos % 21) + 1) * 6) + 127, 0); break;
    case 3: return strip.Color(255 - (((WheelPos % 21) + 1) * 6), 255, 0); break;
    case 4: return strip.Color(255 - (((WheelPos % 21) + 1) * 6) + 127, 255, 0); break;
    case 5: return strip.Color(0, 255, ((WheelPos % 21) + 1) * 6); break;
    case 6: return strip.Color(0, 255, (((WheelPos % 21) + 1) * 6) + 127); break;
    case 7: return strip.Color(0, 255 - (((WheelPos % 21) + 1) * 6), 255); break;
    case 8: return strip.Color(0, 255 - ((((WheelPos % 21) + 1) * 6) + 127), 255); break;
    case 9: return strip.Color(((WheelPos % 21) + 1) * 6, 0, 255); break;
    case 10: return strip.Color((((WheelPos % 21) + 1) * 6) + 127, 0, 255); break;
    case 11: return strip.Color(255, 0, 255 - (((WheelPos % 21) + 1) * 6)); break;
    default: break;
  }
}

That example is very choppy I know...it needs a faded appearance on the empty colors. colorwheel is a pain to work with for that so I will probably just use rgb values. :slight_smile:

Yeah, this is the code for the GetPixelColor function... it's just reading an array. That seems to be what the library does - maintains an array of colors and pumps them out to the strip on request.

uint32_t Adafruit_NeoPixel::getPixelColor(uint16_t n) const {

  if(n < numLEDs) {
    uint16_t ofs = n * 3;
    return (uint32_t)(pixels[ofs + 2]) |
#ifdef NEO_RGB
      (((type & NEO_COLMASK) == NEO_GRB) ?
#endif
    ((uint32_t)(pixels[ofs    ]) <<  8) |
      ((uint32_t)(pixels[ofs + 1]) << 16)
#ifdef NEO_RGB
      :
    ((uint32_t)(pixels[ofs    ]) << 16) |
      ((uint32_t)(pixels[ofs + 1]) <<  8) )
#endif
      ;
  }

  return 0; // Pixel # is out of bounds
}

yup. hence my post earlier not working. it fed back the array color and not the registered color on the led. :frowning: hence why I want to try out
OctoWS2811 LED Library, Driving Hundreds to Thousands of WS2811 LEDs with Teensy 3.0 though, I haven't looked at it's definitions just yet so it may be doing the exact same thing. :confused:

V1x0r:
OctoWS2811 LED Library, Driving Hundreds to Thousands of WS2811 LEDs with Teensy 3.0 though, I haven't looked at it's definitions just yet so it may be doing the exact same thing. :confused:

If it has any kind of GetColor() function, it has to be reading an internally maintained array, because there is no way to get information out of the WS2812, it is input-only.

that is why this stupid thing is so confusing! how do they do this!! >_<

V1x0r:
how do they do this!! >_<

Well if you could monitor the presence / absence of current draw, you could send a single lit LED along the row and when the current drops to zero you know you have shifted it off the end. This could be one on start up so fast that you would not see it flicker.

That is an excellent point! and an astute yet very simple thing to do! simply "pin 4" would be used as a check pin gathering use information. I haven't searched this up yet to test...any ideas on monitoring current draw via arduino? I'll go search this after I send this out too. :slight_smile:

Grumpy_Mike:
Well if you could monitor the presence / absence of current draw, you could send a single lit LED along the row and when the current drops to zero you know you have shifted it off the end. This could be one on start up so fast that you would not see it flicker.

I think you'd notice that...can somebody watch the LEDs very carefully on power up and report back? (especially the last LED in the strip)

With the controllers in those photos there's really only one way they can be doing it - measure the current.

V1x0r:
any ideas on monitoring current draw via arduino?

You could put a resistor in the circuit and measure voltage drop across it while you search for the end.

When you're happy you've found it, bypass the resistor with a MOSFET.

Grumpy_Mike:

V1x0r:
how do they do this!! >_<

Well if you could monitor the presence / absence of current draw, you could send a single lit LED along the row and when the current drops to zero you know you have shifted it off the end. This could be one on start up so fast that you would not see it flicker.

Yeah that's why I basically suggested to do that same thing but 'backwards' starting beyond the end of the string and lighting up one light at the end until see some current flow. That way you would only see one LED blink real fast on the end. Starting at the beginning, I think you would see all the LEDs blink, so that's why I'm wondering if there's any flickering or anything right after startup. I agree that with three wires that's probably the only way. With four wires, that fourth wire could be either a data line returning from the end, or it could be a current sensor, and that would give a way to measure the string. I don't think there's any other way really.

any ideas on monitoring current draw via arduino?

A small resistor in the ground with an analogue input on the other side. You are only looking for a few mV so the resistor can be very small indeed. In normal operation you would not notice it.

Grumpy_Mike:

any ideas on monitoring current draw via arduino?

A small resistor in the ground with an analogue input on the other side. You are only looking for a few mV so the resistor can be very small indeed. In normal operation you would not notice it.

Wouldn't that measure the current used by the Arduino? Doesn't that fluctuate a lot?

Wouldn't that measure the current used by the Arduino?

No you misunderstand.
The ground return from the LED strip has a 2R2 ( or so ) resistor before it get to the arduino ground, Then you measure on the LED side of this resistor.

So, i can't see under the chip for what pin goes where and I'm not at home to test points...but it appears as though they are using multiple pins...granted, three of them would have to be devoted to push pin. it does look like the pins are devoted to the blatantly obvious components. Unless they are treating the din pin as both input and output. (possible?) if it is an input then the current draw check would be logical from there. anyway...It would be cool to pull current draw. :slight_smile:

the rf version has dual grounds...I should look at that closer again and see if that second ground goes elsewhere. on the small adapter it has a large ground connection so maybe that is going to a resistor on one of the input pins. Great idea to check! I did post the images for both boards...but a better image is of the small one (which is the one mostly in question) it does have three resistors

I don't have a fast enough camera to catch if a pixel illuminates or not. mind you, some of the leds will also flicker once power is applied to the strip anyway.

V1x0r:
So, i can't see under the chip for what pin goes where and I'm not at home to test points...but it appears as though they are using multiple pins...granted, three of them would have to be devoted to push pin. it does look like the pins are devoted to the blatantly obvious components. Unless they are treating the din pin as both input and output. (possible?) if it is an input then the current draw check would be logical from there. anyway...It would be cool to pull current draw. :slight_smile:

No it's not possible to use that pin as any kind of output. The chip just doesn't have that function. It would be documented in the data sheet, and there would be some method of triggering the function to output data, and there's nothing like that.

I think you would need to measure current draw on the power pins, not the signal line, because that's just carrying binary data, that you are sending, so anything you measure there would be a result of what you sent, not what's happening on the light string, and that's if reading the current of a data line was meaningful anyway. It would be interesting to know if the resistors are connected to some kind of current sensor. Can you take a high quality photo of the boards? I couldn't really tell anything from the previous photos.

Grumpy_Mike:

any ideas on monitoring current draw via arduino?

A small resistor in the ground with an analogue input on the other side. You are only looking for a few mV so the resistor can be very small indeed. In normal operation you would not notice it.

You have to be very careful with that. Those strips can draw a LOT of amps - a 5m strip with 60 LEDs/m and all the LEDs turned on needs over 18 amps. That's why I suggested including a MOSFET to bypass the resistor when you finish measuring.

Grumpy_Mike:
The ground return from the LED strip has a 2R2 ( or so ) resistor before it get to the arduino ground, Then you measure on the LED side of this resistor.

A 2R2 resistor at 18 amps will drop 40 volts... :slight_smile:

(Or catch fire in the attempt)