嵌套库时,属性值会丢失(在每个循环之后)

时间:2017-01-08 17:11:13

标签: arduino arduino-ide

我在我的Arduino代码中创建了2个库。一个是HwSwitch库,另一个是使用HwSwitch库的HwServo库。

HwSwitch图书馆:

HwSwitch::HwSwitch(String switchName, int switchPort, int inputType, int pressedState)
{ 
    Name = switchName;
    SwitchPort = switchPort;
    _pressedState = pressedState;
    _lastCheckMillis = 0;

    pinMode(switchPort, inputType);
    _lastPinState = digitalRead(SwitchPort);
}

bool HwSwitch::IsPressed()
{
    int currentPinState = GetPinState();
    return currentPinState == _pressedState;
}

bool HwSwitch::SwitchStateChanged()
{
    int currentPinState = GetPinState();
    if (_lastPinState != currentPinState)
    {
        Serial.println("---");
        Serial.println("1. Now: " + String(currentPinState) + " - Prev: " + String(_lastPinState));

        _lastPinState = currentPinState;
        Serial.println("2. Now: " + String(currentPinState) + " - Prev: " + String(_lastPinState));

        return true;
    }

    return false;
}

int HwSwitch::GetPinState()
{
    unsigned long ms = millis();
    if ((ms - _lastCheckMillis) < 50)
    {
        return _lastPinState;
    }

    _lastCheckMillis = ms;
    return digitalRead(SwitchPort);
}

HwServo Library:

HwServo::HwServo(int servoPort, int zeroPoint, HwSwitch limitSwitch)
{
    _servo.attach(servoPort);
    _servo.write(zeroPoint);

    ServoPort = servoPort;
    ZeroPoint = zeroPoint;

    LimitSwitch = limitSwitch;
}

void HwServo::RotateUp()
{
    _servo.write(ZeroPoint + UP);
}

void HwServo::RotateDown()
{
    if (!LimitSwitch.IsPressed())
    {
        _servo.write(ZeroPoint + DOWN);
    }
}

void HwServo::Stop()
{
    _servo.write(ZeroPoint);
}

这就是我在Arduino代码中初始化它的方式:

HwServo HwServos[] = {
    HwServo(9, 94, HwSwitch("S1", 14, INPUT_PULLUP, HIGH)),
    HwServo(5, 90, HwSwitch("S2", 8, INPUT_PULLUP, HIGH)),
};

void setup() { }

void loop() {

    for(int i = 0; i < 2; i++)
    {
        HwServo hwServo = HwServos[i];

        if (hwServo.LimitSwitch.SwitchStateChanged())
        {
            SendSwitchStateUpdate(hwServo.LimitSwitch);

            if (hwServo.LimitSwitch.IsPressed())
            {
                hwServo.Stop();
            }
        }
    }
}

现在终于到了问题!正如您在HwSwitch库中看到的,我使用Serial.println输出一些数据。在这里我可以看到_lastPinState已成功更新,但在每次循环后都会重置。但是,当我直接创建HwSwitch并使用它时,_lastPinState不会重置。换句话说,只有在HwServo库中使用HwSwitch库时才会重置值。

显然这与指针有关?我可能错误地初始化了我的类,但我不知道如何解决它。有谁可以帮助(并最好解释)这个问题?

1 个答案:

答案 0 :(得分:1)

我现在没有把我的Arduino放在我身上,但我看了看并重新编写了代码,在我最好的猜测中添加了省略的构造函数,并将其编译。有些事情需要纠正。我确定还有其他方法,但这就是我所做的。

有关完整代码,请转到here

首先,我创建了一些指向我想要留下的对象的指针,如下所示:

HwServo *HwServos[2];
HwSwitch *s1;
HwSwitch *s2; 
HwServo *sv1; 
HwServo *sv2;

现在每个都留在Arduino的内存中。

现在,在setup()

中构建对象
void setup() {
    s1 = new HwSwitch("S1", 14, INPUT_PULLUP, HIGH);
    s2 = new HwSwitch("S2", 8, INPUT_PULLUP, HIGH);
    sv1 = new HwServo(9, 94, *s1);
    sv2 = new HwServo(5, 90, *s2);


    //Now, since you're going through an array:
    HwServos[0] = sv1;
    HwServos[1] = sv2;
}

使用该设置功能!也许并不总是必要的,或者在某些情况下甚至是推荐的,但收集只需要在那里创建的东西很好,特别是在这种情况下。

请注意,new未在任一对象的范围内使用,而是在程序范围内使用...因此,不需要在对象中使用花哨的析构函数。通常情况下,你担心在程序终止之前(或者最适合的时候)将它们全部删除,但在Arduino的情况下,它会失去权力并且无论如何都会杀死所有东西。

您应该将类​​定义更改为:

class HwSwitch {
public:
    String Name;
    int SwitchPort;
    int _pressedState;
    int _lastCheckMillis;
    int _lastPinState;
    HwSwitch(String, int, int, int);
    bool IsPressed();
    bool SwitchStateChanged();
    int GetPinState();
};

class HwServo {
public:
    HwServo();
    HwServo(int, int, HwSwitch &);
    int ServoPort;
    int ZeroPoint;
    HwSwitch & LimitSwitch;
    void RotateUp();
    void RotateDown();
    void Stop();
    Servo _servo;
};

注意:我制作了所有内容public,如果您愿意,可以随意将private内容移回私有。

我将构造函数更改为:

HwSwitch::HwSwitch(String switchName, int switchPort, int inputType, int pressedState)
{ 
    Name = switchName;
    SwitchPort = switchPort;
    _pressedState = pressedState;
    _lastCheckMillis = 0;

    pinMode(switchPort, inputType);
    _lastPinState = digitalRead(SwitchPort);
}

HwServo::HwServo(int servoPort, int zeroPoint, HwSwitch &limitSwitch)
{
    _servo.attach(servoPort);
    _servo.write(zeroPoint);

    ServoPort = servoPort;
    ZeroPoint = zeroPoint;

    LimitSwitch = limitSwitch;
}

我像这样修改了loop()

void loop() {
// put your main code here, to run repeatedly:
    for(int i = 0; i < 2; i++)
    {
        if (HwServos[i]->LimitSwitch.SwitchStateChanged())
        {
            SendSwitchStateUpdate(HwServos[i]->LimitSwitch);
            if (HwServos[i]->LimitSwitch.IsPressed())
            {
                HwServos[i]->Stop();
            }
        }
    }
}