RP2040 using both internal AND external Neopixels?

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
jwinslade
 
Posts: 44
Joined: Fri May 21, 2021 12:00 pm

RP2040 using both internal AND external Neopixels?

Post by jwinslade »

Has anyone successfully used BOTH the single on-board Neopixel AND one or more external Neopixels in an Arduino-type sketch?

I would intuitively think that constructing a second instance of Adafruit_NeoPixel, such as shown below, should work, with the correct pins (in my case, external 12, internal 16) and Neopixel counts, of course.

Code: Select all

Adafruit_NeoPixel strip1(LED_COUNT1, LED_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(LED_COUNT2, LED_PIN2, NEO_GRB + NEO_KHZ800);
It appears that the first-constructed instance will always work, but the second instance will always fail to show any display, no matter which displays (internal or external) are used for which instance.

Has anyone gotten something like this to work?

Any ideas?

TIA.

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

What board are you using? I'll try to replicate/explore if I have it.

Dave

User avatar
jwinslade
 
Posts: 44
Joined: Fri May 21, 2021 12:00 pm

Re: RP2040 using both internal AND external Neopixels?

Post by jwinslade »

dastels wrote: Sun Sep 25, 2022 12:26 pm What board are you using? I'll try to replicate/explore if I have it.
Thanks.

This is the Adafruit Feather RP2040, the one with the USB C connector and the on-board single neopixel.

I do have a work-around (using another board in the project to drive the Neopixel string) but I am curious why it will not work, and if it might be a bug or an oversight in coding. (Or, LOL, me not RTFMing.)

I took a quick look at the source and I get the impression that this might be some kind of a resource fight involving the PIO system. The docs say that it has '8 PIO state machines', so it's probably not a resource exhaustion, but I have not found much in the way of PIO documentation. (Trying to follow the Neopixel code is an exercise in masochism!)

I did try a different approach in programming, and that was putting the constructor for the Neopixel instance inside a function, so it will (assuming standard c/++ conventions) be instantiated on the stack and not globally, thus triggering the destructor (and assuming resource free-up) upon function exit.

This approach will work ONCE, meaning the first function call it will work as expected and blink away just fine. On subsequent function calls it fails. This also supports my hunch of some kind of a resource issue.

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

Interesting. Yes, I see no reason why that code wouldn't work. But, as you say, there's the PIO stuff that makes the RP2040 different than, say, a SAMD51.

I'll ask around.

Dave

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

OK, I just wired an 8 pixel strip to a Feather RP2040, running the following code:

Code: Select all

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// Released under the GPLv3 license to match the rest of the
// Adafruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        12 // On Trinket or Gemma, suggest changing this to 1
#define INTERNAL_PIN 16

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 8// Popular NeoPixel ring size

// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel internal_pixel(1, INTERNAL_PIN, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  internal_pixel.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}

void loop() {
  pixels.clear(); // Set all pixel colors to 'off'
  internal_pixel.clear(); // Set all pixel colors to 'off'

  // The first NeoPixel in a strand is #0, second is 1, all the way up
  // to the count of pixels minus one.
  for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...

    // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
    // Here we're using a moderately bright green color:
    pixels.setPixelColor(i, pixels.Color(0, 150, 0));
    if (i % 2 == 0) {
      internal_pixel.setPixelColor(0, pixels.Color(150, 0, 0));
    } else {
      internal_pixel.clear();
    }
    pixels.show();   // Send the updated pixel colors to the hardware.
    internal_pixel.show();   // Send the updated pixel colors to the hardware.

    delay(DELAYVAL); // Pause before next pass through loop
  }
}
It works fine. with the strip gradually filling and the onboard pixel flashing in sync.

Dave

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

Can you post the entire code you're using that doesn't work as expected?

Dave

User avatar
jwinslade
 
Posts: 44
Joined: Fri May 21, 2021 12:00 pm

Re: RP2040 using both internal AND external Neopixels?

Post by jwinslade »

Let me give your code a try. Thanks. I have a test one set up on a breadboard so it will be easy to try tonight.

I do have a work-around for the main project, however.

User avatar
jwinslade
 
Posts: 44
Joined: Fri May 21, 2021 12:00 pm

Re: RP2040 using both internal AND external Neopixels?

Post by jwinslade »

Mystery solved!

TL;DR version: It was an old Neopixel library version.

War And Peace version:

Your example, adjusted for an external 'strip' of one (and my c coding style, of course) ;-) first behaved like my previous versions, as in one and only one would light.

After playing around for a few minutes, trying to figure out exactly which statement caused things to break, just for giggles, I tried compiling and loading it on the Windows peecee in the home office, as opposed to the Linux machine I usually use. This time it worked as expected! Both the internal and external Neopixels worked.

I then started looking at differences, and it was the library version. Doing a quick update of the Neopixel library fixed it.

This makes sense, since when I did a quick check-out of the code, it appeared that the 2040 section was kind of duct-taped in as an add-on to the legacy Feather code sections.

I'm sure that they had reports (internally or externally) of two Neopixel instances failing, so they fixed it.

Now the strangest one, which does verify what I call a 'resource fight' is this one.

Code: Select all

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel pixels(1, 12, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel internal_pixel(1, 16, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels

void setup()
{
  pinMode(13, OUTPUT);
  pixels.begin();
  internal_pixel.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}

void loop()
{
  digitalWrite(13, LOW);
  pixels.clear();
  pixels.show();
  internal_pixel.clear(); // Set all pixel colors to 'off'
  internal_pixel.show();

  delay(DELAYVAL);

  internal_pixel.setPixelColor(0, internal_pixel.Color(0, 15, 0));
  digitalWrite(13, HIGH);
  internal_pixel.show();   // Send the updated pixel colors to the hardware.

  delay(DELAYVAL); // Pause before next pass through loop
}
This was when I was futzing around trying to figure out exactly things were breaking, removing and inserting various statements.

Note that the color is NOT set on the external Neopixel, nor is show() called on the external after setting the color, but when this code above was run on the old library, it was the EXTERNAL Neopixel that flashed.

Anyway, thanks for the assistance and I'm glad that they corrected the issue.

And, if anyone wants to see an example of some very spooky inline assembler code, check out the Neopixel library! I'm glad I did not have to write (or maintain) that one! ;-)

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

Ah, out of date libs. That'll do it. I regularly check for and install board and (especially) library updates.

Glad to hear of your success.

Dave

User avatar
jwinslade
 
Posts: 44
Joined: Fri May 21, 2021 12:00 pm

Re: RP2040 using both internal AND external Neopixels?

Post by jwinslade »

I admit that I am one who is cautious of 'upgrades', as throughout my career (I'm now retired) I lost count of the times when an 'upgrade' or 'versioning' or a simple code tweak that had been tested in the lab caused something to break, which at best required a roll-back and not-at-best ('trap door' upgrade) caused production downtime.

Lesson learned here. I should first check versions when something does not work as expected.

Anyway, thanks again for the assistance.

User avatar
dastels
 
Posts: 15608
Joined: Tue Oct 20, 2015 3:22 pm

Re: RP2040 using both internal AND external Neopixels?

Post by dastels »

Granted, I've had that happen to me as well.

Dave

Locked
Please be positive and constructive with your questions and comments.

Return to “Feather - Adafruit's lightweight platform”