2017-01-08 1 views
1

J'ai créé 2 bibliothèques à utiliser dans mon code Arduino. L'une est une bibliothèque HwSwitch, l'autre est une bibliothèque HwServo qui utilise la bibliothèque HwSwitch.Les valeurs des propriétés sont perdues (après chaque boucle) lors de l'imbrication des bibliothèques

HwSwitch Bibliothèque:

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 Bibliothèque:

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

Et voilà comment j'initialisés dans le code 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(); 
      } 
     } 
    } 
} 

Maintenant, enfin au problème! Comme vous pouvez le voir dans la bibliothèque HwSwitch, je génère des données en utilisant Serial.println. Ici, je peux voir que _lastPinState est mis à jour avec succès, mais est réinitialisé après chaque boucle. Cependant, lorsque je crée directement un HwSwitch et que je l'utilise, _lastPinState n'est pas réinitialisé. En d'autres termes, la réinitialisation de la valeur semble se produire uniquement lorsque la bibliothèque HwSwitch est utilisée dans la bibliothèque HwServo.

Apparemment, cela a quelque chose à voir avec les pointeurs? J'initialise probablement mes classes incorrectement, mais je n'ai aucune idée comment le réparer. Quelqu'un qui peut aider avec (et de préférence expliquer) ce problème?

+1

Essayez de faire la variable 'LimitSwitch' un pointeur (dans l'écriture de fichier h' HwSwitch * LimitSwitch ; '). Passez ensuite un pointeur au constructeur (ainsi le constructeur devient '..., HwSwitch * limitSwitch)' et ensuite vous l'appelez '... 94, new HwSwitch (" S1 ", 14 ...'). Enfin, vous devez changer les appels directs (par exemple, '.SwitchStateChanged()') en indirects (donc '-> SwitchStateChanged()'). C'est la manière standard de gérer les objets. Et, si vous envisagez de supprimer un objet 'HwServo', créez un destructeur et supprimez-le également. Essayez ceci et vérifiez s'il résout vos problèmes. – frarugi87

+0

Parce que le mot-clé 'new' n'est pas utilisé, et qu'il n'y a pas d'allocation de mémoire dynamique, le simple fait d'utiliser le destructeur par défaut et de laisser le pointeur hors de portée devrait fonctionner correctement :) – NonCreature0714

+0

@ frarugi87 J'utilise des pointeurs (*) mais j'ai échoué à trouver comment accéder aux méthodes ou propriétés après cela. Maintenant, je sais que je devais utiliser ->, a eu le code en cours d'exécution maintenant, merci! – Stitch10925

Répondre

1

Je n'ai pas mon Arduino sur moi en ce moment, mais j'ai regardé et j'ai réécrit votre code, ajouté les constructeurs omis à ma meilleure estimation, et je l'ai compilé. Il y avait des choses qui avaient besoin d'être corrigées. Je suis sûr qu'il y a d'autres façons, mais c'est ce que j'ai fait.

Pour le code complet, rendez-vous au here.

D'abord, j'ai créé quelques pointeurs vers des objets que je voudrais rester, comme ceci:

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

Maintenant, chacun est réservé à la mémoire de l'Arduino.

Maintenant, construire les objets 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; 
} 

Utilisez cette fonction de configuration !!! Peut-être pas toujours nécessaire, ou dans certains cas même recommandé, mais c'est bien de collecter des choses qui n'ont besoin d'être créées qu'une fois là-bas, surtout dans ce cas.

Notez que new n'a pas été utilisé dans la portée de l'un ou l'autre objet, mais plutôt dans le cadre du programme ... Donc, aucun destructeur de fantaisie dans vos objets n'est requis. Normalement, vous vous inquiétez de les supprimer tous avant la fin du programme (ou à chaque fois que cela vous convient), mais dans le cas d'Arduino, ça va juste perdre de la puissance et tout tuer de toute façon.

Vous devez changer vos définitions de classe à ceci:

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

Note: J'ai fait tout public, se sentir libre de se déplacer private revenir à des choses privées si vous le souhaitez.

J'ai changé les constructeurs à:

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

Je modifié loop() comme ceci:

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

Ce code ainsi que l'explication dans les commentaires précédents par @ frarugi87 m'a aidé à faire fonctionner le code. Merci! – Stitch10925