Arduino - Enum变量值自行变化

时间:2017-10-15 13:49:21

标签: c++ enums arduino

我创建了一个Arduino超级草图来控制LED通道,以模拟简单的日落和日晒。在我的类LEDChannel声明中,我有一个公共枚举来表示LED通道的状态,并且我在类中有一个State枚举的私有实例(CurrentState)来跟踪这个LEDChannel实例。

一切都编译好并上传到我的Arduino Mega。问题是当我调试我的代码并检查CurrentState变量的值时,我得到一个超出枚举范围的值。有时我得到7579的值(我上次测试的实际值)。另一天,我可以得到612的值。值应该只有0到4.我验证了我的代码和任何地方我改变了这个变量的值,我使用枚举。例如:

CurrentState = ManualSunset;

CurrentState变量在LEDChannel Class的默认构造函数中接收值NoAction。

LEDChannel类是一个更大项目的一部分,该项目用于制作与其他类别的水族箱控制器,以代表RTC时间模块,蓝牙模块,风扇和温度传感器。

我使用Visual Studio Community 2015和Arduino的vMicro插件开发了我的项目。如果您需要完整的项目,我会找到一种方法使其可用。

这是LED通道声明/定义和主要的Arduino程序.ino。这是我的代码的简易版本。我删除了所有不必要的代码要重现该问题,只需在主程序nNbLEDChannel = 1;中注释第13行。然后,您应该为变量CurrentState获取值ManualSunrise(3)。请注意,nNbLEDChannel仅用于主.ino文件。

#pragma once

#if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
#else
    #include "WProgram.h"
#endif

//#include "DataTypes.h"
typedef byte duration;
class AquariumSimulator;

class LEDChannel
{
public:
    typedef enum State
    {
        AutomaticSunset = 0,
        AutomaticSunrise = 1,
        ManualSunset = 2,
        ManualSunrise = 3,
        NoAction = 4
    };

private:
    byte MaxBrightness;
    unsigned long lastTick;
    byte CurrentBrightness;
    LEDChannel::State CurrentState;
    byte DigitalPin;
    duration ManualSunsetDuration;// In secondes
    duration ManualSunriseDuration;// In secondes
    AquariumSimulator* pAquariumSim;

public:
    void StartManualSunrise(duration SecDuration);
    void PerformSunrise();
    LEDChannel();
    LEDChannel(byte DigitalPIN, AquariumSimulator* pSim);
private:
    void PerformManualSunrise();        
    void SetCurrentBrightness(byte value);
    void IncreaseCurrentBrightness(byte value = 1);
};

这是LEDChannel.cpp

#include "LEDChannel.h"
/*
Constuctor
*/
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
    LEDChannel();
    // Initialize default values
    pAquariumSim = pSim;
    pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}

LEDChannel::LEDChannel() 
{
    CurrentState = NoAction;

}

void LEDChannel::PerformSunrise()
{

    switch (CurrentState)
    {
    case AutomaticSunrise:
        //PerformAutomaticSunrise();
        break;

    case ManualSunrise:
        PerformManualSunrise();
        break;
    }
}

void LEDChannel::PerformManualSunrise()
{

    unsigned long currentTick = millis();
    if (currentTick >= (lastTick + ManualSunriseDuration / MaxBrightness))
    {

        // If current brightness is at max brigthness value, stop sunset
        if (CurrentBrightness == MaxBrightness)
        {
            CurrentState = NoAction;
            lastTick = 0;
        }
        else
        {
            IncreaseCurrentBrightness();
            lastTick = currentTick;
        }
    }
}

void LEDChannel::SetCurrentBrightness(byte value)
{
    if (value > 255)
        CurrentBrightness = 255;
    else
        CurrentBrightness = value;
    analogWrite(DigitalPin, CurrentBrightness);

}

void LEDChannel::IncreaseCurrentBrightness(byte value)
{
    if ((CurrentBrightness + value) <= 255)
        CurrentBrightness += value;
    else
        CurrentBrightness = 255;
    SetCurrentBrightness(CurrentBrightness);
}

