shutting off ws2812 leds

jruthroffjruthroff Posts: 38
edited 2020-02-14 - 11:53:15 in Customer Projects
HI all, I'm relatively new to the forum after a lengthy absence, and am pretty new to Propeller C.

In the code below, I'm triggering two sets of ws2812's to turn on when a PIR sensor indicates motion, all attached to a Propeller Activity Board WX. This part of the code works fine. What I'm having a problem with is getting the 2812's to shut off after the specified time period has passed. Once they come on, they stay on.

Thanks in advance!

Code is below...
/*
PIR on pin 17 detects motion. When it does, two groups of we2812's turn on. 10 seconds
after the motion ceases, the LED's turn off. 
*/

#include "simpletools.h"                      // Include simpletools library
#include "ws2812.h"                           // Include ws2812 library   

#define LED_PIN1    16                        // Pin and Led Count declarations
#define LED_PIN2    15
#define LED_COUNT1  4
#define LED_COUNT2  4

ws2812 *leds;                                 //set up ws2812 instance  

 int lightsA[] = {COLOR_GREEN, COLOR_GREEN};
 int lightsB[] = {COLOR_RED, COLOR_RED, COLOR_RED, COLOR_RED};

state = 0;

int main()
{
  while(1)                                            // Main loop   
 
    {  
    int state = input(17);                            // Check sensor (1) motion, (0) no motion
    print("%c state = %d%c\n",                        // Display sensor
    HOME, state, CLREOL);
    pause(200);                                       // Pause 1/5 second before repeat
    
    if(state == 1)                                   // If sensor detects motion
                                                      // turn on leds 
   {
   leds = ws2812b_open();
  
   {
     ws2812_set(leds, LED_PIN1, lightsA, LED_COUNT1);  // Starts group 1 leds
     ws2812_set(leds, LED_PIN2, lightsB, LED_COUNT2);  // Starts group 2 leds
   }               
   pause (10000);                                      // Pause 10 seconds 
   void ws2812b_close(leds);                           // Shut off leds
   }   
  }
}




