Using Feather S2 RGB LED

I'm using a Feather S2 controller in my project. It is battery powered, I do have a switch to turn the battery on and off, it's a push on, push off switch, at times I wasn't sure if the battery was on. I'm using the Arduino IDE for my project.

How can I turn the on board RGB LED on to indicate the power is on? Would just need to be one color and energized in the setup function.

Thanks
John

In "C++" or micropython?
All I see is via micropython

And then, depending, it might be a neopixel (WSxxxx) or an APA102.
Is there a schematic noting which "IO" it's associated with?
Maybe it's IO13
https://feathers2.io/
If it's for C++, supposing you need the neopixel library and use IO13 ?

Pinouts | Adafruit ESP32-S2 Feather | Adafruit Learning System says 13 is the red LED and 33 is the NeoPixel:

There are two LEDs you can control in code.

  • NeoPixel LED - This addressable RGB NeoPixel LED, labeled Neo on the board, works both as a status LED (in CircuitPython and the bootloader), and can be controlled with code. It is available in CircuitPython as board.NEOPIXEL, and in Arduino as PIN_NEOPIXEL.
  • There is a NeoPixel power pin that needs to be pulled high for the NeoPixel to work. This is done automatically by CircuitPython and Arduino. It is available in CircuitPython and Arduino as NEOPIXEL_POWER.

If you run into NeoPixel power issues on Arduino, ensure you are using the latest Espressif board support package. If you are still having issues, you may need to manually pull the pin high in your code.

  • Red LED - This little red LED, labeled #13 on the board, is on or blinks during certain operations (such as pulsing when in the bootloader), and is controllable in code. It is available in CircuitPython as board.LED, and in Arduino as LED_BUILTIN or 13.

I tried loading the the Blink sketch prior to posting my question, but got the error that LED_BUILTIN wasn't defined. After your comments a defined a LED as pin 13 and changed the references to LED_BUILTIN to LED, it now complied and loaded but the LED doesn't blink.

I then installed the NeoPixel library and looked at the examples but those are for external RGB strips connected to a pin. I added the NeoPixel library to the modified blink with the LED defined as pin 13 and 33, still no blink.

Whose S2 have you got? Manufacturers vary.
Modified blink and all that - care to post? Curious.

It's a Adafruit Feather S2, Here's the modified sketch.

/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

#define redLED 13

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(redLED, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(redLED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(redLED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

Thanks for your help

I was more interested in seeing the 'neopixel' implementation.
( The library include will have no effect this way. )

1 Like

I didn't think it would but gave it a shot. If you just wanted to see the NeoPixel library implemented here's one of the examples called RGBWstrandtest

// NeoPixel test program showing use of the WHITE channel for RGBW
// pixels only (won't look correct on regular RGB NeoPixel strips).

#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?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN     6

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT  60

// NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255)

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)

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.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(BRIGHTNESS);
}

void loop() {
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0)     , 50); // Red
  colorWipe(strip.Color(  0, 255,   0)     , 50); // Green
  colorWipe(strip.Color(  0,   0, 255)     , 50); // Blue
  colorWipe(strip.Color(  0,   0,   0, 255), 50); // True white (not RGB white)

  whiteOverRainbow(75, 5);

  pulseWhite(5);

  rainbowFade2White(3, 3, 1);
}

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

void whiteOverRainbow(int whiteSpeed, int whiteLength) {

  if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;

  int      head          = whiteLength - 1;
  int      tail          = 0;
  int      loops         = 3;
  int      loopNum       = 0;
  uint32_t lastTime      = millis();
  uint32_t firstPixelHue = 0;

  for(;;) { // Repeat forever (or until a 'break' or 'return')
    for(int i=0; i<strip.numPixels(); i++) {  // For each pixel in strip...
      if(((i >= tail) && (i <= head)) ||      //  If between head & tail...
         ((tail > head) && ((i >= tail) || (i <= head)))) {
        strip.setPixelColor(i, strip.Color(0, 0, 0, 255)); // Set white
      } else {                                             // else set rainbow
        int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
        strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
      }
    }

    strip.show(); // Update strip with new contents
    // There's no delay here, it just runs full-tilt until the timer and
    // counter combination below runs out.

    firstPixelHue += 40; // Advance just a little along the color wheel

    if((millis() - lastTime) > whiteSpeed) { // Time to update head/tail?
      if(++head >= strip.numPixels()) {      // Advance head, wrap around
        head = 0;
        if(++loopNum >= loops) return;
      }
      if(++tail >= strip.numPixels()) {      // Advance tail, wrap around
        tail = 0;
      }
      lastTime = millis();                   // Save time of last movement
    }
  }
}

