Mirroring RGB led to external LED strip in 0.7.0-rc.3

Hello everyone,
I’m testing the 0.7.0-rc.3 firmware release for electron and I would like to mirror the RGB led on-board to an external LED strip. I have tested it for 0.6.2 and it works absolutely fine but on 0.7.0-rc.3 it doesn’t work. It simply doesn’t turn on. I went through the change-log of firmware releases and I found that there are some changes to RGB.onchange() function in 0.7.0-rc.1 and 0.7.0-rc.2. However, I could not figure what modification is required from my side in order to mirror the LED. I also browsed the forum but I couldn’t find any thread specifically for 0.7.0-rc.3 LED mirroring. If anyone could point me in the right direction, it would be highly appreciated. Thanks!

Can you try and see if this works https://docs.particle.io/reference/firmware/photon/#mirrorto-

Also, can you share a simple code that doesn’t work so that the issue can be reproduced?

1 Like

Hi @kennethlimcp,
Thanks for the suggestion. Actually, I’m not using LEDs on analog pin but I’m using a neopixel LED strip so I cannot use mirrorTo in order to make them work. I’m using 3 LEDs on the strip to depict 3 different parameters based on data fed to them. One of the LEDs imitate the RGB LED on electron. I’ve used RGB.onchange with a changeHandler function to implement this functionality. Following is my sample code.

#include "neopixel.h"

// Initialize objects from the lib

#define PIXEL_COUNT 3                         //3 LEDs
#define PIXEL_PIN D4                          // Digital pin for communications
#define PIXEL_TYPE WS2812B

#define BATTERY_LED 2
#define NETWORK_LED 1
#define POWER_LED 0

Adafruit_NeoPixel LEDStrip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
STARTUP(cellular_credentials_set("APN","","",NULL));
STARTUP(beginLED());
void setup() {
    // Call functions on initialized library objects that require hardware
    initializeLED();
}

void loop() {
    // Use the library's initialized objects and functions

}

void ledChangeHandler(uint8_t r, uint8_t g, uint8_t b)
{
  LEDStrip.setPixelColor(NETWORK_LED, LEDStrip.Color(r, g , b));
  LEDStrip.show();
}
void beginLED()
{
  LEDStrip.begin();
  LEDStrip.show();
  delay(300);
  RGB.onChange(ledChangeHandler);
}

void initializeLED()
{
  LEDStrip.setPixelColor(BATTERY_LED, LEDStrip.Color(150,150,0));
  LEDStrip.setPixelColor(POWER_LED, LEDStrip.Color(150,150,150));
  LEDStrip.show();
}

Kindly note that above code works perfectly with 0.6.2 but the LED mimicking the on-board RGB LED doesn’t turn on when I flash for 0.7.0-rc.3 or 0.7.0-rc.2 or 0.7.0-rc.1

I just tried it with this code on a Photon and it seems to work as expected

SYSTEM_MODE(AUTOMATIC)
SYSTEM_THREAD(ENABLED)


void ledChangeHandler(uint8_t r, uint8_t g, uint8_t b)
{
    digitalWrite(D7, r > 50 || g > 50 || b > 50);
}

void setup()
{
  pinMode(D7, OUTPUT);
  digitalWrite(D7, HIGH);
  RGB.onChange(ledChangeHandler);
}

void loop() 
{
}

Have to get an Electron out next

@ScruffR, I wonder if this is a classic order-of-constructors issue with the neopixel library. The docs for STARTUP say:

The code referenced by STARTUP() is executed very early in the startup sequence, so it's best suited to initializing digital I/O and peripherals.

1 Like

With SYSTEM_THREAD(ENABLED) the “mirrored” LED even catches the AUTOMATIC connection process, so no need to put the RGB.onChange() call in the STARTUP() macro.

@ScruffR, your test uses the onboard LED whereas the OP uses the neopixel library. This is not an apples to apples comparison IMO.

True, but as the RGB.onChange() in my non-apples sample (which should show a way round the problem and proves that this is not an issue introduced with 0.7.0) is located in setup() the race condition you mentioned should not apply either :wink:

Thanks @ScruffR and @peekay123 for the lead. However, I’m a beginner at this so couldn’t figure out some things from the conversation. Sorry for that.:grinning: I wonder if it would be possible for you to explain in detail.

I tried code given by @ScruffR with electron for 0.7.0-rc.3 and it works fine. So I added SYSTEM_THREAD(ENABLED) to my code and removed beginLED() from STARTUP and added it to setup and everything works perfectly. So, the problem is solved for now.

I also wanted to know if this is the only correct way to do this? I mean, is it necessary to use SYSTEM_THREAD(ENABLED) instead of STARTUP? Because I prefer STARTUP over system thread as for the application I’m working on, System thread may create some issue.

If you can tell us what is not clear we can try to break it down for you and any beginner.

But the point Paul was refering to was that STARTUP() might be executed before the Neopixel object is fully set up for the job.

On the other hand if SYSTEM_THREAD(ENABLED) alone may cause problems there might be a design flaw in the project to start with.

3 Likes

@ScruffR and @peekay123 My apologies for not being quite clear. I didn’t understand the thing you mentioned about race condition. Also, as you said that STARTUP() might be executed before the neopixel object is fully set up for the job, I tried something else and it works. I used pointers for the job and that solved the issue. Following is the sample code.

#include "neopixel.h"

