OOP vs Inline avec Arduino

8

Je programme depuis un certain temps maintenant, mais je suis nouveau dans la programmation Arduino et AVR. La principale question que j'ai à propos de la programmation de ces microcontrôleurs est la suivante: y a-t-il des différences majeures dans la conception de code dans les classes orientées objet par rapport à la programmation en ligne plus traditionnelle que j'ai vue dans de nombreux exemples?

En d'autres termes, dans le monde des contrôleurs Arduino / AVR, y a-t-il des économies avec la mémoire et les performances en utilisant des classes ou vice versa?

Disons par exemple que nous avons une classe:

class SomeClass(){

private:
   int x;
   int y;

public:
   void foo();
   void bar();
}

SomeClass thisClass;
thisClass.foo();
thisClass.bar();

Y aurait-il des gains de performances ou de mémoire en concevant le programme d'une manière plus intégrée comme:

int x;
int y;

void foo(){ /*** Do something ***/};
void bar(){ /*** Do more stuff ***/};

J'ai essayé de faire des recherches sur Stack Exchange et Google, mais je n'ai pas trouvé la réponse que je cherchais. La chose la plus proche que j'ai pu trouver était cette question Stack Exchange.

La raison pour laquelle je pose cette question est que j'ai un projet qui doit être aussi léger que possible et je ne sais pas comment je devrais concevoir mon programme dans cet environnement.


Éditer

Merci pour les réponses, cela a fait la lumière sur les choses. Il y a une chose sur laquelle je ne suis pas tout à fait clair.

Supposons que vous ayez une classe que vous concevez qui utilise u8glib comme suit:

class UserInterface{
private:
   U8GLIB_ST7920_128X64 Display;

public:
   UserInterface();
}

Comment feriez-vous pour utiliser la «mémoire dynamique» comme:

UserInterface::UserInterface(){
   UserInterface::Display = U8GLIB_ST7920_128X64(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE);
}
Andy Braham
la source

Réponses:

2

La principale question que j'ai à propos de la programmation de ces microcontrôleurs est la suivante: y a-t-il des différences majeures dans la conception de code dans les classes orientées objet par rapport à la programmation en ligne plus traditionnelle que j'ai vue dans de nombreux exemples?

...

En d'autres termes, dans le monde des contrôleurs Arduino / AVR, y a-t-il des économies avec la mémoire et les performances en utilisant des classes ou vice versa?

Oui, il existe une grande différence entre l'utilisation de C ou C ++ pour les systèmes embarqués à petite échelle tels que Arduino / AVR. C ++ permet de fournir plus d'informations pour les optimisations du compilateur.

Si vous implémentez une infrastructure OOP, une plateforme ou un runtime C ++ et des classes peuvent également aider à l'architecture et à la réutilisation des logiciels. Dans Cosa, un certain nombre de modèles de conception OOP sont utilisés pour réaliser des interfaces pour les programmeurs d'applications et les programmeurs de pilotes de périphériques. La plus courante est la délégation .

L'utilisation de classes abstraites, de fonctions de membre virtuel, d'inlining et de modèles peut aider à réduire l'encombrement et à améliorer les performances par rapport aux implémentations traditionnelles. Par exemple, les classes Cosa Pin sont X5-X10 plus rapides que le noyau Arduino et en même temps plus petites en encombrement. Veuillez consulter les repères .

Une chose à "désapprendre" de la programmation C ++ traditionnelle est l'utilisation de new / delete (malloc / free). Avec une taille SRAM de seulement quelques kilo-octets, l'utilisation d'un tas est très risquée. La réponse est des classes statiques et des données basées sur la pile.

Il y a beaucoup plus à dire sur l'architecture du cadre OOP mais j'espère que cela aidera à répondre à vos questions initiales.

À votre santé!

