Shop OBEX P1 Docs P2 Docs Learn Events
C code to work with WS2812 NeoPixel LEDs - Page 2 — Parallax Forums

C code to work with WS2812 NeoPixel LEDs

245

Comments

  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-09-25 18:29
    I'm going to assume "mak e" was a typo.

    I've seen this a number of times and can't remember why. Is spin2cpp.exe in that directory? That's mostly a rhetorical question since I see it in my copy of the zip. I'm out of ideas at this point :(

    I'll give this a try on my virtual machine with PropWare installed. It's a bit overkill to install PropWare just for this, but it automates the installation process so it'd be hard to forget something.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-09-25 18:46
    Not sure why, but the version of spin2cpp that was included in my Windows release of PropGCC was broken. I'm uploading a new package now with a working copy. In the meantime, simply replace spin2cpp.exe with a copy downloaded directly from the author: https://code.google.com/p/spin2cpp/downloads/detail?name=spin2cpp_v105.zip&can=2&q=
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-25 19:11
    OK. That seemed to work. Now how doI open in SimpleIDE? Do I just create a new project or what?
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-09-25 19:15
    The most help I can be is pointing you at this thread:
    http://forums.parallax.com/showthread.php/157409-How-to-start-with-SimpleIDE

    Don't worry... you're not the only one with that question lol
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-25 19:58
    Not sure why, but the version of spin2cpp that was included in my Windows release of PropGCC was broken. I'm uploading a new package now with a working copy. In the meantime, simply replace spin2cpp.exe with a copy downloaded directly from the author: https://code.google.com/p/spin2cpp/downloads/detail?name=spin2cpp_v105.zip&can=2&q=
    It could be that spin2cpp isn't included in the version of propgcc that is distributed with SimpleIDE. The trouble is, the version of propgcc that SimpleIDE uses now is rather old. When I get back home I'll update my code to use OpenSpin instead. I'm sure that is included in SimpleIDE. Sorry about the trouble.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-25 21:53
    I have already made all the changes so I hope my SimpleIDE still works correctly. I am however having issues compiling the code.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-26 03:35
    NWCCTV wrote: »
    I have already made all the changes so I hope my SimpleIDE still works correctly. I am however having issues compiling the code.
    What sort of issues?
  • ersmithersmith Posts: 6,053
    edited 2014-09-26 05:50
    Not sure why, but the version of spin2cpp that was included in my Windows release of PropGCC was broken. I'm uploading a new package now with a working copy. In the meantime, simply replace spin2cpp.exe with a copy downloaded directly from the author: https://code.google.com/p/spin2cpp/downloads/detail?name=spin2cpp_v105.zip&can=2&q=

    Actually the latest version of spin2cpp is on github, and I recommend using that one:

    https://github.com/totalspectrum/spin2cpp/releases/download/v1.91/spin2cpp_v1.91.zip

    Thanks,
    Eric
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-26 06:05
    ersmith wrote: »
    Actually the latest version of spin2cpp is on github, and I recommend using that one:

    https://github.com/totalspectrum/spin2cpp/releases/download/v1.91/spin2cpp_v1.91.zip

    Thanks,
    Eric
    I guess I should remove the copy from propgcc then. I think we're now using OpenSpin for assembling PASM code now anyway.

    Edit: I meant to say maybe we should remove the code for spin2cpp from the propgcc repository and just get it from its official location on github like we do for OpenSpin. I didn't mean we should leave spin2cpp out of the propgcc distributions.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-27 18:24
    David Betz wrote: »
    You have to create a command window and run the command line tools. However, maybe instead I should just make a SimpleIDE project for this. I can try making the project tonight but I don't have any WS2812 LEDs with me at the moment so I don't be able to verify it until I get home on Friday night.
    I've just attached a Simple Library of this code for use with SimpleIDE to the top post of this thread. I've tested it using an AdaFruit 16 LED ring attached to pin 15 of a PropBOE. It should also work with an ActivityBoard if you connect the ring to pin 15. This is a fairly straight forward translation of JonnyMac's Spin code to C++. In order to use this library I believe all you have to do is copy it into your SimpleIDE workspace under Learn/Simple Libraries/My Libraries. The test program in libws2812.c is the program I used for my Christmas ornament last year. Let me know if you have any problems with this or have any suggestions for improvement.

    Thanks,
    David
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-27 19:53
    Works great! So, How would I implement a continuous loop?
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-27 20:14
    NWCCTV wrote: »
    Works great! So, How would I implement a continuous loop?
    All of the smarts is in JonnyMac's PASM code. The ws2812_init function starts a COG running JonnyMac's code and tells it to update the LEDs connected to the specified pin based on the colors in an array of longs that is passed to it. So, in the example, the address of the array "colors" is registered with the PASM COG and the LEDs are automatically updated to match the RGB color values in that array. So, you can get any animation effect you want just by changing the values in that array. The rest of the functions in the library make use of this to achieve various effects. JonnyMac can better describe what these functions do since they match what his Spin functions do. Alternatively, you can just call ws2812_init and then modify the "colors" array yourself to get whatever effect you want. If you want to just light a single LED at a time and loop continuously you can use something like this:
    #define MY_COLOR COLOR(255, 0, 0) // red
    #define MY_PAUSE 1000 // one second
    
    int i = 0;
    
    while (1) {
        colors[i] = COLOR(0, 0, 0);
        if (++i >= LED_COUNT)
            i = 0;
        colors[i] = MY_COLOR;
        ws2812_pause(MY_PAUSE);
    }
    

    Put this code after the call to ws2812_init and you should get a looping red LED.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 04:11
    I'd like to suggest one simple modification to the ws2812 driver code. Instead of passing the address of an array of RGB longs, why not pass the address of a pointer to an array of RGB longs. That way you can switch arrays by storing a single pointer rather than looping through the entire array changing values. This could allow double buffering. If no one can see a reason not to do this, I think I'll make that change and repost the library code.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 07:44
    I get an error when I do this:
    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 6
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog;
    ws2812_clock_init();
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    #define MY_COLOR COLOR(255, 0, 0) // red
    #define MY_PAUSE 1000 // one second
    
    
    int i = 0;
    
    
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    ws2812_pause(MY_PAUSE);
    }
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 08:47
    NWCCTV wrote: »
    I get an error when I do this:
    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 6
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog;
    ws2812_clock_init();
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    #define MY_COLOR COLOR(255, 0, 0) // red
    #define MY_PAUSE 1000 // one second
    
    
    int i = 0;
    
    
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    ws2812_pause(MY_PAUSE);
    }
    
    What error?
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 08:50
    Maybe you're getting an error because main doesn't return a value? Try this:
    #include <stdint.h>
    #include <propeller.h>
    #include "ws2812.h"
    
    #define LED_PIN 15
    #define LED_COUNT 6
    #define MY_COLOR COLOR(255, 0, 0) // red
    #define MY_PAUSE 1000 // one second
    
    int main(void)
    {
        uint32_t colors[LED_COUNT];
        int cog, i;
    
        ws2812_clock_init();
    
        memset(colors, 0, sizeof(colors));
        if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
            return 1;
    
        i = 0;
        while (1) {
            colors[i] = COLOR(0, 0, 0);
            if (++i >= LED_COUNT)
                i = 0;
            colors[i] = MY_COLOR;
            ws2812_pause(MY_PAUSE);
        }
    
        cogstop(cog);
    
        return 0;
    }
    
    Actually, after taking some time to reformat your code, I see you're missing the final brace. That will certainly cause a compilation error.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 10:44
    That worked!!!! So, how would I add the remaining 6 colors?
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 10:54
    Is 255,0,0 suppose to be red? Mine comes up green.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 11:37
    NWCCTV wrote: »
    Is 255,0,0 suppose to be red? Mine comes up green.
    What LEDs are you using? Yes, COLOR(255, 0, 0) should be red since the arguments to the COLOR macro are red, green, and blue in that order.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 11:48
    NWCCTV wrote: »
    That worked!!!! So, how would I add the remaining 6 colors?
    You just have to put values in the other elements of the "colors" array. colors[0] is the RGB color of the first LED, colors[1] is the color of the second and so on. You can get any animiation effect you want by change the values in the colors[] array at the right times.

    Also, the ws2812_clock_init() and ws2812_pause() functions probably aren't needed as I'm pretty sure there is already some pause or delay function in Simple Libraries. I need to look it up.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-28 12:03
    My single-shot version has an execute() method that allows you to pass a pin # and array (via pointer) to use.

    My latest code (auto and single-shot) is available in ObEx (updated 28 SEP 14)
    -- http://obex.parallax.com/object/703

    Reminder: My code is Spin/PASM -- will need translating for those using C.

    David Betz wrote: »
    I'd like to suggest one simple modification to the ws2812 driver code. Instead of passing the address of an array of RGB longs, why not pass the address of a pointer to an array of RGB longs. That way you can switch arrays by storing a single pointer rather than looping through the entire array changing values. This could allow double buffering. If no one can see a reason not to do this, I think I'll make that change and repost the library code.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 12:41
    JonnyMac wrote: »
    My single-shot version has an execute() method that allows you to pass a pin # and array (via pointer) to use.

    My latest code (auto and single-shot) is available in ObEx (updated 28 SEP 14)
    -- http://obex.parallax.com/object/703

    Reminder: My code is Spin/PASM -- will need translating for those using C.
    What do you mean by "single shot"? How does it differ from your original version.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 13:53
    What LEDs are you using?
    http://www.pololu.com/product/2536

    EDIT: Any reason my color codes would be wrong? I get red with 255.0,255.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 13:56
    NWCCTV wrote: »
    http://www.pololu.com/product/2536

    EDIT: Any reason my color codes would be wrong? I get red with 255.0,255.
    Those are using ws2811 chips instead of ws2812. Not sure what the difference is but that might account for the different color mapping.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 14:15
    NWCCTV wrote: »
    Is 255,0,0 suppose to be red? Mine comes up green.
    It looks like the ws2811 uses GRB and the ws2812 uses RGB color values. To support this you'll have to swap the first two arguments to the COLOR macro for your LEDs.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 14:16
    OK. I can live with modifying the colors. However, I am confused as to how to add another color. I tried the following with no luck. It just changes the LED from Red to Green.
    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 3
    #define MY_COLOR COLOR(0,255, 0) // red
    #define MY_COLOR2 COLOR(255,0,0)
    
    
    #define MY_PAUSE 1000 // one second
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog, i;
    
    
    ws2812_clock_init();
    
    
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    
    
    i = 0;
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    colors[i] = MY_COLOR2;
    ws2812_pause(MY_PAUSE);
    }
    
    
    cogstop(cog);
    
    
    return 0;
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 14:20
    NWCCTV wrote: »
    OK. I can live with modifying the colors. However, I am confused as to how to add another color. I tried the following with no luck. It just changes the LED from Red to Green.
    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 3
    #define MY_COLOR COLOR(0,255, 0) // red
    #define MY_COLOR2 COLOR(255,0,0)
    
    
    #define MY_PAUSE 1000 // one second
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog, i;
    
    
    ws2812_clock_init();
    
    
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    
    
    i = 0;
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    colors[i] = MY_COLOR2;
    ws2812_pause(MY_PAUSE);
    }
    
    
    cogstop(cog);
    
    
    return 0;
    
    That code just overwrites the first color with the second. If you want to see them both then you'll heed to add a call to ws2812_pause between them.
  • pmrobertpmrobert Posts: 673
    edited 2014-09-28 14:28
    The intensity of each color is defined by a number 0-255 - an unsigned char in C. (255,0,0) would give full intensity red and no green or blue. (64,64,64) would give a 25% intensity white. (64,64,0) gives you a 25% intensity yellow. (0,0,128) gives you a 50% intensity blue. Play with the R,G and B numbers at http://www.colorpicker.com/ to get a realtime feel on your monitor of how this works.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-09-28 14:45
    Like this? If this is correct, then my color scheme is way off!!! I get a light blue for my second color.

    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 3
    #define MY_COLOR COLOR(0,255, 0) // red
    #define MY_COLOR2 COLOR(255,0, 255) 
    
    
    #define MY_PAUSE 1000 // one second
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog, i;
    
    
    ws2812_clock_init();
    
    
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    
    
    i = 0;
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    ws2812_pause(MY_PAUSE);
    colors[i] = MY_COLOR2;
    ws2812_pause(MY_PAUSE);
    }
    
    
    cogstop(cog);
    
    
    return 0;
    }
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-09-28 14:53
    NWCCTV wrote: »
    Like this? If this is correct, then my color scheme is way off!!! I get a light blue for my second color.

    #include <stdint.h>#include <propeller.h>
    #include "ws2812.h"
    
    
    #define LED_PIN 15
    #define LED_COUNT 3
    #define MY_COLOR COLOR(0,255, 0) // red
    #define MY_COLOR2 COLOR(255,0, 255) 
    
    
    #define MY_PAUSE 1000 // one second
    
    
    int main(void)
    {
    uint32_t colors[LED_COUNT];
    int cog, i;
    
    
    ws2812_clock_init();
    
    
    memset(colors, 0, sizeof(colors));
    if ((cog = ws2812_init(LED_PIN, colors, LED_COUNT)) < 0)
    return 1;
    
    
    i = 0;
    while (1) {
    colors[i] = COLOR(0, 0, 0);
    if (++i >= LED_COUNT)
    i = 0;
    colors[i] = MY_COLOR;
    ws2812_pause(MY_PAUSE);
    colors[i] = MY_COLOR2;
    ws2812_pause(MY_PAUSE);
    }
    
    
    cogstop(cog);
    
    
    return 0;
    }
    
    You're specifying full intensity of green and full intensity of blue which I suppose gives you a bright blue-green. Try it with the color picker pmrobert posted the link to in message #59. It looks like light blue as you reported.
Sign In or Register to comment.