0

Multi-tasking different regions of a neopixel strip
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 07, 2019 9:38 am

I'm just learning about using the class and update method to effectively multitask different led strips on unique pin assignments. Is there a way to multitask half of a neopixel strip to do one thing like blink steady while the other half does a knight rider fill?

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 07, 2019 4:12 pm

Yes! I've written a library that does exactly that. But no one ever seems to understand the code I write.

Basically its two classes

first class is a neoPixel group. Lets say its a 12 pixel ring, or a 8 pixel strip. In these group classes you program as if they are the only pixels on the pin.

second class is a list of groups. Here you add instances for the first class in the order they are wired. You can even add multiples of the same class. (Very handy for adding things like led rings on the 4 arms of quadcopters)

Now all your sections run independently of each other. Well it looks to the humans as independent. And your coding as if it was. In reality is still just one long string.

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by adafruit_support_bill on Mon Jan 07, 2019 4:30 pm

I haven't seen Jim's code, but what he describes sounds like a good way to approach it. On the one hand, you have a class to represent one or more physical strips, rings, sticks etc. that each need to be addressed serially. And then you have class to define one or more logical groups of pixels that you want to map onto the physical groups.

adafruit_support_bill
 
Posts: 73210
Joined: Sat Feb 07, 2009 10:11 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 07, 2019 4:31 pm

Woud you like to see it?

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 07, 2019 4:45 pm

Yes, I would like to see it. Navigating a library might be another new learning task for me, but I'll explore it if I need to. Based on this learning article, https://learn.adafruit.com/multi-tasking-the-arduino-part-3/overview, I was thinking I could pull this off from within my Arduino IDE sketch.

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 07, 2019 6:47 pm

OK..The finished product.

Image
Link : https://www.thingiverse.com/thing:2225515

This is code for my pair of goggles with neoPixel rings built into them. The version I'm posting has a rasta-ring circling around each one.

Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

#include <blinker.h>
#include <colorObj.h>
#include <idlers.h>
#include <lists.h>
#include <mapper.h>
#include <multiMap.h>
#include <PulseOut.h>
#include <runningAvg.h>
#include <servo.h>
#include <timeObj.h>

#include <chainPixels.h>
#include <neoPixel.h>

#include "theRings.h"

chainPixels theRings(3);
starLight ring1;
portLight ring2;


void setup() {

  setUpPattern();             // First is to set up the pattern we want.
  theRings.addGroup(&ring1);
  theRings.addGroup(&ring2);
  theRings.hookup();
}


void setUpPattern(void) {

  colorObj      aColor;

  aColor.setColor(&white);
  theColors.addColor(0,&aColor);

  aColor.setColor(&red);
  theColors.addColor(1,&aColor);

  aColor.setColor(&red);
  aColor.blend(&black,80);
  theColors.addColor(3,&aColor);

  aColor.setColor(&green);
  aColor.blend(&black,80);
  theColors.addColor(4,&aColor);

  aColor.setColor(&black);
  theColors.addColor(9,&aColor);
}


void loop() { idle(); }


This shows you how it works. Basically I create two ring classes port and starboard. then add them to the chain pixel class. Then my loop() only consists of the one call idle();

Here are the two ring classes..

The .h file..
Code: Select all | TOGGLE FULL SIZE
include <timeObj.h>
#include <chainPixels.h>


#define FRAME_MS  60

extern colorMultiMap theColors;

class starLight : public pixelGroup,
                  public timeObj {

  public :
                starLight(void);
               
          void  setupColors(void);
  virtual void  draw(void);
 
          bool  init;
};


class portLight : public pixelGroup,
                  public timeObj {

    public :
                portLight(void);
               
          void  setupColors(void);     
  virtual void  draw(void);
 
          bool  init;
};



And the .cpp file.
Code: Select all | TOGGLE FULL SIZE
#include "theRings.h"

colorMultiMap theColors;

starLight::starLight(void)
  : pixelGroup(16),
  timeObj(FRAME_MS) {

  init = false;
  start();
}


void starLight::setupColors(void) {

  colorObj      aColor;
 
  for (int i=0;i<16;i++) {
    aColor = theColors.Map(i);
    setPixelColor(i,&aColor);
  }
}


void starLight::draw(void) {

  if (!init) {
    setupColors();
    init = true;
  }
  if (ding()) {
    start();
    roll(true);
  }
}



portLight::portLight(void)
  : pixelGroup(16),
  timeObj(FRAME_MS) {
   
  init = false;
  start();
}


void portLight::setupColors(void) {

  colorObj      aColor;

  for (int i=0;i<16;i++) {
    aColor = theColors.Map(i);
    setPixelColor(15-i,&aColor);
  }
}


void portLight::draw(void) {

  if (!init) {
    setupColors();
    init = true;
  }
  if (ding()) {
    start();
    roll(false);
  }
}