Mikael Patel
la source
Bonne réponse! J'ai mis à jour ma question demandant comment contourner la mémoire dynamique (nouveau / supprimer / malloc / gratuit). Avez-vous des informations sur la non-utilisation de l'allocation dynamique de mémoire? Tout ce qui doit être partagé dans les classes doit-il être global? Cela ne me semble pas juste, on m'a toujours appris à ne pas utiliser les globaux si vous pouvez l'aider.
Andy Braham
Un bref commentaire sur votre exemple UserInterface ci-dessus. L'affichage est en fait une composition d'objet (pas une référence / un pointeur), vous n'avez donc pas besoin de nouveau. Vous devez lancer l'affichage. La construction UserInterface devrait ressembler à ceci. UserInterface::UserInterface() : Display(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE) { ... }. Les paramètres nécessaires du constructeur Display doivent être transmis au constructeur UserInterface.
Mikael Patel
La POO est tout au sujet de l'encapsulation, de la dissimulation des données, donc le partage devrait être un minimum (zéro). Le but est de n'avoir plus ou moins qu'un certain nombre d'objets statiques globaux qui interagissent. Ils détiennent et cachent l'État mondial. Pour les objets, les données de membre sont un état local non dynamique. Pour atteindre l'objectif, vous avez besoin à nouveau d'un ensemble de trucs; transformations de programme.
Mikael Patel
Un exemple; Considérez la conception d'une classe BitSet qui peut avoir un nombre variable de membres. La solution évidente est de calculer le nombre d'octets requis et d'utiliser new / malloc. Une alternative consiste à passer le stockage en tant que paramètre au constructeur BitSet. Une troisième alternative est une classe modèle avec un nombre d'éléments comme paramètre. Cela permet une variable membre qui est le nombre d'octets nécessaire. Veuillez consulter Cosa / BitSet.hh pour plus de détails sur cette variante de transformation de programme. Il y a plus de transformations.
Mikael Patel
J'ai mis à jour mon exemple UserInterface, est-ce plus ou moins la bonne approche? Je pense que j'ai maintenant une très bonne compréhension sur la façon de mettre en œuvre ce dont j'ai besoin.
Andy Braham
4

La raison pour laquelle vous ne pouvez pas trouver la réponse est que la réponse est à la fois Oui et Non.

Pour les choses de classe de base - définir votre classe avec des méthodes, etc. et en instancier des objets - il y a peu de différence dans le résultat final par rapport à "vanilla" C. Les optimisations du compilateur sont si bonnes maintenant que les performances sont les mêmes. Oui, il peut y avoir une légère augmentation de l'utilisation de la mémoire car vous passez un pointeur supplémentaire à chaque appel de méthode (au lieu que foo(int x)vous l'avez foo(MyClass *this, int x)), mais c'est si petit qu'il n'est pas perceptible.

Les grandes différences surviennent lorsque vous commencez à jouer avec le polymorphisme et d'autres sujets avancés. Lorsque vous commencez à exécuter ces programmes complexes, le compilateur n'est pas toujours incapable de déterminer quelles fonctions sont requises et lesquelles ne le sont pas, et il n'est pas en mesure de supprimer les fonctions inutilisées ( "garbage collection" ). Vous pourriez donc vous retrouver avec un code plus gros.

Cela ne signifie pas un code plus lent, juste des morceaux de code qui traînent et qui ne font jamais rien.

Il est plus important de gérer votre mémoire dynamique mieux que d'habitude. Puisqu'il y a une si petite quantité de mémoire, le tas est très petit et, par conséquent, il se fragmente très facilement. La création et la destruction dynamique des objets ( new myClass, delete myClassObject, etc.) est très mauvais. Les objets de classe doivent vraiment être définis statiquement (dans la portée globale est le plus courant) ou temporairement alloués sur la pile (instances locales). Sinon, vous demandez des ennuis - et le premier vous en saurez que des choses étranges se produisent (pas de rapports d'erreur ou d'exceptions, vous voyez ...).

Majenko
la source
Très bien, donc si je comprends bien dans ce monde de la programmation, les classes sont utilisées pour plus d'un rôle d'organisation et de portabilité que le vrai POO et que les choses devraient être allouées statiquement et explicitement plutôt que dynamiquement. Grand merci, cela a beaucoup de sens et explique pourquoi j'ai vu des exemples et ce qui n'est pas écrit comme ils sont.
Andy Braham