Shop OBEX P1 Docs P2 Docs Learn Events
Fun With WS2812(B) LEDs - Page 2 — Parallax Forums

Fun With WS2812(B) LEDs

2

Comments

  • Tim-MTim-M Posts: 522
    edited 2013-12-20 16:29
    Hey Duane,

    Adafruit has some inexpensive slip rings that will help you get power and signals to your wheels...

    http://www.adafruit.com/index.php?main_page=adasearch&q=slip+ring

    Tim
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-20 20:06
    David Betz wrote: »
    I saw Jon's recommendation of the TC4427 but I'm ashamed to admit that, being mostly a programmer, I'm not sure how to go about wiring this up. :-(

    I haven't ordered any of the TC4427 chips yet. I'm hoping the datasheet will shed some light on how to use them. If not, I bet we could talk JonnyMac into helping us out. I'll try to get some ordered in the next few days and I'll post how I wire them up once they arrive (I might already have one in one of my bags of ICs, I'll see if I can find one).
    David Betz wrote: »
    I'm slowly starting to understand what your code is doing. It's very clever. I hope you don't mind if I convert it to C.

    Not at all. It's always fun to see others using code I wrote. I feel like my time I spent writing the code was even better spent than when I thought I was the only beneficiary of the code.

    As I mentioned, I'm pleased with the outcome of the program. The swirling colors was just what I was hoping to achieve when I started writing the code.

    There is a "wheel" object for picking colors that JonnyMac translated to Spin from the AdaFruit code. I use the wheel method myself but I also use my "MergeColors" method more than the "Wheel" method since the "MergeColors" method lets you change the colors by as much or as little as you'd like and over as many or as few LEDs as you'd like.

    I'm glad you feel like you're understanding it. I'm not sure if I could follow what I did if I hadn't been the one to write it in the first place (and sometimes I have trouble even though I wrote it).
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-20 20:15
    Tim-M wrote: »
    Hey Duane,

    Adafruit has some inexpensive slip rings that will help you get power and signals to your wheels...

    http://www.adafruit.com/index.php?main_page=adasearch&q=slip+ring

    Tim

    I thought about those slip rings when I first started trying to add LEDs to the wheels. I just don't see how they are going to be a help. I don't see where I can add a slip ring like those to an ActivityBot's wheel?

    I've made some progress on transferring power and data to a turning wheel. I'll try to post some pictures (and hopefully video) soon showing my attempts so far. I've burned out two LEDs in my ring so far. The first LED of the ring appears to be very susceptible to bad contacts in the power transmission. I think the trouble occurs when the 5V and signal lines are connected but the ground isn't connected. This doesn't appear to harm a single LED but 16 LEDs will cause too much current to pass through (out) the LED's data line and burn it out. Just the first LED of the ring is damaged, if the one LED is replaced, the ring will work again. I've replaced the first LED twice so far. I'll need to figure out some component to protect the LED when the ground connection isn't present.
  • David BetzDavid Betz Posts: 14,514
    edited 2013-12-21 04:17
    Duane Degn wrote: »
    I haven't ordered any of the TC4427 chips yet. I'm hoping the datasheet will shed some light on how to use them. If not, I bet we could talk JonnyMac into helping us out. I'll try to get some ordered in the next few days and I'll post how I wire them up once they arrive (I might already have one in one of my bags of ICs, I'll see if I can find one).
    There is a circuit in the datasheet but I'm not sure how to translate it to the Propeller driving the LED rings. For one thing, it looks like the circuit they provide has 5V input and some other voltage output. I'm looking forward to JonnyMac's tutorial on using this part! :-)

    Not at all. It's always fun to see others using code I wrote. I feel like my time I spent writing the code was even better spent than when I thought I was the only beneficiary of the code.

    As I mentioned, I'm pleased with the outcome of the program. The swirling colors was just what I was hoping to achieve when I started writing the code.

    There is a "wheel" object for picking colors that JonnyMac translated to Spin from the AdaFruit code.
    I looked for the original AdaFruit code but it's hard to read because there is so much embedded assembly language. I guess the JonnyMac's Spin code has a PASM driver as well but most of the higher level code is separate from that. Somehow his Spin code was easier to read.
    I use the wheel method myself but I also use my "MergeColors" method more than the "Wheel" method since the "MergeColors" method lets you change the colors by as much or as little as you'd like and over as many or as few LEDs as you'd like.

    I'm glad you feel like you're understanding it. I'm not sure if I could follow what I did if I hadn't been the one to write it in the first place (and sometimes I have trouble even though I wrote it).
    At first I was totally lost but I started with the Wheel function because I recognized it from JonnyMac's code. That was pretty easy to understand. I went on to MergeColors and Mirror. I can't say I've figured out the code that constantly changes the speed and direction of the rotation or how you handle multiple rings. I'm still working on that.
  • David BetzDavid Betz Posts: 14,514
    edited 2013-12-21 04:48
    What does the Rotate function do? It isn't used in the code that you posted.
  • skylightskylight Posts: 1,915
    edited 2013-12-21 12:56
    Duane what is the max current consumption of those Neopixel rings? It mentions 18ma constant current drivers so am assuming 16x18 is 288ma is this a correct assumption? If so I could power the one ring from the quickstart whilst plugged to usb?
    Also i'm now worried about this level shifting business, is it a no go without using them? I was going to connect the data in to a prop pin directly is this not advisable?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-21 13:18
    David Betz wrote: »
    At first I was totally lost but I started with the Wheel function because I recognized it from JonnyMac's code. That was pretty easy to understand. I went on to MergeColors and Mirror. I can't say I've figured out the code that constantly changes the speed and direction of the rotation or how you handle multiple rings. I'm still working on that.

    I'll attempt to remember and explain what I did. The code to modify which colors are used and how fast the colors spin is the loop inside the Main method.
    repeat 
        repeat localIndex from 0 to RINGS_IN_USE - 1
    
    
          if CheckRingTime(localIndex)
            finalColorIndex[localIndex] := initialColorIndex[localIndex] + difference[localIndex] 
            if initialColorIndex[localIndex] > 255 
              initialColorIndex[localIndex] -= 255
              positionChange[localIndex] *= -1
            if finalColorIndex[localIndex] > 255 
              finalColorIndex[localIndex] -= 255
            difference[localIndex] += differenceDirection[localIndex]
            if difference[localIndex] => MAX_DIFFERENCE
              differenceDirection[localIndex] := -1
            elseif difference[localIndex] =< MIN_DIFFERENCE
              differenceDirection[localIndex] := 1
            initialColor := WheelDim(initialColorIndex[localIndex], BRIGHTNESS)
            finalColor := WheelDim(finalColorIndex[localIndex], BRIGHTNESS)  
            Mirror(initialColor, finalColor, ringAddress[localIndex], position[localIndex])
            initialColorIndex[localIndex]++
            position[localIndex] += positionChange[localIndex]
            if  position[localIndex] > MAX_RING_INDEX
              position[localIndex] -= LEDS_IN_RING
            elseif position[localIndex] < 0
              position[localIndex] += LEDS_IN_RING
    

    I'll go through a few lines at a time.
    repeat 
        repeat localIndex from 0 to RINGS_IN_USE - 1
    

    I start out with an endless loop and then cycle through each of the rings. The constants "RINGS_IN_USE" and "LEDS_IN_RING" can be set in the CON section.
          if CheckRingTime(localIndex)
    

    A lot of the timing issues are dealt with in "CheckRingTime". For one, the time is checked to see if the ring colors should be updated. From within "CheckRingTime" the method "CheckStripSpeed" is called. "CheckStripSpeed" modifies the time interval used between color changes so the speed of the swirl is constantly changing. Once the speed reaches a maximum value the speed starts to decrease (delay increase). A minimum speed also triggers a reversal in the way the speed is changed.

    If the delay time as passed the code continues on below. Otherwise the next LED ring is check to see if its delay period has expired.

    Most of the loop consists of finding three of the four parameters used in the call to the 'Mirror" method.

    When the "Mirror" method is called, it requires four parameters. An initial color, a final color, a position and a memory address. The memory address is static. It was found earlier in the "Main" method and it's the memory location JonnyMac's driver uses to find the LED color values. The other three parameters need to be computed each time it's time to change the colors in the ring.

    The first part of the loop find the two color parameters and adjusts the variables used to modify these parameters.

    Colors are described several different ways. One way to describe a color is with a long. Within the long there is a byte to indicate how much of each of the three colors (RGB) are present in the color. There's also a color index which is a single byte value representing the color's position on the color wheel. It's this color index I'm finding at the beginning of the loop.

    The ring will display a portion of the rainbow. Because of the way "MergeColors" works it doesn't do much good to merge colors more than halfway around the color wheel. Since any color more than halfway around will actually start to get closer to the beginning color rather than further from it. (How far can a dog run into the woods? Halfway, because after than he's running out of the woods.)

    I use "difference" to indicate how far apart the two colors will be. This difference amount changes by +/- 1 each loop. The "difference" value is limited to values between 1/6 of the wheel and 1/2 of the color wheel.
            finalColorIndex[localIndex] := initialColorIndex[localIndex] + difference[localIndex] 
            if initialColorIndex[localIndex] > 255 
              initialColorIndex[localIndex] -= 255
              positionChange[localIndex] *= -1
            if finalColorIndex[localIndex] > 255 
              finalColorIndex[localIndex] -= 255
            difference[localIndex] += differenceDirection[localIndex]
            if difference[localIndex] => MAX_DIFFERENCE
              differenceDirection[localIndex] := -1
            elseif difference[localIndex] =< MIN_DIFFERENCE
              differenceDirection[localIndex] := 1
    

    In the above code I found the initial and final color index and took care of the bookkeeping needed to keep the difference in colors continually changing. Since the color index will be used on a color wheel, number just get wrapped around once they are larger than 255 or lower the zero.
            initialColor := WheelDim(initialColorIndex[localIndex], BRIGHTNESS)
            finalColor := WheelDim(finalColorIndex[localIndex], BRIGHTNESS)  
    
    

    The above code changes the color index (a byte) to a full color held in a long.

    In order to get all the colors to fit in a one byte color wheel, the individual color transitions are relatively coarse. I wanted the ring transitions to be more subtle. That's why I use the MergeColors method from within the mirror method.

    Now that the initial color and final color have been determined, I use these values in the call to the "Mirror" method. The variable "position" will be adjusted after the call to "Mirror" for use in the next loop.

    I'll talk about "Mirror" in a bit.
            Mirror(initialColor, finalColor, ringAddress[localIndex], position[localIndex])
            initialColorIndex[localIndex]++
            position[localIndex] += positionChange[localIndex]
            if  position[localIndex] > MAX_RING_INDEX
              position[localIndex] -= LEDS_IN_RING
            elseif position[localIndex] < 0
              position[localIndex] += LEDS_IN_RING
    

    After the call to "Mirror" some more bookkeeping is done. "positionChange" is used to allow the swirl direction to be reversed. This reversal happens earlier in the loop whenever the full rainbow has been used as an initial color.

    One to the "Mirror" method.
    PUB Mirror(initialColor, finalColor, localPtr, position) | localIndex, scratchBuffer[HALF_RING]'' Fill long buffer at "localPtr" with a mirrored colors.
    
    
      repeat while position > MAX_RING_INDEX
        position -= LEDS_IN_RING
      MergeColors(initialColor, finalColor, @scratchBuffer, HALF_RING)
     
      result := position - 1
      repeat localIndex from 0 to MAX_HALF_INDEX
        if result < 0
          result += LEDS_IN_RING
        if position > MAX_RING_INDEX
          position -= LEDS_IN_RING
                 
        long[localPtr][position++] := scratchBuffer[localIndex]
        long[localPtr][result--] := scratchBuffer[localIndex]  
     
    
    
    

    PUB Mirror(initialColor, finalColor, localPtr, position) | localIndex, scratchBuffer[HALF_RING]'' Fill long buffer at "localPtr" with a mirrored colors.
    

    The purpose of the method is to fill both sides of the ring with a mirror image of one another. The array "scratchBuffer" is used to hold colors to distribute to the two sides of the ring.
      repeat while position > MAX_RING_INDEX
        position -= LEDS_IN_RING
    

    The above code just wraps the position value so it stays within the size of the ring. The position value will determine where the initial color will be placed on the ring. The final color will be halfway around the ring.
    
      MergeColors(initialColor, finalColor, @scratchBuffer, HALF_RING)
    
    

    The "MergeColors" fills an array (scratchBuffer in this case) with a linear color transition between the initial and final colors. Unlike the "Wheel" method, the "MergeColors" method does not use a color wheel. Each of the red, green and blue values are linearly scaled to fill the array. If any one of the three colors is zero in both the initial and final colors, then that particular color will remain zero through the entire transition. You can not use "MergeColors" to produce a full rainbow, only a section of it.

    Now that the scratch buffer has been filled with the desired colors I can get on with fill the ring with these colors.
     
      result := position - 1
    
    

    I'm going to use "result" and "position" to fill assign two LEDs in the ring the same color. The two LEDs first to be assigned are right next to each other so "result" is given a value one less than the "position" value.

    It looks like "position" gets incremented and "result" gets decremented.
    
      repeat localIndex from 0 to MAX_HALF_INDEX
        if result < 0
          result += LEDS_IN_RING
        if position > MAX_RING_INDEX
          position -= LEDS_IN_RING
                 
        long[localPtr][position++] := scratchBuffer[localIndex]
        long[localPtr][result--] := scratchBuffer[localIndex]  
     
    
    
    

    The rest of the above code just checks for wrap around to make sure the values of "result" and "position" are valid ring positions

    David Betz wrote: »
    What does the Rotate function do? It isn't used in the code that you posted.

    The "Rotate" method will shift the colors in a buffer (which could be the buffer of a ring of LEDs) by some number of positions "localRotation". In the case of the rings, you'd want to use the size of the rings as one of the parameters.

    Since the "Mirror" method has a parameter "position", the "Rotate" method ended up not being needed.

    "Rotate" would be useful if you had a ring filled with colors you didn't want to change but you did want to change the position of the colors in the ring. Since I ended up constantly changing the colors while the positions changed, I didn't end up using the "Rotate" method. I thought someone else might want to rotate a set of fix colors so I left it in the program.

    Earlier in the thread you called my code "clever". Thanks. I'm afraid you don't think it's half as clever as I do. I'm downright amazed the code works as well as it does.

    This was one of those times where the envisioned outcome of a project was just what I had hoped for when starting it. These swirling LEDs are just the effect I'd hoped they'd be.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-21 13:27
    skylight wrote: »
    Duane what is the max current consumption of those Neopixel rings? It mentions 18ma constant current drivers so am assuming 16x18 is 288ma is this a correct assumption? If so I could power the one ring from the quickstart whilst plugged to usb?
    Also i'm now worried about this level shifting business, is it a no go without using them? I was going to connect the data in to a prop pin directly is this not advisable?

    I confess to powering three rings off the QuickStart's Vin pin while using USB very frequently. I also regularly connect the data pin directly to the Prop. I'll leave you with a "no comment" as to the advisability of the USB power to the LEDs but connecting the data pin directly to the Prop shouldn't be a problem. The exception is if the ground pin is disconnected to the LEDs then the Prop pin could be fried. It appears these LEDs can be powered and controlled with just 5V and data. The low pulse on the data appears to be used to route the current when a ground connection is missing. I've burned out two LEDs this way and I suspect this can be hard on the Prop. I haven't seen any harm to the Prop so far and while I plan to use level shifters in my future projects I don't worry about driving the LEDs directly from a Prop pin.

    I purposely tried to fry one of these LEDs by using reverse power and other techniques. The LED kept on working. It appears the danger to the LEDs only occur when they are part (first) of a strand. I didn't try any voltages above 5V when attempting to damage a single LED.
  • David BetzDavid Betz Posts: 14,514
    edited 2013-12-21 21:49
    Duane Degn wrote: »
    I'll attempt to remember and explain what I did.
    Thanks for the detailed description of how your code works! I had figured out some of that already but you've certainly filled in a lot of blanks. I ended up doing something much simpler for my Christmas ornament project. I used some fairly simple code to fill the ring with a constantly changing rainbow of colors. I didn't try to make the transitions smooth like you did but instead let the LEDs "twinkle". This worked out fairly well since I mounted the ring behind a clear plastic faceted snow flake ornament that I bought from a Christmas store. I'll make a video once I get everything mounted and installed on our tree. In the meantime, here is the C code required to do this.
    #include <stdint.h>
    #include <propeller.h>
    #include "ws2812.h"
    
    #define LED_PIN     15
    #define LED_COUNT   16
    
    int main(void)
    {
        uint32_t colors[LED_COUNT];
        int cog;
            
        memset(colors, 0, sizeof(colors));
        
        if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
            return 1;
            
        for (;;) {
            ws2812_fill_wheel_continuous_dim(colors, LED_COUNT, LED_COUNT+5, 128, 100);
            ws2812_pause(1000);
        }
            
        cogstop(cog);
        
        return 0;
    }
    

    Here is the ws2812_fill_wheel_continuous_dim function. The ws2812_wheel_dim function is pretty much identical to your WheelDim function.
    void ws2812_fill_wheel_continuous_dim(uint32_t *colors, int count, int samples, int brightness, int delay)
    {
        int i = 0, di = 1;
        int j = 0;
        for (;;) {
            colors[i] = ws2812_wheel_dim(j * (255 / samples), brightness);
            ws2812_pause(delay);
            i += di;
            if (i >= count) {
                di = -1;
                --i;
            }
            else if (i < 0) {
                di = 1;
                ++i;
            } 
            if (++j >= samples)
                j = 0;    
        }
    }
    
  • TharkunTharkun Posts: 67
    edited 2013-12-22 05:46
    Hi,

    can someone tell me whether it is possible to build a POV-Display with those LEDs( WS2812),
    i mean something like this:

    http://www.youtube.com/watch?feature=player_embedded&v=wdRf6fLRGvc

    How many times can i turn on/off the LEDs per second. The Datasheed says:

    1.25µs (per Bit) * 24 + 50µs(reset)= ~ 0.01ms
    that means 100,000 switches per second are possible ? I think my calculation is wrong, what about latency and internal timings of the ws2811 ?

    When putting the LED on a spinning wheel i need at least a minimum of about 1000-2000 switches per second.

    Any thoughts ?
  • TharkunTharkun Posts: 67
    edited 2013-12-22 05:52
    ok, find this on adafruit:

    Can I use NeoPixels for POV (persistence of vision) displays?
    Not recommended. The refresh rate is relatively low (about 400 Hz), and color displays in fast motion may appear “speckled.” They look fine when stationary though. For POV use, LPD8806 strips will look much better (they have about a 4 KHz refresh rate).

    It's a pity, because it's so easy to handle these LEDs without the use of driver-ICs etc.

    :-(
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-22 07:37
    Edit: I think the 400Hz doesn't have anything to do with how fast the data can be transmitted. See post #46 below.

    I wonder how they came up with 400Hz? My guess is that's what the Arduino's refresh rate is. Not the mighty Propeller's.

    The Arduino has to do a bunch of computations between refreshes. The Propeller doesn't need to pause between refreshes and JonnyMac's driver just keep pumping out bits whether the data has changed or not.

    I was just looking at JonnyMac's driver and I think it wouldn't be too hard to modify to use it in a POV setup. The hub pointer would just need to be incremented with each full loop through the pixels.

    There's time to do this during the 50us refresh pause. You might want to add a delay to slow down the refresh. The delay could be computed based on some sort of tachometer in order to hold the image stead on the display.

    Punching some numbers into the calculator this is what I come up with for an 8 pixel display.

    1 / ((1.25us/bit * 24bit * 8/refresh) + 50us/refresh) * (1s/1,000,000us)) = 3,448 refresh/s

    IMO 3,448 Hz isn't too bad.

    You could almost double the rate by using multiple cogs for the driver and make smaller chains of LEDs.

    If you used one cog to drive 2 pixels you could increase the rate to over 9 KHz.

    I think the 3.4 KHz for all 8 pixels should be good enough for a simple display.

    How many pixels did you have in mind.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-22 08:03
    David Betz wrote: »
    I didn't try to make the transitions smooth like you did but instead let the LEDs "twinkle". This worked out fairly well since I mounted the ring behind a clear plastic faceted snow flake ornament that I bought from a Christmas store. I'll make a video once I get everything mounted and installed on our tree.

    My initially dimming the colors ends up destroying a lot of the color information. So my talk of smooth color transitions only really applies to the LEDs if they're left at their full brightness. The "Wheel" method retains enough color information to be plenty usable.

    I look forward to seeing the video.
  • TharkunTharkun Posts: 67
    edited 2013-12-22 08:58
    Duane Degn wrote: »
    1 / ((1.25us/bit * 24bit * 8/refresh) + 50us/refresh) * (1s/1,000,000us)) = 3,448 refresh/s

    IMO 3,448 Hz isn't too bad.

    How many pixels did you have in mind.

    My plan is to use one prop-pin per LED (8,16 or 24 LEDs) and not use cascading.
    Than the refresh rate increases to 8 * 3,448 refresh/s !?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-22 09:21
    Duane Degn wrote: »
    I wonder how they came up with 400Hz?

    It just dawned on me, they weren't talking about the ability to refresh the data they were talking about the WS2811 chip. Darn.

    400 Hz might be enough for a small slow POV. If you used two strips 180 degrees from each other and limited the size of the display, I bet it could still work.

    If the display spun at 30Hz you'd have 13 horizontal pixels.

    It would be nice if these could be used this way. They're so easy to wire up.

    Edit: I just say your last post Tharkun. I hadn't refreshed the thread before making this post. I'll reply to your new post shortly.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-22 09:47
    Tharkun wrote: »
    My plan is to use one prop-pin per LED (8,16 or 24 LEDs) and not use cascading.
    Than the refresh rate increases to 8 * 3,448 refresh/s !?

    The fastest a single LED could be refreshed (with data) is 12.5 KHz. With a single pixel, it would take 30us to send the data but then there's the 50us wait period to indicate the end of the frame. The data line would spend most of its time idle.

    You'd need to modify the WS2811 driver if you wanted to have more than 7 data lines active at once. I doubt it would be too hard to have the driver alternate between two data lines so the one LED is refreshed while the other LED's data line is paused. I don't think this is really necessary though. I have a feeling the 400Hz refresh cycle will be the limiting factor.

    As I've thought about this, I think the 400Hz problem might not be as big of a problem if the colors in the LED were either on or off. However if you're not taking advantage of the WS2811's ability to control the colors fully, you might as well just use normal RGB LEDs.

    Edit: The more I think about the 400Hz issue the more I think using these LEDs in a POV display is a bad idea.
  • stupotstupot Posts: 2
    edited 2013-12-22 12:30
    hi duane,

    just wondering if you mind sharing the gerber files for your led ring? I have been having a play about with kicad designing my own, but I am a little uneasy getting 10 made as it is not somthing I have done before :)

    no worries if not
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-22 13:17
    stupot wrote: »
    hi duane,

    just wondering if you mind sharing the gerber files for your led ring? I have been having a play about with kicad designing my own, but I am a little uneasy getting 10 made as it is not somthing I have done before :)

    no worries if not

    I question the sanity of anyone wanting to make their own 16 pixel ring when AdaFruit's rings are so reasonably priced. Welcome to the asylum.:smile:

    Keep in mind my ring uses the "B" version of the LED.

    I've attached the gerbers I sent to OSH Park. I'm not sure if other fab houses will allow the center cutout. Which fab house to you plan to use?

    If you need the center cutout removed from the gerbers let me know. It should be easy to make the change.

    I hope you let me know how the boards turn out and I hope you share any photos of videos you make with your rings.

    Edit(3/11/15): It's possible there's a more recent version of this design on my GitHub account
  • stupotstupot Posts: 2
    edited 2013-12-22 13:37
    thanks Duane

    i was goning to use http://www.seeedstudio.com as they seem the cheapest, I could probably get one of the ones from adafruit here in the UK, but I like the idea of soldering a few my self :)

    will get back with some photos in a few weeks when parts arrive.
  • skylightskylight Posts: 1,915
    edited 2013-12-24 07:22
    Duane Degn wrote: »
    I confess to powering three rings off the QuickStart's Vin pin while using USB very frequently. I also regularly connect the data pin directly to the Prop. I'll leave you with a "no comment" as to the advisability of the USB power to the LEDs but connecting the data pin directly to the Prop shouldn't be a problem. The exception is if the ground pin is disconnected to the LEDs then the Prop pin could be fried. It appears these LEDs can be powered and controlled with just 5V and data. The low pulse on the data appears to be used to route the current when a ground connection is missing. I've burned out two LEDs this way and I suspect this can be hard on the Prop. I haven't seen any harm to the Prop so far and while I plan to use level shifters in my future projects I don't worry about driving the LEDs directly from a Prop pin.

    I purposely tried to fry one of these LEDs by using reverse power and other techniques. The LED kept on working. It appears the danger to the LEDs only occur when they are part (first) of a strand. I didn't try any voltages above 5V when attempting to damage a single LED.
    Thanks for that information,as a matter of interest are you running at max current ie all leds full on and white?
    I think I can risk at least two rings off of USB, I intend to get a 5V 5 Amp PSU when I can afford it.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-24 08:42
    skylight wrote: »
    Thanks for that information,as a matter of interest are you running at max current ie all leds full on and white?

    Now that you mention it the LEDs are set to 1/3 brightness and the "Mirror" algorithm produces colors which are mixtures of two colors, none of the colors displayed turn on all three RGB components at once.

    I think in general, the rings are operating at 1/9 power.

    I'm glad you asked about this. Using 1/9 power is a significant detail.

    I use the reduced brightness so it's not uncomfortable working with the LEDs as I test the various patterns. These things are awfully bright.

    I generally don't run off USB power for very long. When I'm showing the rings to others, I use a pack of four NiMH AAs as the power source.

    It would be a good precaution to use a powered USB hub when powering the LEDs from USB.
  • skylightskylight Posts: 1,915
    edited 2013-12-24 09:06
    Yes agreed on the USB, as you say discussion makes you think of things that didnt occur before, I've been trying to work out ways of supplying 5v through batteries without resorting to using regulators and bingo your suggestion of using rechargables never entered my mind, 4 x 1.2v = 4.8v voila! thanks very much for that!
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-24 09:50
    skylight wrote: »
    Yes agreed on the USB, as you say discussion makes you think of things that didnt occur before, I've been trying to work out ways of supplying 5v through batteries without resorting to using regulators and bingo your suggestion of using rechargables never entered my mind, 4 x 1.2v = 4.8v voila! thanks very much for that!

    Four NiMH can be over 5.0V when freshly charged. You ought to make sure and measure the voltage to see if it's within limits before using the pack without a regulator. It seems like 5.5V is a common fully charged value but some packs may go even higher which could possibly damage some 5V devices.
  • skylightskylight Posts: 1,915
    edited 2014-01-03 10:37
    Duane Degn wrote: »
    Four NiMH can be over 5.0V when freshly charged. You ought to make sure and measure the voltage to see if it's within limits before using the pack without a regulator. It seems like 5.5V is a common fully charged value but some packs may go even higher which could possibly damage some 5V devices.
    Thanks for that Duane, perhaps I could drop 0.7v by placing a diode in series? may also stop problems having USB and Battery power connected at the same time when using a quickstart board?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-03 11:04
    skylight wrote: »
    Thanks for that Duane, perhaps I could drop 0.7v by placing a diode in series? may also stop problems having USB and Battery power connected at the same time when using a quickstart board?

    I'm not sure about either of your questions. I generally don't worry about the overvoltage of four NiMH unless I'm using something expensive. I generally try not to run the QuickStart off both battery and USB at the same time. I believe the Rev B version of the QuickStart has added protections in this regard.
  • skylightskylight Posts: 1,915
    edited 2014-01-03 14:16
    It was a thread I'd read some time back regarding the quickstart and having both forms of power connected at the same time could cause damage, unless as you may suggest that was only a problem with Rev A?

    I'm happy as my second neopixel ring arrived today so I can further use both yours and Jon's spin code to understand how to drive several rings at the same time
    Thanks for your help.
  • GarethGareth Posts: 278
    edited 2014-03-01 14:40
    @Duane .... My S2 thanks for the work with the NeoPixel code.... keep up the good work ;-)
    IMG_0917.png
    IMG_0918.png
    IMG_0919.png
    IMG_0920.png
    IMG_0921.png
    IMG_0922.png
    IMG_0923.png
    IMG_0924.png
    IMG_0925.png
    640 x 480 - 139K
    640 x 480 - 185K
    640 x 480 - 149K
    640 x 480 - 184K
    640 x 480 - 234K
    640 x 480 - 215K
    640 x 480 - 208K
    640 x 480 - 188K
    640 x 480 - 192K
  • Bill HenningBill Henning Posts: 6,445
    edited 2014-11-29 10:09
    I just tried this... LOVE IT!

    Really nice work!
    Duane Degn wrote: »
    Attached in the source code used to produce the effects seen in post #1, video.

    I think the "guts" of the algorithm are in the "Mirror" method.
    PUB Mirror(initialColor, finalColor, localPtr, position) | localIndex, scratchBuffer[HALF_RING]
    '' Fill long buffer at "localPtr" with a mirrored colors.
    
    
      repeat while position > MAX_RING_INDEX
        position -= LEDS_IN_RING
      MergeColors(initialColor, finalColor, @scratchBuffer, HALF_RING)
     
      result := position - 1
      repeat localIndex from 0 to MAX_HALF_INDEX
        if result < 0
          result += LEDS_IN_RING
        if position > MAX_RING_INDEX
          position -= LEDS_IN_RING
                 
        long[localPtr][position++] := scratchBuffer[localIndex]
        long[localPtr][result--] := scratchBuffer[localIndex]  
     
    
    
    

    The above method fills a buffer with colors which transitions from "initialColor" to "finalColor". These transitional colors are then moved to positions in the LED buffer as to produce a mirror image of the pattern on two sides of the ring.

    Here's the "MergeColors" method used by the "Mirror" method to create the transitional colors.
    PUB MergeColors(initialColor, finalColor, distinationPtr, localSize) | tempColor[3], {
        } colorMultiplier, localIndex, initialColors[3], finalColors[3], pseudoIncrements[3]
    '' localSize should include the initialColor but not finalColor.
      
      BustColors(initialColor, @initialColors)
      BustColors(finalColor, @finalColors)
       
      ' find incremental color change
      ' use the "PSEUDO_MULTIPLIER" mulitplier to reduce rounding errors
      ' Note we divide by multiplier prior to assigning color
      ' to expanded pattern buffer.
      repeat result from 0 to 2   
        pseudoIncrements[result] := ((finalColors[result] - initialColors[result])* PSEUDO_MULTIPLIER) / localSize 
      
      colorMultiplier := 1
       
      ' assign initial color
      long[distinationPtr] := initialColor
       
      ' assign between colors
      ' final color not copied here. It will be copied as the
      ' initial color of the next loop
      repeat localSize - 1
        distinationPtr += 4
        repeat result from 0 to 2
          tempColor[result] := initialColors[result] + ((pseudoIncrements[result] * {
                             } colorMultiplier) / PSEUDO_MULTIPLIER)
        ' assign altered color
        long[distinationPtr] := Strip.Color(tempColor[0], tempColor[1], tempColor[2])
        colorMultiplier++
    
    
    

    To use the code with fewer than three rings (or more than three rings), change the constant "RINGS_IN_USE" to the appropriate value.

    It should also be possible to use the code with rings of NeoPixels differing numbers of LEDs in the ring. The constant "LEDS_IN_RING" should be changed to indicate how many LEDs are in the ring.
    LEDS_IN_RING = 16
      RINGS_IN_USE = 3
    
  • charlieCegocharlieCego Posts: 1
    edited 2015-01-10 01:59
    I was trying to check our your code, but the zip file appears corrupt. I couldnt open it with winrar or windows explorer. Any chance you could re-compress and re-upload?

    thnx,
    reza
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-01-10 04:59
    I was trying to check our your code, but the zip file appears corrupt. I couldnt open it with winrar or windows explorer. Any chance you could re-compress and re-upload?

    thnx,
    reza

    I just downloaded it and extracted the files without any trouble. I used the Propeller Tool's "Archive" feature to create the zip file.

    The forum could have been experiencing a temporary glitch. The forum software does some strange things every now and then.

    I've attached the two files in the archive to this post.

    Edit(3/11/15): Warning, the code attached is an old version. There are likely better options available.
    I plan to upload this program or an improved version to my GitHub account
    If there isn't code similar to what is attached here on my on GitHub, send me a message and I'll make and check for any improved versions of the code.
Sign In or Register to comment.