// Manual Sunrise for a duration in secondes
void LEDChannel::StartManualSunrise(duration SecDuration)
{

    switch (CurrentState)
    {
    case NoAction:
        CurrentState = ManualSunrise;
        ManualSunriseDuration = SecDuration;
        SetCurrentBrightness(0);
        break;
    }

}

主程序.ino

#include "LEDChannel.h"

LEDChannel** pLED;
byte nNbLEDChannel;

void setup()
{
    pLED = new LEDChannel*[1];
    pLED[0] = new LEDChannel(44, NULL);

    /*  If i put the next line as comment CurrentState get a valid value. 
    If i assigne a value to nNbLEDChannel I get invalid value for CurrentState*/
    nNbLEDChannel = 1;  

    pLED[0]->StartManualSunrise(10);
}

void loop()
{
    pLED[0]->PerformSunrise();
}

2 个答案:

答案 0 :(得分:0)

您是否确保在setup()之前无法调用loop()?

在指针数组是&#34;来源&#34;之后立即设置一个值是可疑的。这个问题。这导致我怀疑pLED值是否正在改变,或者您有一些其他索引问题导致nNbLEDChannel所在的内存被解释为LEDChannel对象。

答案 1 :(得分:0)

我没有拿出我的Arduino UNO板,但我很确定你的主要问题是你试图从另一个构造函数中调用默认构造函数。编辑:调用LEDChannel()实际上构建了一个新的类实例,然后永远不会被使用或分配。 Arduino默认使用的C ++标准版本不支持该功能,有关详细信息,请参阅以下answer(如果您使用的是版本,它还演示了从另一个构造函数调用构造函数的正确语法支持它的标准)。这意味着CurrentState变量未初始化,并且在您观察时将是一些随机值。取消注释:

nNbLEDChannel = 1;

实际上与错误无关,只是重新排列显然将CurrentState变量置于有效值的内存。

类似的功能,在构造函数中具有公共代码,可以通过将公共初始化代码从默认构造函数移动到另一个这样的函数来实现,然后由两个构造函数调用(不要忘记初始化所有此函数中的类的成员变量为默认值,然后执行任何其他“特殊”初始化):

LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
    // Initialize default values
    commonInitFunction();

    //Do other "special" initialization
    pAquariumSim = pSim;
    //pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}

LEDChannel::LEDChannel()
{
    // Initialize default values
    commonInitFunction();

    //Do other "special" initialization
}

void LEDChannel::commonInitFunction()
{
    CurrentState = NoAction;
    //make sure all other member variables have been initialized to something either in here or
    //in your constructors to keep from having unexpected behavior
}

虽然初始化初始化列表中的变量是一个好主意,如here所述,然后将构造函数更改为以下(注意:我只选择了一些随机默认值):

LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim):
  MaxBrightness(255),
  lastTick(0),
  CurrentBrightness(0),
  CurrentState(NoAction),
  DigitalPin(DigitalPIN),
  ManualSunsetDuration(60),
  ManualSunriseDuration(60),
  pAquariumSim(pSim)
{
    //pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}

LEDChannel::LEDChannel():
  MaxBrightness(255),
  lastTick(0),
  CurrentBrightness(0),
  CurrentState(NoAction),
  DigitalPin(0),
  ManualSunsetDuration(60),
  ManualSunriseDuration(60),
  pAquariumSim(NULL)
{
    CurrentState = NoAction;
}

这确保为类的实例化初始化所有值(包括以正确的顺序)。

在旁注中,我确实注意到您提供的代码中的一些其他项目可能会导致您出现意外行为。

由于CurrentBrightness是一个字节(即uint8_t),在你的void LEDChannel :: IncreaseCurrentBrightness(字节值)方法中,检查CurrentBrightness +值是否为&lt; = 255.如果总和,这将只是假因溢出而等于255。基本上,如果CurrentBrightness为250并且我将值10添加到它,那么如果我没有弄错,我将获得值4。这可能不是此检查的理想行为。

第二个是你的枚举的typedef关键字没有做任何事情,因为你没有指定类型。在C ++中,如果你只想用你给它的原始名称来引用枚举或结构,则不需要typedef,就像你在这里所做的那样。查看一些答案here,即使其中没​​有一个被接受,前几个是