AttachInterrup() et LiquidCrystal_I2C

Bonjour,
Nouvel utilisateur, je me suis lancé dans un projet de télécommande centralisée pour des prises en RF433.
J'ai découpé mon projet en séquence afin de m'approprier chaque élément avant de passer au suivant.
RF433, OK
RTC, OK
Codeur Rotatif avec Switch, OK
LCD branché avec 4 PINs, OK
Tout fonctionnait, et comme je commençais à manquer de PIN, je me suis lancé dans l'I2C pour afficher mes menus sur mon écran 16/02.
Or, depuis que j'ai déclaré l'écran avec la bibliothèque LiquidCrystal_I2C la fonction attachInterrupt ne fonctionne plus.
Soupçonnant des problèmes de branchement je suis revenu en arrière pas à pas, et j'ai écumé les forum sans succès.
Y aurait il une incompatibilité entre I2C et AttachInterrupt ?
J'utilise un UNO R3

AttachInterrupt pour l'encodeur rotatif ?
Sur quelles pins ?
Utilises-tu digitalPinToInterrupt() ?

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)(

Bonjour,
Oui je l'utilise avec le PIN 2 ou 3 correspondant au Interruption de l'UNO.

#define inputCLK 2
....
attachInterrupt(digitalPinToInterrupt(inputCLK), Checkpos, CHANGE);
....
void Checkpos() {
Serial.print("tourne");
  currentStateClk = digitalRead(inputCLK);


  if (currentStateClk == LOW && previousStateClk == HIGH) {
    if (digitalRead(inputDT) != currentStateClk) {
      counter--;
    }
    else {
      counter++;
    }
  }

  previousStateClk = currentStateClk;
  affichage();


}

Mon code fonctionnait jusqu'à présent avec l'écran en 4 broches.
J'ai mis des balises pour voir à quel moment du programme cela coinçait, et ma balise "tourne" ne s'affiche même pas.

hello
il n’y a aucune raison pour que tu aies des problèmes suite à ta manip
mais sans prg et sans schéma sans savoir quelle platine …
bref sans renseignements…

autrement, j’ai revu ton bout de code

#define inputCLK 2
pinMode inputCLK,INPUT; //voir si INPUT_PULLUP si l'encodeur est en collecteur ouvert par exemple
attachInterrupt(digitalPinToInterrupt(inputCLK), Checkpos, RISING); //interruption sur flanc montant
....
void Checkpos()                      //si le prg vient dans cette fonction, c'est sur un flanc montant
{
  if (digitalRead(inputDT))          //si l'autre voie du codeur est à HIGH
  {
    counter--;                       //alors on décompte
  }
  else                               // sinon
  {
    counter++;                       //on compte
  }
}
la fonction Affiche(); n'a rien à faire dans la fonction d'interruption
il faut l'appeler dans la boucle par exemple 
sur un test de changement de la valeur du compteur

Bonjour,
Apparement, il y a incompatibilité. :confused:
Je n'avais pas bien écumé les forum. En étudiant, la bibliothèque sur GitHub, j'ai trouvé ce lien.
https://forum.arduino.cc/index.php?topic=140588.0 Post de bperrybap
La réponse est longue mais laisse penser qu'il peut y avoir des incompatibilités. Je penche pour une ré-rentrée de données qui bloque avec la séquence de l'I2C. Lorsque l'on tourne le rotateur qui est très sensible, la fonction Interrupt traite les premières informations, lance l'affichage et pendant ce temps, un autre ordre interrupt est reçu et le tout se fige.
Je penche pour cette raison car certaines de mes balises de débugage (en texte) étaient incomplètes via le port série.

Après, j'ai une version chinoise de mon UNO R3.
Il se peut que cela ne soit pas reproductible sur toutes les platines.

J'ai réintégré la gestion du codeur rotatif dans le voice loop et cela fonctionne. Le pas à pas, il n'y a rien de tel.
En espérant que ma petite mésaventure pourra servir.
Si toutefois quelqu'un a déjà réussi, je serais fanas pour une explication.
Merci pour vos réponses.

tu es en train de nous dire que ta fonction interrupt commencait à exécuter la fonction affichage et qu'une nouvelle interruption arrive et que ça mets le binz.

un traitement d'interruption doit être le plus court possible.
c'est pourquoi je t'ai modifié ton code et signalé que la fonction affichage n'avait pas sa place à cet endroit.
tu nous dis que tu as rusé en traitant le codeur dans la loop.
tu peux louper des signaux.

tu aurais du tester la modif de ton code

bonjour dfgh,
C'est exactement cela. J'étais en train de poster que ton conseil de sortir affiche() m'a éclairé sur cette erreur. Hélas ce n'est pas un Chat, donc mon post n'est pas parti.
Je vais retenter en sortant affiche(), et je posterai mes résultats.

Sinon dans la version loop, je " loupe " peut être des informations. Mais, comme les menus qui sont changés par le codeur sont cycliques, ce n'est pas grave.

La connaissance ne vaut que si elle est partagée.
Avant le confinement, je ne savais pas ce que c'était qu'un Arduino.

Merci à toi,

Finalement, en sortant la fonction qui gère l'affichage de l'attachInterrupt cela fonctionne. Les menus déroulants s'affichent via l'I2C.
Néanmoins, ce n'est pas l'idéal. La fonction AttacheInterrupt prenant le pas sur tout autre processus, cela génère des arrêts de la fonction Loop ou un trop grand nombre de changement que l'I2C ne parvient pas à traiter à temps. Il faut tourner le codeur rotatif tout doucement pour faire afficher les menus sur l'écran, sinon l'affichage via I2C ne se fait pas.
Comme la fonction delay est inopérante pendant une phase d'attachInterrupt, cela revient à faire du porte à porte en formule1.

Par ailleurs, avec la programmation du codeur rotatif dans la void Loop, il n'y a pas de blocage et le déroulement des menus est plus fluide.

Merci à tous les deux, vos questions et remarques m'ont permis de comprendre les relations entre AttachInterrupt et le reste de la boucle ainsi que le fonctionnement de l'I2C.

Dernier question pour dfhg, j'ai vu que tu avais changé le code et que tu utilisais le front montant de l'impulsion pour déclencher AttachInterrupt(). Je n'arrive pas encore à comprendre dans quelle situation il faut utiliser RISING, FALLING ou CHANGE ? J'imagine que RISING et FALLING dépendent de l'état initiale de la broche 2 ou 3 ?

oui,
FALLING: est un flanc descendant ( mouvement de HIGH vers LOW )
RISING est un flanc montant ( mouvement de LOW vers HIGH )
CHANGE est un changement de niveau ( niveau HIGH ou niveau LOW )

sur un CHANGE, tu ne sais pas si le signal est HIGH ou LOW, c'est ce qui t'obligeait, après être entré dans la fonction d'interruption à lire la voie A, puis la voie B

en prenant FALLING, tu sais en entrant dans la fonction d'interruption que la voie A est LOW il ne te reste plus qu'à lire la voie B. et à incrémenter ou décrémenter le compteur.
ta fonction d'interruption s'en trouve très courte.

même raisonnement en prenant RISING

si tu regardes la voie B en te déplacant de gauche à droite, tu voies qu'au moment du falling, la voie A est à un niveau LOW
inversement, si tu suis la voie B en te déplacant de droite à gauche, au moment du falling, la voie A est à HIGH

https://www.google.com/search?q=codeur+incremental&client=firefox-b-d&tbm=isch&source=iu&ictx=1&fir=B-nkEhWJsgZFdM%2C2mTuN0EbNaBB6M%2C_&vet=1&usg=AI4_-kSwCNwx2ffPK8UZM1y-cU5hBnVq2g&sa=X&ved=2ahUKEwjC9NzNgZvqAhVN6RoKHYd2CUoQ9QEwA3oECAMQGg&biw=1597&bih=960#imgrc=9e_fsvgaale5EM

désolé, je n'ai pas brillé avec l'insertion d'image