Valeur inversée.....

Hello à tous.
Pour situer mon niveau: ben débutant.
mon probléme:
je récupère la valeur d’un codeur que je transforme en angle, cette valeur peut etre relevée dans une variable par l’appui sur un bouton poussoir. Dans ce cas je veux allumer une série de LED plus ou moins éloignée suivant la position du codeur par rapport à la valeur précisée…Hors cela ne fonctionne que lorsque je suis en sens négatif (de 0 à -360 degrés)…
Rien en positif…j’ai cherché un peu mais je ne trouve pas de réponse concrete, ce qui m’ammene à vous exposer cela…
ci-dessous le code (entre balises, note pour les modos :slight_smile: )
Merci à tous!

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 7, 6, 40, 42);

long int pinA = 2;
long int pinB = 3;
long int pos = 0;
int valeur = 0;
int ledG1 = 22;
int ledG = 24;
int ledred = 26;
int ledD = 28;
int ledD1 = 30;
const int entree = A0;
const int sortie = 52 ;
int etatBouton;

const int entreeRaz = 46;
float raz;
int etatBoutonRaz = 0;


void setup()  {
  Serial.begin (9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Angle =");
  lcd.setCursor(2, 1);
  lcd.print("Rel =");

  pinMode(entree, INPUT);
  pinMode(sortie, OUTPUT);
    pinMode(ledG1, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledred, OUTPUT);
  pinMode(ledD, OUTPUT);
    pinMode(ledD1, OUTPUT);
  pinMode(entreeRaz, INPUT);



  pinMode(pinB, INPUT);

  attachInterrupt(0, front, CHANGE);


}

void loop()    {
  float angle  = (pos * 0.0036);
 
  digitalWrite(sortie, HIGH);
  etatBouton = analogRead(entree);
  etatBoutonRaz = digitalRead(entreeRaz);

  //bouton remise a zero
  if (etatBouton == 0)  {

  }
valeur=angle
if (valeur
  //remise a zero apres 360 degre±
  if ( (   angle >= 360) || (   angle <= -360)) {
    pos = 0;
  }

  //Récupération de la valeur de l'angle
  if (etatBoutonRaz == 0)  {
raz = angle;
    valeur = etatBoutonRaz;
     }

    //éclairage progressif position RAZ= valeur centrale
    //led G1
  if (((float)raz > angle * 1.31) && ((float)raz < angle * 1.11))  {
     digitalWrite(ledG1, HIGH);
  }
  else
  {
    digitalWrite(ledG1, LOW);
  }
     //led G
  if (((float)raz > angle * 1.11) && ((float)raz < angle * 1.03))  {
     digitalWrite(ledG, HIGH);
  }
  else
  {
    digitalWrite(ledG, LOW);
  }
  
  // led Rouge
  if (((float)raz > angle * 1.03) && ((float)raz < angle / 1.03))  {
    digitalWrite(ledred, HIGH);
  }
  else
  {
    digitalWrite(ledred, LOW);
  }
  
 //led Droite
  if (((float)raz > angle / 1.03) && ((float)raz< angle / 1.11))  {
     digitalWrite(ledD, HIGH);
  }
  else
  {
     digitalWrite(ledD, LOW);
  }
 //led Droite1
  if (((float)raz > angle / 1.11) && ((float)raz< angle / 1.31))  {
     digitalWrite(ledD1, HIGH);
  }
  else
  {
     digitalWrite(ledD1, LOW);
  }

  lcd.setCursor(9, 0);
  lcd.print(angle);
  lcd.print("   ");
  lcd.setCursor(9, 1);
  lcd.print(raz);
  lcd.print("   ");
}

void front()   {
  long int sA = digitalRead(pinA);
  long int sB = digitalRead(pinB);
  if (sA == sB)   {
    --pos;
  }
  else   {
    ++pos;

  }
}

pas besoin de long int pour un digitalRead... ça retourne 0 ou 1

  long int sA = digitalRead(pinA);
  long int sB = digitalRead(pinB);

la variable pos étant partagé entre les fonctions et l'interruption, elle doit être déclarée volatile et une copie doit être faite dans le code principal en section critique (désactiver les interruption) pour utiliser la copie sinon elle peut changer pendant que ça boucle

comme l'ange c'est pos * 0.0036, pourquoi ne pas faire tous vos test en entier avec pos plutôt qu'en float en utilisant directement la valeur du rotary encoder?

(et je ne suis pas bien sûr de vous suivre dans vos intervalles )

Je pense qu’il y a une erreur ici. Est-ce que ce ne devrait pas être in digitalRead plutôt?

 etatBouton = analogRead(entree);

Je n’ai pas analysé très à fond ton code mais je pense que les tests que tu fais posent problème. Suivant que la valeur de l’angle est positive ou négative les bornes des tests < et > devrait changer. Le plus simple serait de mémoriser le signe et de faire le test sur la valeur absolue. Ensuite en fonction du signe allumer un groupe de LEDs ou l’autre.

fdufnews:
Je pense qu'il y a une erreur ici. Est-ce que ce ne devrait pas être in digitalRead plutôt?

 etatBouton = analogRead(entree);

j’imagine que son bouton A un pullup externe.
C’est pas terrible mais comme le test se fait avec if (etatBouton == 0)  {, la valeur lue sera bien 0 en cas d’appui.

(ce serait intéressant de savoir comment les boutons sont connectés )

Déjà, il y a des erreurs dans le code :

  if (etatBouton == 0)  {

  }
valeur=angle
if (valeur
  //remise a zero apres 360 degre±
  • Rien dans les accolades donc le test ne sert à rien
  • Manque un ;
  • Manque une parenthèse droite

De plus valeur est un entier et angle un float, donc tu vas tronquer le contenu...

Quelles sont les valeurs de 'angle' affichées sur le LCD lorsque tu es en positif ? Sont-elles correctes ?

Hello, merci à tous d'avoir porté un peu d’intérêt....
effectivement j'ai posté le code pendant une modification....donc pas propre du tout.
La valeur est bien en analogique, j'avais au départ modifié l'intensité d'éclairage suivant la position.
JML j'avoue avoir utilisé ce bout de code sans vraiment comprendre l'interruption....
La valeur lue est bien l'angle de +360 à 0 ou de 0 à -360 (remise à zéro a chaque tour complet).
Est ce cette interruption qui me réduit la vitesse de rotation? a chaque fois que je tourne un peu vite les valeures lues débloquent....
bon aller, je continue mon long apprentissage...
Encore merci

Comme vous débutez, ne vous perdez pas avec les interruptions, les volatile etc… utilisez une bibliothèque pour gérer vous encodeur rotatif.

Je vous suggère de prendre celle ci qui est connue pour fonctionner très bien, même à haut débit (téléchargement sur GitHub ici)

testez votre montage avec ce code en ouvrant la console série à 115200 bauds:

// *** DEFINITION DE L'ENCODEUR ROTATIF ***
#include <Encoder.h> // https://www.pjrc.com/teensy/td_libs_Encoder.html
const byte encodeurDTPin = 2; // Encodeur DT
const byte encodeurCLKPin = 3; // Encodeur CLK
Encoder encodeurRotatif(encodeurDTPin, encodeurCLKPin); // attaché sur pins 2 (Encodeur DT) et 3 (Encodeur CLK)

const int clicksParTick = 2; // mon encodeur émet 2 "clicks" par cran/tick 

long valeurCourante = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("PRET !"));
  encodeurRotatif.write(valeurCourante* clicksParTick); // on met le compteur à la valeur par défaut
}

void loop() {
  long nouvelleValeur = encodeurRotatif.read() / clicksParTick; 
  if (nouvelleValeur != valeurCourante) {
    valeurCourante = nouvelleValeur;
    Serial.println(valeurCourante);
  }
}

connectez l’encodeur au 5V et GND et DT sur pin 2 et CLK sur la pin 3

vous devriez voir les valeurs défiler quand vous tournez l’encodeur.

(dans ce code je divise par 2 la valeur de l’encodeur parce que mon encodeur émet 2 clicks par tick. Certains n’en ont qu’un, d’autres 4. à vous de voir comment se comporte le votre)