If you want to try using this, you're going to have to grab ... Hmm.. two folders off my github to support this environment.

https://github.com/leftCoast/Arduino/tree/master/libraries <- This is my libraries folder.

Look for..

LC_baseTools <- The basic toolkit all my stuff relies on. You'll need this.
LC_NeoPixel <- My neopixel library. My simplified neoPixel interface, chain pixels and what have you. This uses coloObj to do the color stuff. That comes in LC_baseTools it makes doing custom color stuff a LOT easier.

NOTE: The version of the neoPixel library you see there only works for the original RGB neoPixels. It needs a hack to run with the RGBW version.

Gool luck, let me know if you can get this working.

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 07, 2019 11:22 pm

I tried it as best as I could, I really am a light year behind you, so it might take some time to catch up.
I downloaded all of those .h, .cpp, and .ino files to my ../Arduino/libraries directory and then opened goggle_lights.ino and ran verify.

Here are just the first few lines of the error messages:

Arduino: 1.8.8 (Windows Store 1.8.19.0) (Windows 10), Board: "Adafruit Trinket M0"
theRings.cpp:31:3: error: stray '\302' in program
<title>Arduino/theRings.cpp at master · leftCoast/Arduino · GitHub</title>
^
theRings.cpp:31:3: error: stray '\267' in program
theRings.cpp:31:3: error: stray '\302' in program
theRings.cpp:31:3: error: stray '\267' in program
theRings.cpp:244:5: error: missing terminating ' character

Wouldn't the Adafruit_NeoPixel.h library be sufficient for me to define a class and 2 classes within that class as you have described? And then be able to execute the 2 animations on one strip simultaneously?

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 07, 2019 11:25 pm

*Define the class and 2 subclasses in my .ino file that is?

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Tue Jan 08, 2019 1:59 am

Wait a second, you only needed to d-load the two folders I said, Not the Arduino entire library folder.

LC_BaseTools & LC_NeoPixels

There is a TON of stuff in that github repository you don't want cluttering up your life.

Did you only grab those two? Or possible are you now swimming in source code files?

Something really odd going on here. theRings.cpp is only 70 lines long. You're getting errors on line 200 and some? Can you copy paste that file to the forum here?

thanks

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 14, 2019 1:36 am

Interim problem found--the contents of the files I downloaded are html.

