Exercice : Commande d'une pompe
Simulateur

Cet exercice est à réaliser avec le simulateur en ligne Wokwi
Description et fonctionnement
On souhaite réaliser l'automatisation d'une pompe munie de deux capteurs de niveau utilisée pour maintenir un niveau bas de liquide dans une cuve. Le fonctionnement est résumé ainsi lorsque le niveau de liquide monte dans la cuve :
tant que le niveau est bas dans la cuve (c'est-à-dire inférieur au capteur bas), la pompe est à l'arrêt,
lorsque le niveau haut est atteint, la pompe se met en marche,
tant que le niveau est au-dessus du niveau bas, la pompe fonctionne
dès que le niveau passe en dessous du capteur bas, la pompe s'arrête

Implantation dans le simulateur
Question
Créez et testez une classe Sensor
composée de :
deux variables membres privées :
pinNumber
qui stockera le numéro du port sur lequel le capteur sera branchéstate
qui stockera l'état du capteur
un constructeur avec paramètre pour initialiser l'objet avec le numéro de port
un accesseur de lecture pour renvoyer l'état du capteur
Question
Créez et testez une classe Pump
composée de :
deux variables membres privées :
pinNumber
qui stockera le numéro du port sur lequel la LED, qui simule la pompe, sera branchéestate
qui stockera l'état de la pompe
un constructeur avec paramètre pour initialiser l'objet avec le numéro de port et mettre la pompe à l'arrêt,
un accesseur d'écriture pour fixer l'état de la pompe
un accesseur de lecture pour renvoyer l'état de la pompe
Question
Proposez une solution répondant au cahier des charges
Solution
//Déclaration des classes
class Sensor{ //capteur
private:
byte pinNumber;
bool state;
public:
Sensor(int);
bool getState();
};
class Pump{
private:
byte pinNumber;
bool state;
public:
Pump(int);
void setState(bool);
bool getState();
};
// Programme principal
Sensor sensorHaut(CAPTEUR_HAUT);
Sensor sensorBas(CAPTEUR_BAS);
Pump pump(POMPE);
void setup(){
}
void loop()
{
/*On teste l'état des capteurs et de la pompe :
- si les deux capteurs sont activés et que la pompe était à l'arrêt, on la met en marche
- si la pompe est activée et que le capteur bas n'est plus activé, on arrête la pompe
*/
if(sensorHaut.getState() && sensorBas.getState() && !pump.getState()){
pump.setState(HIGH);
}
if(pump.getState() && !sensorBas.getState()){
pump.setState(LOW);
}
}
// Objets : définition des fonctions membres
Sensor::Sensor(int pin){ //Constructeur
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
};
bool Sensor::getState(){ //permet d'obtenir l'état d'un capteur
state=digitalRead(pinNumber);
return(state);
};
Pump::Pump(int pin){ //Constructeur
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber,LOW);
};
void Pump::setState(bool state){//Fixe l'état de la pompe
this->state = state;
digitalWrite(pinNumber,this->state);
};
bool Pump::getState(){//permet d'obtenir l'état de la pomp
return(this->state);
}
Héritage de classe : ajout d'une temporisation
On souhaite maintenant améliorer le fonctionnement de la pompe tout en gardant la classe initiale. L'amélioration consiste à ajouter une temporisation réglable lorsque la pompe passe de l'état « en marche » à l'état « à l'arrêt ».
Question
Créez une nouvelle classe qui héritera de la classe Pump
et qui intégrera la nouvelle fonctionnalité.
Solution
Cet exemple permet de mettre en place un héritage de classe : la nouvelle classe PumpTemp hérite de la classe Pump. Elle ne fait que modifier la fonction membre setState() à laquelle on ajoute une temporisation dans le cas où on demande l'arrêt de la pompe. Cela permet de garder le même programme principal à l'exception près de la création de l'objet pump qui fait maintenant référence à la classe PumpTemp (ligne PumpTemp pump(POMPE);)
class Sensor{
private:
byte pinNumber;
bool state;
public:
Sensor(int);
bool getState();
};
class Pump{
protected:
byte pinNumber;
bool state;
public:
Pump(int);
void setState(bool);
bool getState();
};
//Héritage de la classe Pump avec ajout d'une tempo à l'arrêt de la pompe
class PumpTemp : public Pump{
public:
PumpTemp(int);
void setState(bool);
};
/* Programme principal */
Sensor sensorHaut(CAPTEUR_HAUT);
Sensor sensorBas(CAPTEUR_BAS);
PumpTemp pump(POMPE);
void setup()
{
}
void loop()
{
if(sensorHaut.getState() && sensorBas.getState() && !pump.getState()){
pump.setState(HIGH);
}
if(pump.getState() && !sensorBas.getState()){
pump.setState(LOW);
}
}
/* Objets */
Sensor::Sensor(int pin){
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
};
bool Sensor::getState(){
state=digitalRead(pinNumber);
return(state);
};
Pump::Pump(int pin){
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber,LOW);
};
void Pump::setState(bool state){
this->state = state;
digitalWrite(pinNumber,this->state);
};
bool Pump::getState(){
return(this->state);
};
PumpTemp::PumpTemp(int pin) : Pump(pin){
};
void PumpTemp::setState(bool state){
//si on demande extinction, on temporise
//Extinction : état demandé = 0, ancien état = 1
if(state == LOW && this->state == HIGH){
//Temporisation
delay(3000);
}
Pump::setState(state);
};
Héritage de classe : commandes on/off
Il s'agit maintenant de revoir la manière de fonctionner de la pompe : plutôt que de fixer le fonctionnement par un état logique dans le programme principal, il est demandé de mettre en place des fonctions plus explicites de mise en marche, setPumpOn()
et mise à l'arrêt setPumpOff()
: une nouvelle classe PumpOnOff
sera créée.
Question
Créez et testez la nouvelle classe PumpOnOff
Solution
/*
Commande pompe à 2 capteurs
Intégre les fonctions setPumpOn et setPumpOff
*/
class Sensor{
private:
byte pinNumber;
bool state;
public:
Sensor(int);
bool getState();
};
class Pump{
protected:
byte pinNumber;
bool state;
public:
Pump(int);
void setState(bool);
bool getState();
};
//Héritage de la classe Pump avec ajout d'une tempo à l'arrêt de la pompe
class PumpTemp : public Pump{
public:
PumpTemp(int);
void setState(bool);
};
/* Programme principal */
Sensor sensorHaut(CAPTEUR_HAUT);
Sensor sensorBas(CAPTEUR_BAS);
PumpTemp pump(POMPE);
void setup()
{
}
void loop()
{
if(sensorHaut.getState() && sensorBas.getState() && !pump.getState()){
pump.setState(HIGH);
}
if(pump.getState() && !sensorBas.getState()){
pump.setState(LOW);
}
}
/* Objets */
Sensor::Sensor(int pin){
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
};
bool Sensor::getState(){
state=digitalRead(pinNumber);
return(state);
};
Pump::Pump(int pin){
pinNumber = pin;
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber,LOW);
};
void Pump::setState(bool state){
this->state = state;
digitalWrite(pinNumber,this->state);
};
bool Pump::getState(){
return(this->state);
};
PumpTemp::PumpTemp(int pin) : Pump(pin){
};
void PumpTemp::setState(bool state){
//si on demande extinction, on temporise
//Extinction : état demandé = 0, ancien état = 1
if(state == LOW && this->state == HIGH){
//Temporisation
delay(3000);
}
Pump::setState(state);
};