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

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:

@RWB, only if you mirror the RGB led or use led signalling. With onchange(), you should be able to implement the Neopixel stuff as you have it. It should be easy to test. However I caution you to use a small number of Neopixels so as to not make refresh time very long.

@RWB, how does RGB.setBrightness(0) with subsequently setting the desired pinMode() work for you?
Not sure whether the r,g,b components of the onChange() handler will be altered with brightness, but they shouldn’t.
However, if you reuse any of the RGB pins as OUTPUT, you’ll see some flickering on the onboard RGB LED.

@ScruffR @peekay123

I think I have this figured out now after playing around some :slight_smile:

@Oizom_dev I changed the order of the code some to get this working with the v0.7.0-rc.4 firmware.

Note that I’m using the RGBW Neopixels so I have changed the LED type but the code layout is all you should need to copy if you’re using the RGB version.

If you want the LED to start working as soon as the Photon starts up then you need to use SYSTEM_THREAD(ENABLED); .

If you don’t then the Network status LED only starts after the WiFi connects and starts breathing cyan if you’re using Automatic mode. Semi-Automatic and Manual modes start the Network status LED instantly without SYSTEM_THREAD(ENABLED);.

The problem I was having is that the docs didn’t talk about how to turn off the or take over the RGB led pins 27,28,29. other than calling RGB.control(true); which also keeps the RGB.onChange function from working.

Turns out all you have to do is set their pin mode and then they stop driving the Photons’ RGB LED while the RGB.onChange function keeps working which is what you need for supplying the Neopixels the current
RGB values for current system status.

My simplified code is below for anybody who may need it :robot:

SYSTEM_THREAD(ENABLED);


#include "neopixel.h"


// Initialize objects from the lib

#define PIXEL_COUNT 8            //8 LEDs
#define PIXEL_PIN D2             // Digital pin for communications
#define PIXEL_TYPE SK6812RGBW    // Set for RGBW LED's / Change if your using regular RGB Neopixels. 

#define NETWORK_LED 0            // Pixel Number were using to show the Network Status LED Pattern. 

// Initialize objects from the lib
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);



void setup() {
   
   // disable on-board RGB LED on Photon/Electron / You can also set these pins for other uses. 
   pinMode(RGBR, INPUT_PULLUP);
   pinMode(RGBG, INPUT_PULLUP);
   pinMode(RGBB, INPUT_PULLUP); 
   
   Serial.begin(9600);
  
   RGB.onChange(ledChangeHandler);    
   strip.begin(); 
   strip.show(); // Initialize all pixels to 'off'
   delay(300);
  
 
    
}

void loop() {
    
    
}


void ledChangeHandler(uint8_t r, uint8_t g, uint8_t b)
{
  
  strip.setPixelColor(NETWORK_LED, g, r, b, 0); // Change this if your using regular RGB leds vs RGBW Leds. 
  strip.show();
  
}
2 Likes

That's what I meant with this

and

although the "side effects" of RGB.control(true) and RGB.setBrightness() were somewhat "unexpected" :blush:

But I'd not use INPUT_PULLUP or INPUT_PULLDOWN due to the hardwired components - INPUT alone should do.

1 Like

Cool, I was just looking at the functions provided in the Doc's and there is nothing there about what pin names to use to take control of the RGB pins which is why your comments didn't make sense until I saw Bdub's old post here about how to turn off the RGB led in the post below. That's where I got the Input Pullup idea.

Any idea why he chose Input_Pulldown? Instead of just INPUT?

Also, can we have the docs updated so other people know there is another way to use the RGB pins other than RGB.control(true);

Pin names would be RGBR, RGBG and RGBB

He says it'd be redundant but did it anyway - no idea why, but @bdub might be able to clarify :wink:

It’s all working perfectly now :smile:

I also solved the original posters issue with this working with the latest version of the firmware so you can mark this as Solved if you want.