68tjs:
Sans parler de classes qui occupent plus de place en flash qu'une fonction (on n'est pas dans un PC) il faut simplement autant de "groupes de variables" qu'il y a de Del.
Non non... faut pas croire que les classes c'est quelque chose de gourmand et cher...
Le compilateur est assez fort... Les fonctions prennent la même place, les variables idem... En fait utiliser une classe n'est pas vraiment plus coûteux réellement que d'écrire tout à la main. c'est juste une façon de structurer son code, la protection des variables etc. On peut faire mieux au prix de plus de code manuel et en comprenant bien l'architecture des micro et la théorie de compilation et optimisation....
Par exemple ce code avec une classe LED toute simple qui prend en paramètre le N° de pin et la demi période pour faire clignoter la led
class LED
{
public:
// constructor
LED(const uint8_t aPin, uint32_t demiPeriode) : _pin(aPin), _demiPeriode(demiPeriode) {
pinMode(aPin, OUTPUT);
}
void clignote() {
if (millis() - chrono >= _demiPeriode) {
digitalWrite(_pin, (digitalRead(_pin) == LOW) ? HIGH : LOW);
chrono = millis();
}
}
uint8_t _pin;
uint32_t _demiPeriode;
private:
uint32_t chrono = 0;
};
const uint8_t ledPin1 = 13;
const uint8_t ledPin2 = 12;
LED led1(ledPin1, 100ul);
LED led2(ledPin2, 1000ul);
void setup() {}
void loop() {
led1.clignote();
led2.clignote();
}
ça va occuper 1604 octets de flash et 27 octets de mémoire RAM. Le setup() est réduit à sa plus simple expression et la loop() est super lisible... On comprend bien ce que l'on fait.
la même chose peut être effectuée bien sûr en déclarant les mémoires à la main
const uint8_t ledPin1 = 13;
const uint8_t ledPin2 = 12;
uint32_t demiPeriode1;
uint32_t demiPeriode2;
uint32_t chrono1 = 0;
uint32_t chrono2 = 0;
void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
demiPeriode1 = 200ul;
demiPeriode2 = 1000ul;
}
void loop() {
if (millis() - chrono1 >= demiPeriode1) {
digitalWrite(ledPin1, (digitalRead(ledPin1) == LOW) ? HIGH : LOW);
chrono1 = millis();
}
if (millis() - chrono2 >= demiPeriode2) {
digitalWrite(ledPin2, (digitalRead(ledPin2) == LOW) ? HIGH : LOW);
chrono2 = millis();
}
}
ça va occuper 1710 octets de flash et 25 octets de mémoire RAM et c'est pas top à lire... Les 2 octets de RAM gagnés sont parce que les pins sont constantes et l'optimisateur les a virées.
Dans le cas de la classe, on peut les modifier à l'exécution donc si on voulait être iso-fonctionnel, on déclarerait les pins pas en const
mais en volatile
et on retrouverait nos 27 octets.
--> avantage sur la flash pour l'approche par classe.
ou alors si on est un peu plus smart on part avec une boucle et des tableaux
const uint8_t ledPins[] = {13, 12};
const uint8_t nbLED = sizeof(ledPins) / sizeof(ledPins[0]);
uint32_t demiPeriode[] = {200ul, 1000ul};
uint32_t chrono[] = {0, 0};
void clignote(const uint8_t index)
{
if (millis() - chrono[index] >= demiPeriode[index]) {
digitalWrite(ledPins[index], (digitalRead(ledPins[index]) == LOW) ? HIGH : LOW);
chrono[index] = millis();
}
}
void setup() {
for (byte i = 0; i < nbLED; i++) pinMode(ledPins[i], OUTPUT);
}
void loop() {
for (byte i = 0; i < nbLED; i++) clignote(i);
}
ça va occuper 1564 octets de flash et 27 octets de mémoire RAM
ici on a tout fait à la main et réfléchit aux optimisations, on gagne 40 octets de mémoire flash (à mon avis parce que la fonction clignote() doit être optimisée et mise "inline" et potentiellement les boucles juste répétées car nbLED
est petit et constant)
bref - une classe ce n'est pas abominablement coûteux, c'est même mieux que si on ne code pas très bien sans comprendre ce que fait l'optimiseur de code.