I usually get email alerts for a post update, guess I missed this one.
Reasonably certain I have only downloaded the two specified folders.
BUT it looks like right click, save file as, doesn't work in github (I'm using Chrome browser)--the contents of therings.cpp looks to be html--probably all the others have the same affliction. (May also be why the forum wouldn't let me upload that particular 'file')
I'll try it again in the morning, but if you have a streamlined github download trick for me, I'll be sure to use it. Meanwhile, I'll be copying the code lines and pasting in to the applicable files on my local machine. #poop

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 14, 2019 2:34 am

Ok, lets try this..

https://github.com/leftCoast/BykeCommuter

There should be a big green button for downloading.

Sorry, I never have been able to understand the thinking behind most of github.

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 14, 2019 12:48 pm

Success! Thanks for all your time on this. I now have 32 pixels running a white-red-green pattern on pin 3 of my Trinket M0. (running the goggle_lights.ino (with only one character modification).

Couple questions going forward.
1. Where do I change the pin assignment(s)?
2. Where is the pattern defined (aka where is it called from within the .ino)?

Thanks for taking so many rudimentary questions,
Randy

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 14, 2019 1:14 pm

When you create the pixel chain, its only parameter is the pin#.

When you create your groups you specify how many LEDs in each group.

The .h file is where you can look see how to create them and what kind of goodies they have for you.
Code: Select all | TOGGLE FULL SIZE
#ifndef chainPixels_h
#define chainPixels_h

#include <colorObj.h>
#include <neoPixel.h>
#include <idlers.h>
#include <lists.h>

// If you have separate pixel groups that want to act independently but
// are wired in daisy chain fashion. This is beyond handy.
//
// You program each pixelGroup as if it was the only thing on the chain.
// Then, you add all the pixelGroup objects to the global pixelGroup in
// the order that they were wired. All of the addresses are delt with in
// the background automatically.
//
// For example I did a Quad copter that had a taillight that reflected
// how the machine was being flown. Power settings, forward, reverse, left
// right. And a couple of floodlights in front. All neoPixle groups wired
// up on one daisy chain data line.
//
// ON another quadcopter each arm had a glowing ring of lights. So we just
// added an instance of the same object four times.

class pixelGroup;


class chainPixels : public queue, public idler {
 
  public:
            chainPixels(byte inPin);
   virtual   ~chainPixels(void);
             
            void      resetChain(void);
   virtual  void      push(linkListObj* item);
   virtual  void      pop(void);
            void      addGroup(pixelGroup* inGroup);
   virtual  void      idle(void);
            colorObj   getPixelColor(word index);
            void      setPixelColor(word index,colorObj* inColor);
             
  protected:
 
             byte         pin;
             word         numPixels;
             neoPixel*   pixelDriver;
             boolean      dirtyBit;
};


class pixelGroup : public linkListObj {

   public:
            pixelGroup(word inNumPixels);
   virtual   ~pixelGroup(void);
           
            void      setIndex(word inIndex);
            void      setChain(chainPixels* inChain);
            word      getNumPixels(void);
             
            colorObj   getPixelColor(word pixelNum);                     // What color is THIS pixel now?
            void      setPixelColor(word pixelNum, colorObj* color);   // Set THIS pixel this color.
            void      setPixels(colorObj* color);                     // Set ALL our pixles this color.
            colorObj   shiftPixels(bool toEnd=true);                     // Even handier!
            void      roll(bool clockwise=true);
   virtual   void      draw(void);                                       // This will be called repeatedly.
   
   protected:
            chainPixels*   ourChain;
            word            numPixels;
            word            index;
};

#endif


Hope this helps!

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Re: Multi-tasking different regions of a neopixel strip

by BykeCommuter on Mon Jan 14, 2019 4:58 pm

Yes, I'm beginning to unpack this in my mind.
The goggle.ino:
1. sets up "SetupPattern()" as a subroutine in the ino
2. Names two pixel regions, &ring1 and &ring2 using a command "addGroup" which is defined in chainPixels.h
2a. This line also takes the argument prefix "theRings." which sets up a color map for 16 pixels within theRings.cpp
3. QUESTION: so if I added theRings.addGroup(&ring3); , I would get a 3rd region of 16 pixels ie. the next 16 in a chain of neopixels wired end to end? Not specifically numbered, just the next available? Convenient if so, I have two strips of 48 pixels each on pins 3 and 4 currently.
4. chainPixels theRings(3); //this line is where chainPixels.h is invoked to define the pixels as on pin 3--not sure what the "theRings" prefix does.
I did see the readme file and I am part way through that. However, I changed (3) to (4) and nothing happened. Maybe I need to double check my hookup or my logic of the pin assigment is off.
Will have to finish tomorrow morning, God willing, I've got to rest and pack a lunch before running off to a swing shift that runs past midnight.

BykeCommuter
 
Posts: 30
Joined: Tue Sep 06, 2016 9:46 am

Re: Multi-tasking different regions of a neopixel strip

by jim_lee on Mon Jan 14, 2019 9:46 pm

Ok, you're getting it. This is going to take some explaining so here's a bit you can chew on next time you're through here looking.

QUESTION: so if I added theRings.addGroup(&ring3); , I would get a 3rd region of 16 pixels ie. the next 16 in a chain of neopixels wired end to end? YES! You got that bit correctly!

In c++ you inherit general purpose classes, add your own twist to them to make custom things (classes).

A "class" is just the template for a type of object. An object is almost like a tiny subprogram of its own. When I added the two rings to the chain pixel thing, I added objects, not classes. The .h & .cpp files describe how they work and how to run them. Its the objects you create that actually do these fun things.

I gave you pixelGroup as a general purpose class. pixelGroup doesn't actually draw anything. BUT, it knows all about the chainPixels class. Them two are partners. Everything about how to add to the list, addressing lights etc. Is handled by them behind the scenes.

In my example I made (2) derived classes. starLight & portLight each "inherited" pixelGroup or in other words were derived from pixelGroup.

Ok, you need to write a class for each type of pattern you want to show. This is now a lot easier because, white writing it, you don't have to worry about anything else. Other patterns, timing addressing what have you. Each of your pattern class's will have its own draw() method you fill out to do your drawing. In your setup() function, or maybe even before, you will create new objects from your classes and add these objects to your chiainPixel objects. If you only want one pattern three times, you only need to write one class and use that class to create three objects to add to your chainPixel object.

A lot to chew on? Here's something different..

In the example setup() method what's going on is I am creating colors and adding them into a multi color mapper.

Color mapper? Color mappers allow you to order colors by number. Any number. For example you want a temp gauge that shows color with temp. 0C - 100C is good. So you add 0,green 100,green. Now say 100C-120C, not so good but ok.. add 105,yellow, 120,yellow anything over 150C is overheating 150,red.

Then you can pop in a number and it will give back a color. If the number is between 0->100 you get green 105-120 yellow 150+ red. Between these say.. 135? You'll get something like orange. Color mappers blend between set points. Want a line of pixels that fade to black? Start a mapper at one end of your color and the other at black.

Color multi mappers? You add as many color as you want at whatever value you want. The as you map values into it a veritable rainbow come out.

Enough for now. You can chew on that for a bit.

-jim lee

jim_lee
 
Posts: 506
Joined: Thu May 24, 2012 8:24 pm

Please be positive and constructive with your questions and comments.