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);
74HC165
74HC595
D0D1D2D3D4D5D6D7GNDLOGIC