クラス内のバウンスライブラリのインスタンス化

私はクラスオブジェクト内の既存のライブラリからオブジェクトをインスタンス化する方法について頭を下ろそうとしています。具体的には、私はbounce2.h debouncerを働かせようとしています。

現時点では私のコードはコンパイルされていますが、バウンス機能は動作していないと思うのですが、デバッグ機能は動作していません。私の配列にはたくさんの乱数が入っています。バウンスオブジェクトを正しくインスタンス化していない可能性があります。誰かが私を助けることができれば、私は非常に感謝します!

私のヘッダー:

#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();
}

edit - 元のデバウンスのコードを単一のスケッチに追加しました

// 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オブジェクトは CandleRack オブジェクトの構築によってすでにインスタンス化されているため、その行は存在しません。

しかし、あなたが気付いていない場合、後端にあなたを噛む可能性がある静的初期化命令フィアスコとして知られていることを知っておく必要があります。これは基本的に、他のオブジェクトのオブジェクトを使用する場合で、オブジェクトが初期化される順序を予測できないため、それらのオブジェクトがまだ正しく作成されていない場合です。これはあなたのシステムの問題かもしれません。あなたが使っている他のクラスの振る舞いに依存します。

問題を解決する方法の1つは、問題になった場合(または問題を完全に回避したい場合)、ポインタと、最初に使用するとして知られているものを使用することです。これは、コンストラクタやクラス定義内のオブジェクトをインスタンス化しない場所です。代わりに、そのオブジェクトへのポインタを持ち、 new キーワードを使用して、メンバ関数(< code> begin())。

このために、クラス定義オブジェクトのエントリを次のようなポインタに変更します。

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;
    }
}

実際に作成されたオブジェクトを試して削除する必要があることに注意してください。したがって、nullでないかどうかを確認するテストです。

しかし、 newdelete を過度に使用することはお勧めしませんので、可能であれば静的コンテキストでオブジェクトを使用することをお勧めします。新しい newdeletemallocfree は、メモリが不足し、それに伴うすべての関連する安定性の問題が発生します。

もちろん、これはすべてオプションであり、他のクラスがうまく動作する場合は必要ないでしょう。

1
追加された
私の編集を参照してください。 2番目のコードにはまったく関係のない問題があります。
追加された 著者 Majenko,
それがCandleRack.hにある場合、CandleRack.cppにも含まれているので、CandleRack.cppに含まれています。
追加された 著者 Majenko,
CandleRackオブジェクトを削除して静的に作成した場合に限り、削除されることはありません。バウンスオブジェクトが作成されている場合は、バウンスオブジェクトを実際に削除したい場合はCandleRackのデストラクタを作成できますが、常に静的に作成する場合は必要ありません。
追加された 著者 Majenko,
ヒープフラグメンテーションの原因となるのは、 newdelete の繰り返しです。ヒープの断片化は非常に非常に悪いです。静的な方法で( delete を使用せず、 delete を使用したくない) new を使用すると、ヒープフラグメンテーションが発生しません。
追加された 著者 Majenko,
はい、できます。スタティックにすべてを静的に行い、全く新しいものを使用することはできません。ちょうど元の状態に戻り、Bounceオブジェクトを割り当てる関数をbegin関数内で削除します。ただし、静的な初期化順序の問題があります。他のオブジェクトのコンストラクタが何をしているのか分かりません。あなたのオブジェクトのためのポインタを使用することによって、あなたは "最初の使用時に"構築されているものを取得しています。つまり、システムが完全に初期化された後に常に構築されます。
追加された 著者 Majenko,
@ frarugi87はい、私はベッドの直前に書きました。すばらしい答えではありません。
追加された 著者 Majenko,
個人的に私は誤解を招くので、この回答を修正したいと思います。実際の問題には関係していないので、ポインタ(と新しい)部分を確実に削除する必要があります。あなたがそれを維持したい場合は、周囲の単語を変更してください(これは必須のことではありません)。しかし、1)ポインタをNULLに初期化する必要があります。2)新しい3)を明示的に削除する前に、ポインタがnull(複数のbegin呼び出しから保護するか、メモリリークが発生するか)をチェックします(そうでなければ、オブジェクトが縮小スコープで使用されている場合にメモリリークが発生します)
追加された 著者 Tom Collins,
@マジェンコ今これは良い答えです.. +1
追加された 著者 Tom Collins,
ありがとう。それでも私には同じ問題がありますが、配列に乱数をたくさん追加しています。それが役に立つならば、私はdebounceオブジェクトを使用するためのコードを1つのスケッチに投稿できますか?
追加された 著者 Slacker,
ああ、OK。 1つの問題は、 #define NUM_LEDS がFastLED配列から来ていることです。私はどのように参照するか、#defineを指すかどうかはわかりません(それは必要です)。
追加された 著者 Slacker,
すばらしいです。ちょうどそれを試してみて、それは問題を選別しました!巨大な感謝:)オブジェクトでFastLEDを使用しているトリッキーなビットのために今:)
追加された 著者 Slacker,
1つの質問...私はarduinoのスケッチで new を使うのは良いことではないことを読んでいました。この古いアドバイスですか?
追加された 著者 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,