void pulseWhite(uint8_t wait) {
  for(int j=0; j<256; j++) { // Ramp up from 0 to 255
    // Fill entire strip with white at gamma-corrected brightness level 'j':
    strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
    strip.show();
    delay(wait);
  }

  for(int j=255; j>=0; j--) { // Ramp down from 255 to 0
    strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
    strip.show();
    delay(wait);
  }
}

void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {
  int fadeVal=0, fadeMax=100;

  // Hue of first pixel runs 'rainbowLoops' complete loops through the color
  // wheel. Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to rainbowLoops*65536, using steps of 256 so we
  // advance around the wheel at a decent clip.
  for(uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops*65536;
    firstPixelHue += 256) {

    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...

      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      uint32_t pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());

      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the three-argument variant, though the
      // second value (saturation) is a constant 255.
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255,
        255 * fadeVal / fadeMax)));
    }

    strip.show();
    delay(wait);

    if(firstPixelHue < 65536) {                              // First loop,
      if(fadeVal < fadeMax) fadeVal++;                       // fade in
    } else if(firstPixelHue >= ((rainbowLoops-1) * 65536)) { // Last loop,
      if(fadeVal > 0) fadeVal--;                             // fade out
    } else {
      fadeVal = fadeMax; // Interim loop, make sure fade is at max
    }
  }

  for(int k=0; k<whiteLoops; k++) {
    for(int j=0; j<256; j++) { // Ramp up 0 to 255
      // Fill entire strip with white at gamma-corrected brightness level 'j':
      strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
      strip.show();
    }
    delay(1000); // Pause 1 second
    for(int j=255; j>=0; j--) { // Ramp down 255 to 0
      strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
      strip.show();
    }
  }

  delay(500); // Pause 1/2 second
}

I meant your implementation of course, WG.
You stated that it's for external, but it's all the same (the neopixel doesn't know where it is).

Have you tried the adafruit forum ?

I did go on the Adafruit forum but most of the existing treads were with circuit python. I though this forum may be better as it's Arduino based. I'll post the same question there.

Thanks again

This Compiles --

// 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        6 // On Trinket or Gemma, suggest changing this to 1

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 1 // 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_NEOPIXEL, 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)
}

void loop() {
  pixels.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));

    pixels.show();   // Send the updated pixel colors to the hardware.

    delay(DELAYVAL); // Pause before next pass through loop
  }
}

I don't know what's meant by There is a NeoPixel power pin that needs to be pulled high... [b]This is done automatically[b]... available as NEOPIXEL_POWER.
If it's automagic, what's availability for? Does it have to be asserted HIGH?
IDK -- I don't have one of these.

For low power/battery life, there's a power bus that can be turned on or off, and the Neopixel is attached to it. I think it's supposed to be toggled on automatically, require intervention to disable it, but the note you highlighted in #8 might mean it could need explicit control.

I'm surprised LED_BUILTIN wasn't defined as 13. (#4) Maybe PIN_NEOPIXEL and NEOPIXEL_POWER aren't defined either. Is it a genuine board with the same pins & board configuration, etc?

I did see earlier today that one of the LDO's needs to be set high as the RGB led gets it's power from that LDO, I'll see if I can find where I saw that and I'll try this sketch later.

As far as the blink sketch I sent you, I would have thought just defining the pin would do it. It does complie and I added a couple of serial.print statements, the code is running it just doesn't blink the led. I changed the pin to 33 and added the neopixel library that complied but also didn't work

Here's where I saw the reference to the LDO, it's on the datasheet you sent.

" I'm trying to control the RGB LED but it wont light up

The RGB LED (APA102) is powered by the second LDO. You need to enable the second LDO power via GPIO21 to be able to use the RGB LED. It's controlled this way to have the RGB LED power automatically shutdown when the ESP32-S2 MCU goes into deep sleep."

You're saying the sketch that I posted, as posted, didn't run a color change pattern (dead in the water)?

Are you using an Adafruit Feather S2 or a Unexpected Maker Feather S2? And are you using the Arduino IDE board library for the right board (Adafruit or UM?) They use different pixel power pins.

@DaveX it is an Adafruit Feather S2

@runaway_pancake I haven't tried your sketch yet.

An interesting development but first, @runaway_pancake your sketch didn't compile, for me any way, I get the error "PIN_NEOPIXEL was not declared in this scope.

I had previously downloaded the modified blink code. When I plugged the USB cable back in, to download your code, the blue LED is blinking. To make sure that was the code in there I downloaded it again, this time removing the NEOPixal library, that was in there previous. After it downloaded it was not blinking. I then unplugged the USB and plugged it back in and not it blinks. Is it not getting a reboot after download or something?