在类中实例化反弹库

我试图了解如何从类对象中的现有库中实例化对象。具体来说,我试图让bounce2.h debouncer正常工作。

目前我的代码编译,但我认为debounce函数不起作用,因为按钮正在填充我的数组有很多随机数(甚至来自设置),而它在非基于类的草图上工作正常,所以我认为我是可能没有正确实例化反弹对象。如果有人可以提供帮助,我将非常感激!

我的标题:

#ifndef CandleRack_h
#define CandleRack_h

class CandleRack
{
  public:

    CandleRack(byte candleRackStatus);
    void begin();
    void pushButton();
    void selectRandomCandle();
    void turnOnCandle(byte candlePosition);
    void burnCandlesForMs();
    void fadeOutCandle(byte candlePosition);

  private:
    Bounce _debouncePushButton;
    byte _pushButtonPin; 
    byte _candleRackStatus;    
    byte _candlePosition;
    byte _candleStatus[];
    elapsedMillis _candleTimeElapsed;
    unsigned int _candleOnForMs;
};
#endif

我的cpp

#include "Arduino.h"
#include 
#include 
#include 
#include "CandleRack.h"

#define NUM_LEDS 50

CandleRack::CandleRack(byte candleRackStatus)
{
  _candleRackStatus = candleRackStatus;
}

void CandleRack::begin()
{
  randomSeed(analogRead(0));

  _debouncePushButton = Bounce();
  _pushButtonPin = 3;
  _candleOnForMs = 20000;
  pinMode(_pushButtonPin, INPUT_PULLUP);
  _debouncePushButton.attach(_pushButtonPin);
  _debouncePushButton.interval(10);

  for (byte b = 0; b < NUM_LEDS; b++)
  {
    _candleStatus[_candlePosition] = 0;
  }

  Serial.println("Candle Array: ");      //Debug ************************
  for (byte b = 0; b < NUM_LEDS; b++)    //Debug ************************
  {                                      //Debug ************************
    Serial.print(_candleStatus[b]);      //Debug ************************
    Serial.print(", ");                  //Debug ************************
  }                                      //Debug ************************
  Serial.println("");                    //Debug ************************
  Serial.println("Begin Complete");      //Debug ************************
}


void CandleRack::pushButton()
{
 //Look for a button push
  if (_debouncePushButton.update())
  {
    if (_debouncePushButton.fell())
    {
      selectRandomCandle();
    }
  }
}


void CandleRack::selectRandomCandle()
{
  byte randomCandlePosition;
  do
  {
    randomCandlePosition = random(0, NUM_LEDS);
  }
  while (_candleStatus[randomCandlePosition] != 0);

  turnOnCandle(randomCandlePosition);
}


void CandleRack::turnOnCandle(byte _candlePosition)
{
 //leds[_candlePosition] = CRGB::Red;
  _candleStatus[_candlePosition] = 1;

  Serial.println("Button Pushed: ");     //Debug ************************
  Serial.println(_candlePosition);       //Debug ************************
  Serial.println("Candle Array: ");      //Debug ************************
  for (byte b = 0; b < NUM_LEDS; b++)    //Debug ************************
  {                                      //Debug ************************
    Serial.print(_candleStatus[b]);      //Debug ************************
    Serial.print(", ");                  //Debug ************************
  }                                      //Debug ************************
  Serial.println("");                    //Debug ************************
}


void CandleRack::burnCandlesForMs()
{
 //See if it is time to turn the candle off
  for (byte b = 0; b < NUM_LEDS; b++)
  {
    if (_candleTimeElapsed > _candleOnForMs && _candleStatus[b] == 1)
    {
      CandleRack::fadeOutCandle(b);
      _candleTimeElapsed = 0;
    }
  }
}


void CandleRack::fadeOutCandle(byte _candlePosition)
{
  _candleStatus[_candlePosition] = 0;
}

我的素描:

#include "Arduino.h"
#include 
#include 
#include 
#include "CandleRack.h"

CandleRack MyCandleRack(0);

