class CStateMachineRotary //déclaration de la classe
{
public:
...
void setPosition(int newposition)//méthode manipulateur pour modifier à l'attribut privé position
{ position=newposition;} //on parle de méthode inlinée car l'implémentation est faite dans la déclaration de la classe
...
};
loop(...){
...
unsigned int periodiciteTache3=10000; //10s
static unsigned long timerTache3 = millis();
if (millis() - timerTache3 >= periodiciteTache3) {
timerTache3 += periodiciteTache3;
encoder1.setPosition(encoder1.getPosition()+4);
}
....
}
Solution complète en vrac fourni pour le td en distanciel
solurot.ino
////////////////////////////////////////////////////////////////////
class CStateMachineRotary //déclaration de la classe
{
public: //membres accessibles depuis l'extérieur de la classe, il s'agit de l'interface d'interaction de la classe
CStateMachineRotary(int brocheAinit, int brocheBinit); //Constructeur avec paramètres pour régler les 2 broches Arduino utilisées
void clock(); //méthode pour cadencer la machine à état (faire 1 coup d'horloge)
int getPosition()//méthode accesseur pour accéder à l'attribut privé position
{ return position;} //on parle de méthode inlinée car l'implémentation est faite dans la déclaration de la classe
private: //membres privés pour réaliser l'encapsulation: ces attributs sont inacessibles directement depuis l'extérieur de la classe
byte etat; //numéro de l'état actif
byte entreeA; //valeur lue sur l'entrée A
byte entreeB; //valeur lue sur l'entrée B
int brocheA; //numéro de broche Arduino utilisée pour l'entrée A
int brocheB; //numéro de broche Arduino utilisée pour l'entrée B
virtual void frontDetecte(){}; //methode abstraite, sera implémentée dans la classe fille
virtual void actionSurTousLesEtats(){}; //methode abstraite, sera implémentée dans la classe fille
protected: //ces membres peuvent être accédés dans les classes filles
int position; //position angulaire mesurée
}; //ne pas oublier le ;
////////////////////////////////////////////////////////////////////
class CStateMachineRotaryWithSpeed: public CStateMachineRotary
{
public:
CStateMachineRotaryWithSpeed(int brocheAinit, int brocheBinit);
float getSpeed(); //méthode accesseur pour accéder à l'attribut privé speed
private:
float speed; //vitesse mesurée
unsigned long lastPulseTime; //horodatage du dernier front
void frontDetecte(); //implémentation pour effectuer des traitements lorsqu'un front est detecté
};
////////////////////////////////////////////////////////////////////
//TODO par les étudiants CStateMachineRotaryWithSpeedAndReset
//hérite de CStateMachineRotaryWithSpeed et
//ajoute une broche pour la remise à zero de position dans n'importe quel état
class CStateMachineRotaryWithSpeedAndReset: public CStateMachineRotaryWithSpeed
{
public:
CStateMachineRotaryWithSpeedAndReset(int brocheAinit, int brocheBinit,int brocheRinit); //Ce constructeur dispose d'un paramètre supplémentaire pour configurer la broche utilisée pour le bouton
private:
int brocheR; //un nouvel attribut pour stocker le numéro de la broche servant au reset
void actionSurTousLesEtats(); //implémentation de la méthode permettant de gérer l'action "appui sur le bouton reset" indépendamment de l'état courant de la machine à état
};
////////////////////////////////////////////////////////////////////
CStateMachineRotaryWithSpeedAndReset::CStateMachineRotaryWithSpeedAndReset(int brocheAinit, int brocheBinit,int brocheRinit): CStateMachineRotaryWithSpeed(brocheAinit, brocheBinit){
brocheR=brocheRinit;
pinMode(brocheR,INPUT_PULLUP);
}
////////////////////////////////////////////////////////////////////
void CStateMachineRotaryWithSpeedAndReset::actionSurTousLesEtats(){
if (digitalRead(brocheR)==0){ //ici on dévie légèrement du modèle de la machine à état car il faudrait idéalement avoir lue cette entrée en même temps que les autres à l'étape lecture des entrées
position=0;
//Serial.println("raz position");
}
}
////////////////////////////////////////////////////////////////////
//Implémentation du constructeur de la classe fille, exécutée après avoir exécuté le constructeur de la classe mère
CStateMachineRotaryWithSpeed::CStateMachineRotaryWithSpeed(int brocheAinit, int brocheBinit): CStateMachineRotary(brocheAinit, brocheBinit){
lastPulseTime=micros(); //initialisation de la date initiale pour l'horodatage des fronts
}
////////////////////////////////////////////////////////////////////
//implémentation de la méthode frontDetecte() qui n'était pas implémentée dans la classe mère
void CStateMachineRotaryWithSpeed::frontDetecte()
{
unsigned long newPulseTime=micros();
speed=1000000./(newPulseTime-lastPulseTime);
/*Serial.print("ici ");
Serial.print(lastPulseTime);
Serial.print(" ");
Serial.print(newPulseTime);
Serial.print(" ");
Serial.print(speed);
Serial.println(" ");
*/
lastPulseTime=newPulseTime;
}
////////////////////////////////////////////////////////////////////
//implémentation de la mesure de vitesse
float CStateMachineRotaryWithSpeed::getSpeed(){
unsigned long newTime=micros();
//TODO donner un signe à la vitesse en fonction du sens de rotation
if((newTime-lastPulseTime)>4000000)
speed=0; //vitesse=0 si mise à jour de la vitesse depuis plus de 4 secondes TODO: faire dépendre ce délai de la vitesse en cours...
return speed;
}
////////////////////////////////////////////////////////////////////
//Implémentation de la méthode constructeur
CStateMachineRotary::CStateMachineRotary(int brocheAinit, int brocheBinit){
brocheA=brocheAinit;
brocheB=brocheBinit;
pinMode(brocheA,INPUT);
pinMode(brocheB,INPUT);
entreeA=digitalRead(brocheA);
entreeB=digitalRead(brocheB);
etat=0;
position=0;
}
////////////////////////////////////////////////////////////////////
//Implémentation de la méthode clock
void CStateMachineRotary::clock(){
//lecture et mémorisation des entrées
entreeA=digitalRead(brocheA);
entreeB=digitalRead(brocheB);
//actions sur transition
if ((etat==0) && (entreeA==1)){
frontDetecte();
position++;
}
if ((etat==1) && (entreeA==0)){
frontDetecte();
position--;
}
//évolution de l'état (veiller à ne pas retester etat après l'avoir changé, sinon passer par une variable temporaire)
//byte ancienetat=etat;
switch (etat){
case 0: if (entreeA==1)
etat=1;
else if (entreeB==1)
etat=3;
break;
case 1: if (entreeB==1)
etat=2;
else if (entreeA==0)
etat=0;
break;
case 2: if (entreeA==0)
etat=3;
else if (entreeB==0)
etat=1;
break;
default:
case 3: if (entreeB==0)
etat=0;
else if (entreeA==1)
etat=2;
break;
}
/*if (ancienetat!=etat){
Serial.print("e");
Serial.println(etat);
}
*/
//actions sur état
actionSurTousLesEtats();
}
//CStateMachineRotaryWithSpeed encoder1(A4,A5);
CStateMachineRotaryWithSpeedAndReset encoder1(A4,A5,A1);