Comments

  • Mike GreenMike Green Posts: 22,998
    edited 2020-02-14 - 11:53:44
    The ws2812b_close function doesn't change the color of the leds. It just closes the communications channel to the leds. You have to turn off the leds by sending them a COLOR_BLACK (or zero), then close the channel. You'd add:
    int lightsAoff[] = {COLOR_BLACK, COLOR_BLACK };
    int lightsBoff[] = {COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK };
    

    then do:
    ws2812_set(leds, LED_PIN1, lightsAoff, LED_COUNT1); // Turns group 1 leds off
    ws2812_set(leds, LED_PIN2, lightsBoff, LED_COUNT2); // Turns group 2 leds off
    

    wait a little, then you can close the channel.
  • Thanks Mike, that did the trick!

    Does turning off the leds by sending a COLOR_BLACK reduce the power consumption any more/less than sending COLOR_BLACK and closing the channel? I'm really power challenged on this project and anything I can do to stretch the battery life would be helpful.

    John
  • Duane DegnDuane Degn Posts: 10,096
    edited 2020-02-13 - 22:42:42
    jruthroff wrote: »
    Thanks Mike, that did the trick!

    Does turning off the leds by sending a COLOR_BLACK reduce the power consumption any more/less than sending COLOR_BLACK and closing the channel? I'm really power challenged on this project and anything I can do to stretch the battery life would be helpful.

    John

    The chip controlling the LED colors doesn't have an "off" command. They'll continue to monitor the input line for a signal.

    I just tested a group of four WS2812B LEDs. When set to black these four LEDs combined draw 6mA of current.

    If the idle current draw is high enough to worry about, you could add a latching relay to control the 5V power of the LEDs. Depending on how often this relay is used, it could save a small about of power.
  • Thanks for researching it. I can live with a current draw that low.

    Cheers,

    John
  • jruthroffjruthroff Posts: 38
    edited 2020-02-15 - 05:33:12
    This project has taken an interesting, and unwelcome, turn.

    When powered up, it works just as I hoped. When the ping (I replaced the PIR with a Ping as the PIR was too slow to respond) detects something within 150cm, it turns the leds on for the designated period of time, then turns them off. Ping starts pinging again, and the cycle repeats (as desired). After a few minutes though, the ping stops pinging. The light on the ping stops blinking, and everything comes to a halt. Pressing the reset button on the board (a Propeller Activity WX) gets everything running again, but then the cycle repeats and it all comes to a stop. I would think there is something in the code that is causing this, but if that's the case I can't see it. Any ideas? Code is below...

    Thanks to all,

    John
    /*
    Ping on pin 17 detects motion. When it does, two groups of we2812's turn on. x seconds
    after the motion ceases, the LED's turn off.
    */
    
    #include "simpletools.h"                            // Include simpletools library
    #include "ws2812.h"                                 // Include ws2812 library
    #include "ping.h"                                   // Include ping library
    
    #define LED_PIN1 12                                 // Pin and Led Count declarations
    #define LED_PIN2 15
    #define LED_COUNT1 4
    #define LED_COUNT2 4
    
    ws2812 *leds;                                       //set up ws2812 instance
    
    int lightsA[] = {COLOR_GREEN, COLOR_GREEN};
    int lightsB[] = {COLOR_RED, COLOR_RED, COLOR_RED, COLOR_RED};
    int lightsAoff[] = {COLOR_BLACK, COLOR_BLACK };
    int lightsBoff[] = {COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK };
    
    int main()
    {  
    while(1)                                             // Main loop
    
    {
    int cmDist = ping_cm(17);                            // Check sensor distance
    print("cmDist =%d\n",cmDist);                        // Display distance
    pause(200);                                          // Pause 1/5 second before repeat
    
    if(cmDist <150)                                      // If sensor detects object within 150cm
                                                         // turn on leds
    {
    leds = ws2812b_open();
    
    {
    ws2812_set(leds, LED_PIN1, lightsA, LED_COUNT1);     // Starts group 1 leds
    ws2812_set(leds, LED_PIN2, lightsB, LED_COUNT2);     // Starts group 2 leds
    }
    pause (10000);                                       // Pause x seconds
      
    ws2812_set(leds, LED_PIN1, lightsAoff, LED_COUNT1);  // Turns group 1 leds off
    ws2812_set(leds, LED_PIN2, lightsBoff, LED_COUNT2);  // Turns group 2 leds off
    
    pause (1000);
    
    void ws2812_close(leds);                             // Shut off leds
    }
    }
    }
    
  • @jruthroff
    Curious, how are your LEDs wired?
  • I haven't used WS2812 LEDs with C but my here is what I'd try.

    Move the "leds = ws2812b_open();" statement to before the line "while(1) // Main loop".
    This way it's only called once.
    Remove the "void ws2812_close(leds); "

    I think the above would likely solve the problem.

    If you really want to use "open" and "close" each time you light the LEDs I think you need to change the way you use the close function. As written, the line "void ws2812_close(leds);" doesn't call the function. I forget the name of this sort of statement but I'm pretty sure it doesn't do what you think it does. To call the close function, you'd use "ws2812_close(leds);". Beginning the line with "void" changes it from a function call to something else.

    As your code is presently written, it runs out of cogs since the cog is never stopped properly.
  • AK, there are two "banks", on consisting of two leds, and the other consisting of four. Each bank has its own trigger pin (since this is a temporary project, I'm using a PAB WX and just plugging into the headers).

    Concerning how the the leds are physically attached to each other, they have very short soldered wire connections and are in serial (which I believe is the only way they can be wired).

    Thanks,

    John
  • Good catch Duane. Testing now, but that seems to have squared things away.

    So for learning purposes, since I was calling "leds=ws2812b_open();" each time the program would loop, I was opening a new cog with each triggering event but never closing the cog, so after eight triggers I ran out of cogs. Is that about right?

    In any case, thanks!

    John
  • jruthroff wrote: »
    since I was calling "leds=ws2812b_open();" each time the program would loop, I was opening a new cog with each triggering event but never closing the cog, so after eight triggers I ran out of cogs. Is that about right?
    I think that's what was happening. I haven't used those functions myself.
    I'm glad things are working now.
  • Thanks much!
Sign In or Register to comment.