void setup() {
  delay(3000);//sanity delay

  Serial.begin(9600);
  while (!Serial); 

  Serial.println("Setup Starts"); //Debug ************************

  MyCandleRack.begin();

  Serial.println("Setup Complate"); //Debug ************************
}

void loop() {

  MyCandleRack.pushButton();
//MyCandleRack.burnCandlesForMs();

  FastLED.show();
}

编辑 - 为原始去抖动示例添加了单个草图的代码

// Detect the falling edge

// Include the Bounce2 library found here :
// https://github.com/thomasfredericks/Bounce-Arduino-Wiring
#include 


#define BUTTON_PIN 2
#define LED_PIN 13

int ledState = LOW;


// Instantiate a Bounce object :
Bounce debouncer = Bounce(); 

void setup() {

 //Setup the button with an internal pull-up :
  pinMode(BUTTON_PIN,INPUT_PULLUP);

 //After setting up the button, setup the Bounce instance :
  debouncer.attach(BUTTON_PIN);
  debouncer.interval(500);

 //Setup the LED :
  pinMode(LED_PIN,OUTPUT);
  digitalWrite(LED_PIN,ledState);


}

void loop() {

 //Update the Bounce instance :
   debouncer.update();

  //Call code if Bounce fell (transition from HIGH to LOW) :
   if ( debouncer.fell() ) {

    //Toggle LED state :
     ledState = !ledState;
     digitalWrite(LED_PIN,ledState);

   }
}
0

1 答案

您的主要问题(症状的原因)是您的 _candleStatus 数组没有大小。在没有指定大小的情况下,最终没有为阵列分配内存,因此没有有效内容。

在你的类定义中:

byte _candleStatus[];

应修改为:

byte _candleStatus[NUM_LEDS];

并且 NUM_LEDS 应该在标题中定义,而不是在CPP文件中定义。 (通过在头文件中指定它,因为头文件包含在CPP文件中,所以定义最终在两个文件中)。

除此之外,这条线没有按照你的想法做到:

_debouncePushButton = Bounce();

您正在将仅为该场合创建的匿名反弹对象的内容复制到预先存在的Bounce对象中。您不希望该行存在,因为Bounce对象已经由构造 CandleRack 对象实例化。

但是,您需要注意一些被称为静态初始化命令Fiasco 的东西,如果您不了解它,可能会在后端咬你。这基本上是当您在其他对象中使用对象并且尚未正确创建这些对象时,因为您无法预测对象的初始化顺序。这可能是您系统中的问题,也可能不是问题 - 这一切都取决于您使用的其他类的行为方式。

解决这个问题的一种方法是,如果你发现它确实成了一个问题(或者你只想完全避免这个问题)就是使用指针和所谓的首次使用时构建。这是您不在构造函数或类定义中实例化任何对象的地方 - 而是只有指向它们的指针并使用 new 关键字从成员函数中构造对象(例如<�代码>开始()</代码>)。

为此,您将类定义对象条目更改为指针,例如:

Bounce *_debouncePushButton = NULL;

(请注意,并非所有版本的编译器都支持类定义中的赋值。它是C ++的现代补充,并且取决于您的Arduino软件版本可能有效也可能无效。如果没有,您可以移动通过从定义中删除 = NULL 并将 _debouncePushButton = NULL; 添加到构造函数中来赋值给构造函数。)

然后在 begin()函数中构造一个新对象(如果尚未创建):

if (_debouncePushButton == NULL) {
    _debouncePushButton = new Bounce();
}

Now you have to access the _debouncePushButton as a pointer to an object not an object, so change all your accesses to use the pointer dereference operator ->:

_debouncePushButton->attach(_pushButtonPin);
... etc ...

如果该类应该超出范围或以动态方式使用,您真的应该创建一个析构函数来删除任何具有已创建:

CandleRack::~CandleRack() {
    if (_debouncePushButton != NULL) {
        delete _debouncePushButton;
    }
}

请注意,您应该只尝试删除实际创建的对象 - 因此要测试它是否为空。

但是不鼓励过度使用 newdelete ,因此最好在静态上下文中使用对象(如果可能)。太多 newdeletemallocfree 会导致堆碎片导致内存不足以及随之而来的所有相关稳定性问题。

当然,所有这些都是可选的,如果其他类表现良好,则可能不需要它。

1
额外
看我的编辑。您的代码存在第二个完全不相关的问题。
额外 作者 Majenko,
如果它在CandleRack.h中,那么它也在CandleRack.cpp中,因为CandleRack.h包含在CandleRack.cpp中。
额外 作者 Majenko,
只有你删除了CandleRack对象,并且因为你静态地创建它永远不会被删除。你可以为CandleRack制作一个析构函数,如果你真的想要并删除Bounce对象(如果它已经被创建),但如果你总是要静态创建它,那么就没有任何需要。
额外 作者 Majenko,
并且不是使用 new 那么糟糕 - 重复的 newdelete 导致堆碎片 - 当你只有一个小的时候堆碎片非常非常糟糕。以静态方式使用 new (从不使用 delete 并且永远不想使用 delete )永远不会导致堆碎片。
额外 作者 Majenko,
你可以,是的。可以静态地完成所有事情而不是完全使用new - 只需恢复原样并删除在begin函数中指定Bounce对象的行 - 但是如果你不喜欢静态初始化顺序问题的话不知道其他对象的构造函数在做什么。通过使用指针为您的对象,您将获得所谓的“首次使用时构造”,这意味着它们将始终在系统完全初始化后构建。
额外 作者 Majenko,
@ frarugi87是的,我刚睡觉前写的。这不是一个很好的答案。
额外 作者 Majenko,
就个人而言,我会解决这个问题,因为它具有误导性。你绝对应该删除指针(和新的)部分,因为它与实际问题无关。如果,在另一方面,你想保留它,改变周围的单词(这不是一个强制性的事情,它只是你建议的东西)但是,然后,你需要1)初始化指针为NULL 2)检查指针是否为空(防止多次开始调用,或者存在内存泄漏),然后再创建新的3)明确删除它(否则如果对象在缩小范围内使用则存在内存泄漏)
额外 作者 Tom Collins,
@Majenko现在这是一个很好的答案.. + 1
额外 作者 Tom Collins,
谢谢。它仍然给我同样的问题,它为数组添加了大量的随机数。如果它有帮助,我可以在单个草图中发布使用去抖动对象的代码吗?
额外 作者 Slacker,
唉,好的。一个问题是 #define NUM_LEDS 来自我的FastLED数组,我想在主草图中需要它。我不确定如何引用/指向#define(它需要)。
额外 作者 Slacker,
大。刚刚尝试过,它解决了问题!非常感谢:)现在对于在对象中使用FastLED的棘手的一点:)
额外 作者 Slacker,
一个问题......我读过在arduino草图中使用 new 并不好。这是旧的adivce吗?
额外 作者 Slacker,
我一直在阅读 new ,我应该在某处使用 delete 以及 arduino.land/FAQ/content/4/24/en/mixing-malloc-and-new.html
额外 作者 Slacker,
我是否也应该为我的其他库对象使用指针 - elapsedMillis?它目前运作正常,但考虑到你的最后建议,在那里使用指针可能也有优势?
额外 作者 Slacker,
有道理 - 我现在明白,从线程开头我遇到的错误是randomNumber数组问题 - 其余的更多是'最佳实践'。所以我需要做的就是改变(在标题中) elapsedMillis _candleTimeElapsed [NUM_LEDS];elapsedMillis * _candleTimeElapsed [NUM_LEDS]; ?因为在这种情况下我不能使用 - > 表示法,因为现在我仔细观察它实际上并没有实例化一个在这种情况下引用的elapsedMillis对象。是对的吗?
额外 作者 Slacker,
感谢更新的答案,这对我的理解产生了巨大的影响。特别是我之前假设使用 new 将是实例化对象的首选方式。
额外 作者 Slacker,