// Initialize objects from the lib

#define PIXEL_COUNT 3                         //3 LEDs
#define PIXEL_PIN D4                          // Digital pin for communications
#define PIXEL_TYPE WS2812B

#define BATTERY_LED 2
#define NETWORK_LED 1
#define POWER_LED 0

Adafruit_NeoPixel *LEDStrip;
STARTUP(cellular_credentials_set("APN","","",NULL));
STARTUP(beginLED());
void setup() {
    // Call functions on initialized library objects that require hardware
    beginLED();
    initializeLED();
}

void loop() {
    // Use the library's initialized objects and functions

}

void ledChangeHandler(uint8_t r, uint8_t g, uint8_t b)
{
  LEDStrip->setPixelColor(NETWORK_LED, LEDStrip->Color(r, g , b));
  LEDStrip->show();
}
void beginLED()
{
  LEDStrip = new Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
  LEDStrip->begin();
  LEDStrip->show();
  delay(300);
  RGB.onChange(ledChangeHandler);
}

void initializeLED()
{
  LEDStrip->setPixelColor(BATTERY_LED, LEDStrip->Color(150,150,0));
  LEDStrip->setPixelColor(POWER_LED, LEDStrip->Color(150,150,150));
  LEDStrip->show();
}

This way, neopixel sets up after I call beginLED() in start-up and so order of execution is maintained. As you mentioned, there could be some design flaw in the project since SYSTEM_THREAD(ENABLED) alone causes issues. That’s a bug I’m working on but I’m not able to fully debug it. Anyway, for now this works fine.

Thank you so much for all the help. :slight_smile:

2 Likes

@Oizom_dev Thanks for sharing this code! It works out the box :slight_smile:

@Peekay123 & @ScruffR If I run this Neopixel library is there anything I need to watch out for as far as using other pins on the Photon that may be tied to any of the functions or Photon hardware that the Neopixel library is using while running?

Generally speaking you can use any GPIO pin as long you are not explicitly (or implicitly via a library) activating any alternate function (e.g. HW interface) on that very pin.

Since your question is rather open, listing all possible interferences would be rather laborious. Knowing what specific pin(s) you have in mind would make that easier :wink:

For my current project, I’m using just about every pin on the Photon as shown in the schematic below.

My original intent was to use the Photons bottom pins 27,28, and 29 to control this RGB Push button using the Neopixel and a single digital line makes more sense to me on many fronts.

I can use a cheaper button without a LED, I will not need all 3 RGB pins 27,28,29, and I already need to control a batch of Neopixels on this project anyways. This will free up 2 of the bottom RGB pins on the Photon by not using the RGB button.

The only other thing I want to add to this is a uSD card to hold firmware files downloaded via a HTTP download to SD card. I assume there will be no problem sharing the SPI bus with the RFM95w LoRa radio?

Just curious if the Neopixels would affect any of the pins I’m using in the schematic drawing or not? I’m not using PWM out on any of the pins.

I assume the Neopixel data pin can be one of the bottom 27,28,29 pins without any problems?

Are you using the RX/TX pins already?

I guess you already did, but just to explicitly say: In order to use 27, 28 & 29 you need to take deactivate the system RGB control.
Once you’ve done that, these can be used as any other GPIO too but be arware of the hardwired components on the photon (RGB LED and current limiting resistors).

Yea the TX/RX pins are how the 4Dsystems LCD display communicates with the Photon.

I’ve deactivated system RGB control before so I’ve seen that work.

I’ll be sure to ask for advice on the RGB pins and how the Hardwired parts could affect my application once I know what I want to use them for.

Thanks for the clarification on all this :thinking:

@ScruffR Is the code below the correct way to turn off the system control of the Photon RGB LED?

RGB.control(true);

I added that line to the setup and it turns the Photon RGB off but then the Neopixel LED goes out also.

It’s looking like the line above stops the line below from feeding the Neopixel the current RGB network status.

RGB.onChange(ledChangeHandler);

I didn’t see any other functions for turning off the LED in the Photon LED Docs page :slight_smile:

With RGB.control(true) you don’t only deactivate system control but take over control over the RGB LED via RGB.color().
But after that you can use pinMode() and any other suitable GPIO command to control their behaviour.

You may also want to look into this
https://docs.particle.io/reference/firmware/photon/#led-signaling

I get that and it makes perfect sense.

I’m using the Neopixel code above to mirror the Photon status RGB LED but since the Photon will be inside the product case it makes sense to just turn it OFF to save on power consumption.

I’m controlling the Neopixel data on D4 and the Neopixel is just displaying the color data via the ledChangeHandler below. Problem is the ledChangeHandler stops working when I take control of the LED so the Neopixel goes dark when the Photon goes out which makes sense.

void ledChangeHandler(uint8_t r, uint8_t g, uint8_t b)
{
  LEDStrip->setPixelColor(NETWORK_LED, LEDStrip->Color(r, g , b));
  LEDStrip->show();
}

Is there a way to make the ledChangeHandler work while the Photon RGB LED remains OFF consuming no power?

I looked over all the LED functions and it looks like if you're using the RGB colors to set the Neopixel color then you have to have 3 RGB PWM pins set to get the RGB values to feed the Neopixel.

I see no way to not use 3 Pins to mirror the status LED somewhere else.

Look like I need to just leave the LED on the Photon ON even though it's not going to be visible.

:confused: