相关文章推荐
慷慨大方的硬盘  ·  page.waitfornavigation ...·  2 年前    · 
飞奔的山羊  ·  OC Swift ...·  2 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am new to C++ I come from a C# background. I am creating an Arduino project using c++ using vs code thanks to https://docs.platformio.org/ .

The following code works and turns on my led strip:

main.cpp

#include <Arduino.h>   
#include <LedStrip.h>
// pin where led strip is connected
#define LED_STIP_PIN 4
// number of leds in the strip
#define LED_STRIP_COUNT 7
// My wrapper class
LedStrip myLedStripWrapper;
void setup() {
   // empty
void loop() {
    myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);
    // myLedStripWrapper.foo1();  // <<<HERE-1>>>
    // wait forever
    while (true) {
        delay(1);

LedStrip.h

#include <Adafruit_NeoPixel.h>
class LedStrip
public:
    Adafruit_NeoPixel strip;
    void setup(uint16_t led_count, uint16_t pin)
        // Declare our NeoPixel strip object:
        Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);                
        strip = a;
        // INITIALIZE NeoPixel strip
        strip.begin();            
        strip.show();            
        strip.setBrightness(15); 
        foo1();     // <<<HERE-2>>> <------------------- calling foo1 from here turns on the led strip           
    // Color led strip blue
    void foo1()
        uint32_t color = strip.Color(0, 0, 100);
        for (uint16_t 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(100);

Note that in the code I have labels <<<HERE-1>>> and <<<HERE-2>>>. I want to call function foo1 from <<<HERE-1>>>. Why is it that if I uncomment <<<HERE-1>>> and comment <<<HERE-2>>> the code does not work and the LED strip does not turn on? In other words I do not want to call foo1 from within the class wrapper. I am just calling it form there because it only works if I call it form there.

I'm not familiar with Adruino, but my guess is that Adafruit_NeoPixel destructor, triggered by a local variable going out of scope, does something to disable the strip. You are probably not supposed to have two instances of Adafruit_NeoPixel in your program. – Igor Tandetnik Jul 3, 2020 at 20:43 Yes Adafruit_NeoPixel has a desctructor that disables the led strip. How can I prevent calling teh destructor? I want to initialize the strip variable from within the setup function in my LedStrip class – Tono Nam Jul 3, 2020 at 20:46 Looking at Adafruit_NeoPixel constructor implementation, you could probably just call updateLength, updateType and setPin on strip directly, without constructing a local variable. – Igor Tandetnik Jul 3, 2020 at 21:00 @IgorTandetnik yes I guess I will do that. I was just hoping I could create a wrapper class. – Tono Nam Jul 3, 2020 at 21:03

The writers of that class made a grade-school C++ mistake and didn't correctly observe the Rule of Three. This means an Adafruit_NeoPixel object can be copied when it is not safe to do so.

void setup(uint16_t led_count, uint16_t pin)
    // Declare our NeoPixel strip object:
    Adafruit_NeoPixel a(led_count, pin, NEO_GRB + NEO_KHZ800);                
    strip = a; // copy here. Both a and strip point to a shared resource
    // INITIALIZE NeoPixel strip
    strip.begin();            
    strip.show();            
    strip.setBrightness(15); 
} // a goes out of scope here and frees the shared resource in its 
  // destructor. Oops.

The easiest fix is to initialize strip in LedStrip's constructor where it doesn't need to be copied.

To ensure strip isn't copied, you're going to have to prevent LedStrip from being copied or implement special member functions that allow LedStrip to be copied without copying strip. In the example below I will simply prevent copying.

If copying is required consider replacing Adafruit_NeoPixel strip; with std::shared_ptr<Adafruit_NeoPixel> strip; so a pointer will be copied rather than an object that can turn into a bomb when copied.

class LedStrip
public:
    Adafruit_NeoPixel strip; // you sure you want this public?
    //  adding constructor so we don't have to copy a Adafruit_NeoPixel  object
    LedStrip(uint16_t led_count, uint16_t pin): 
        strip(led_count, pin, NEO_GRB + NEO_KHZ800) // this is a member initializer list
                                                    // It allows us to construct strip 
                                                    // without having to copy anything.
                                                    // more on that later
        // INITIALIZE NeoPixel strip
        strip.begin();            
        strip.show();            
        strip.setBrightness(15); 
    // preventing copying of LedStrip
    LedStrip(const LedStrip& ) = delete;
    LedStrip & operator=(const LedStrip& ) = delete;
    // note if the compiler doesn't like the = delete, remove it, make 
    // the copy constructor and assignment operator private, and do not 
    // implement them
    // Color led strip blue
    void foo1()
        uint32_t color = strip.Color(0, 0, 100);
        for (uint16_t 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(100);
private:
/* only needed if the = delete trick above doesn't work.
    LedStrip(const LedStrip& );
    LedStrip & operator=(const LedStrip& );
LedStrip myLedStripWrapper;

becomes

LedStrip myLedStripWrapper(LED_STRIP_COUNT, LED_STIP_PIN);
myLedStripWrapper.setup(LED_STRIP_COUNT, LED_STIP_PIN);

vanishes from the world, never to be seen again.

Documentation on the Member Initializer List.

Documentation on std::shared_ptr

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.