Arduino uno - verification programme => mesure angle

Salut à tous,

je débute totalement et je suis en train de creer une serie de programmes qui à terme se retrouverons fusionnés dans une interface sous processing.

aujourd'hui j'ai fait un programme qui mesure un angle sur une plage bien precise, je m'explique.

j'ai un arbre tournant qui comprend 4 cames et qui actionne un seul et unique interrupteur.
j'ai 8 plages parcourues par l'interrupteur, la premiere desactive l'interrupteur, la suivante l'active, etc etc ...
et j'ai besoin de connaitre l'angle des 4 plages qui desactives l'interrupteur.
à savoir :
plage 1 : x°
plage 2 : x°
plage 3 : x°
plage 4 : x°

pour cela j'ai donc créé un programme qui compte le temps où l'interrupteur est ouvert ou fermé sur chaque plages.
j'additionne tout ces temps et ce total est équivalent à 360°
et donc, si je veux connaitre l'angle d'une plage je fais une règle de 3 (c'est le cas de la plage n°2 que j'observe)

vu que je ne suis pas faignant j'ai tenté ce programme de moi meme sachant que ça ne fait que 3 jours que je suis sur ce language.

je post ce programme ici pour que vous me disiez si il y a plus simple, si il est optimisé où si j'ai des erreurs.

le programme semble fonctionner, ma crainte c'est que je ne suis pas certain qu'il ne faille pas un interrupt ou un truc du genre pour être certain que le programme attente l'etat suivant afin de correctement comptabiliser le temps total sur un tour d'arbre

j’espère que je suis clair, je suis très à l'ecoute
merci d'avance :wink:

const byte PIN_SIGNAL = 2;
int buttonState = 0;
int lastButtonState = 0;
long temps_total = 0;
int angle2 = 0;
const int angle_total = 360;
long p1 = 0;
long p2 = 0;
long p3 = 0;
long p4 = 0;
long p5 = 0;
long p6 = 0;
long p7 = 0;
long p8 = 0;

/** Fonction setup() */
void setup() {
   /* Initialise le port série */
 Serial.begin(115200);
   /* Met la broche en entrée */  
 pinMode(PIN_SIGNAL, OUTPUT);
}


/** Fonction loop() */
void loop() {
// lit l'état actuel du bouton poussoir et le mémorise dans la variable
 buttonState = digitalRead(PIN_SIGNAL);

 // compare l'état actuel du bouton poussoir à l'état précédent mémorisé
 if (buttonState != lastButtonState) {  

 /* Mesure la durée de la période */
p1 = pulseIn(PIN_SIGNAL, LOW);
 Serial.print("p1: ");
      Serial.println(p1);

   if (buttonState != lastButtonState){
p2 = pulseIn(PIN_SIGNAL, HIGH);
    Serial.print("p2: ");
   Serial.println(p2);}

      if (buttonState != lastButtonState){
p3 = pulseIn(PIN_SIGNAL, LOW);
    Serial.print("p3: ");
   Serial.println(p3);}

      if (buttonState != lastButtonState){
p4 = pulseIn(PIN_SIGNAL, HIGH);
    Serial.print("p4: ");
   Serial.println(p4);}

    if (buttonState != lastButtonState){
p5 = pulseIn(PIN_SIGNAL, LOW);
    Serial.print("p5: ");
   Serial.println(p5);}

    if (buttonState != lastButtonState){
p6 = pulseIn(PIN_SIGNAL, HIGH);
    Serial.print("p6: ");
   Serial.println(p6);}

    if (buttonState != lastButtonState){
p7 = pulseIn(PIN_SIGNAL, LOW);
    Serial.print("p7: ");
   Serial.println(p7);}

    if (buttonState != lastButtonState){
p8 = pulseIn(PIN_SIGNAL, HIGH);
    Serial.print("p8: ");
   Serial.println(p8);}

//affiche le temps total
  temps_total = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
  Serial.print("temps total: ");
       Serial.println(temps_total);

//affiche l'angle inter fermé
     angle2 = (p2 * angle_total) / (temps_total) ;
     Serial.print("angle 2: ");
       Serial.println(angle2);
     }
  

delay(100);
 }

Merci d'utiliser les tags de code pour poster du code

Évitez les appels à delay() et les print() intempestifs qui ralentissent vos mesures

pulseIn() va sans doute rater un tick sur deux. En effet Par exemple, si le premier appel a pour paramètre LOW, l'instruction pulseIn() attend que la broche passe à LOW, commence alors le chronométrage, attend que la broche repasse au niveau HIGH et stoppe alors le chronométrage. La fois suivante vous demandez alors de mesurer la partie HIGH mais comme la broche est déjà HIGH il va falloir attendre qu'elle retombe, un cycle LOW puis mesurer le prochain HIGH

Il serait sans doute préférable d'utiliser une interruption et de compter le temps entre deux fronts montant ou descendant.

Super, merci pour vos réponses, j'ai modifié mon post pour utiliser les tags.

je savais qu'il y avait un loup ... du coup il faut bel et bien que j'utilise l'interruption, fonction avec laquelle j'ai du mal mais je vais la creuser.

pour les println c'est du temporaire, ça va passer sous processing à terme avec uniquement un affichage des angles LOW

compter le temps entre 2 fronts montants me parait pas mal, ça se fait avec la fonction interrupt c'est bien ça ? il faut le millis aussi ?
par contre il me faut bien 8 signaux sur une rotation complete pour avoir mon 360° et mon temps total, ça va le faire avec les 2 fonctions citées ?

bref, là vous m'avez paumé :smiley: faut que je me replonge dans tout ça et repartir de zéro

PS : je n'ai pas encore mis de resistance pullup sur mon cablage, je m'en chargerais plus tard.

merci encore

punaise je suis perdu :frowning:

j'ai fait pas mal de recherches, j'ai aussi cherché/trouvé des dolipranes :smiley:
mais ça c'est normal au debut.

avec le attachinterrupt je suis perdu, c'est du trop haut niveau pour moi je pense ....
je n'arrive meme pas à faire un simple programme pour comprendre la fonction, enfin si mais je ne fais pas encore ce que je veux

dans le cas de mon programme d'angle sur 8 pistes, est-ce qu'il me faut 2 ou 4 attachinterrupt ?

enfin bref là pour l'instant je nage, est-ce que vous pourriez me donner un debut de piste ?

merci

Une seule interruption, déclenchée sur un changement de valeur (transition high vers low ou low vers high)

Ce code d'exemple standard fait clignoter la led de la carte à chaque front

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state; // inverse l'état à chaque CHANGEment de valeur de la pin 2
}

genial, merci, j'etudie ça !

petit test ce matin avec un banc qui fait tourner mon arbre equipé d'un tachymetre deporté.

ça fonctionne !!
mais j'ai des sauts ... comme si il manquait la resistance de pull up ??

idem comme le post sur le compte tour

j'affiche bien les 4 angles qui sont corrects car verifiés par un autre moyen, c'est à dire :
54
54
54
53

et au bout de quelques mesures ça affiche
63
0
72
60

puis ça revient à
54
54
54
53

et cela pendant 5 ou 6 affichages

c'est un soucis de filtre ou de parasites ?

merci

zoilgust:
... c'est un soucis de filtre ou de parasites ? ...

Cela se peut. Des parasites (faux rebonds) peuvent être pris en compte : faire un léger filtrage du signal.

Par ailleurs, pour les supers connaisseurs des interruptions matérielles des Arduino.

Si on a paramétré une interruption avec l'option "CHANGE", que se passe-t-il si un changement n'est pas pris en compte (par exemple un parasite de courte durée dont seul le front de départ serait vu). L'entrée "interruption" voit alors consécutivement deux fronts identiques. Comment l'Arduino réagit-il ?

Autrement dit, est-ce que suite à un "parasite", l'interruption va-t-elle se mettre a compter l'espace entre un front montant suivi d'un front descendant plutôt que l'inverse.

Cordialement.

Pierre

surtout pour ce programme pour lequel je n'utilise pas encore d'interruptions

il a le merite de fonctionner ainsi et c'est mon premier programme fait tout seul, mais une optimisation est necessaire à coup sûr

ChPr:
Cela se peut. Des parasites (faux rebonds) peuvent être pris en compte : faire un léger filtrage du signal.

Par ailleurs, pour les supers connaisseurs des interruptions matérielles des Arduino.

Si on a paramétré une interruption avec l'option "CHANGE", que se passe-t-il si un changement n'est pas pris en compte (par exemple un parasite de courte durée dont seul le front de départ serait vu). L'entrée "interruption" voit alors consécutivement deux fronts identiques. Comment l'Arduino réagit-il ?

Autrement dit, est-ce que suite à un "parasite", l'interruption va-t-elle se mettre a compter l'espace entre un front montant suivi d'un front descendant plutôt que l'inverse.

Cordialement.

Pierre

du coup j'ai regardé le sujet de l'anti-rebond et du pull-up

il semble que l'arduino a une resistance, interne

de mon coté j'utilise une CH340 pour mes essais, pourquoi ?
simplement parce que je me suis foiré quelques fois et que j'ai grillé quelques arduino, du coup pour mes essais je prend des ch340

pour la ch340 ce serait sur la borne 6 ?

egalement, concernant le filtre anti-rebond, j'ai vu qu'il fallait un condensateur de 10nf

mais ... c'est quoi la difference entre les 2 :

http://www.conrad.fr/ce/fr/product/1235247/Condensateur-polyester-Kemet-R82EC2100AA50K-10-nF-100-V-10-Pas-5-mm-L-x-l-x-h-72-x-25-mm-x-65-mm-1-pcs?ref=searchDetail

http://www.conrad.fr/ce/fr/product/1279954/Condensateur-anti-parasite-X2-Wuerth-Elektronik-890324023006CS-10-nF-275-VAC-10-Pas-10-mm-L-x-l-x-h-13-x-5-x-11-mm?ref=searchDetail

zoilgust:
de mon coté j'utilise une CH340 pour mes essais, pourquoi ?
simplement parce que je me suis foiré quelques fois et que j'ai grillé quelques arduino, du coup pour mes essais je prend des ch340

pour la ch340 ce serait sur la borne 6 ?

Bonsoir
Je ne sais pas ce que essaie d'expliquer là
Mais sur le fait ce soit un "arduino" dont la gestion USB/UART est faite par un 8U2/16U2/FTDI/CH340/CPI202/autres
ça n'influe en rien sur le fait sur le fait que les I/O du MCU restent identiques.

Si tu a "grillé des arduino" , la proba que ça viennent des # USB/UART est "excessivement minime" :grin:

Pose toi plutôt des questions sur les manips faites par/au travers de l'interface "chaise/clavier" chez toi ! :grin:

zoilgust:
... egalement, concernant le filtre anti-rebond, j'ai vu qu'il fallait un condensateur de 10nf ...

Faites le montage décrit sur le schéma ci-joint. Une capacité de 4.7 ou 10 nF convient bien. Pour cette application, n'importe quel type de condensateur convient. Ce qu'il faut, c'est qu'il soit bien au plus près des bornes de l'Arduino.

Cordialement.

Pierre

merci de me suivre ici egalement :wink:

Merci ChPr, je regarde ça

@Artouste
j'ai grillé des arduino sur un autre type de montage il y a quelques mois, le soucis se situait sur des retours de masse (simulateur de jeu de voiture avec siege mobile, tres connu)

j'ai modifié mon montage pour isoler volant et pedalier du reste et plus de soucis

mais oui, tu as raison, le probleme se situe souvent entre le siege et la souris !!

merci pour ta reponse

PUNAISE que je me tire les ch'veux à tenter de re-traduire ce programme avec des attachinterrupt ....

la vache ! me manque une case de connaissance là !!

je n'arrive pas à concretiser ce que je souhaite faire en langage C...

revoilà l'explication avec des pieces d'allumeur :smiley:
et voilà l'image de ce que je dois mesurer

ce sont les angles pendant lequel l'inter est ouvert et fermé

je n'ai besoin de connaitre que les 4 angles de fermeture

OUI, mais pour avoir ces angles il faut :

  • que je compte le temps total de chaque interruption sur un seul tour (les FALLING et RISING)
  • ça me donne 4 FALLING et 4 RISING
  • j'additionne tous ces temps d'interruption et ça me donne une équivalence de 360°
  • ensuite je fais une regle de 3 pour avoir chaque FALLING converti en angle

facile hein 8) ;D

c'est exactement ce que me fait le programme que j'ai fait tout seul comme un grand :roll_eyes:
sisi .... mais c'est tres scolaire, et de ce qu'on me dit => il n'est pas certain que tous les pulsin soient pris en compte, ok, je modifie (enfin j'essaye)

pourtant ce programme à fonctionné à l'exception près des parasites (filtre anti rebond absent)
de temps en temps j'avais des aberations

je le remet tout en bas, ok, j'affiche trop de choses pour l'instant dans le moniteur => je vais en virer
il manque les commentaires, mais c'est tellement simple qu'a votre niveau ce ne sera pas un problème je pense :wink:

bref je me dis donc que je vais transformer tout ça avec des attachinterrupt .... ok :cry:

alors ... je fais 2 attachinterrupt que je boucle le temps d'avoir 4 FALLING et 4 RISING ?
ou alors 8 attachinterrupt ?

me faut absolument un tour complet pour avoir le temps total et le comparer aux FALLING

c'est peut être d'un niveau trop élevé pour moi à cet instant, je continue les cours mais rien de ce que je souhaite faire ne semble ressortir dans ces cours :frowning:

j'ai pourtant trouvé un exemple ou il y avait plusieurs attachinterrupt et qui me semble pas mal
voir le dernier code :
http://www.locoduino.org/spip.php?article64

programme créé qui fonctionne

const byte PIN_SIGNAL = 2;
int buttonState = 0;
int lastButtonState = 0;
long temps_total = 0;
int angle2 = 0;
int angle4 = 0;
int angle6 = 0;
int angle8 = 0;
const int angle_total = 360;
long p1 = 0;
long p2 = 0;
long p3 = 0;
long p4 = 0;
long p5 = 0;
long p6 = 0;
long p7 = 0;
long p8 = 0;

/** Fonction setup() */
void setup() {
    /* Initialise le port série */
  Serial.begin(115200);
    /* Met la broche en entrée */  
  pinMode(PIN_SIGNAL, OUTPUT);
}


/** Fonction loop() */
void loop() {
 // lit l'état actuel du bouton poussoir et le mémorise dans la variable
  buttonState = digitalRead(PIN_SIGNAL);
  // compare l'état actuel du bouton poussoir à l'état précédent mémorisé
  if (buttonState != lastButtonState) {  
  /* Mesure la durée de la période */
p1 = pulseIn(PIN_SIGNAL, LOW);
  Serial.print("p1: ");
       Serial.println(p1);
       
    if (buttonState != lastButtonState){
p2 = pulseIn(PIN_SIGNAL, HIGH);
     Serial.print("p2: ");
    Serial.println(p2);}
    
       if (buttonState != lastButtonState){
    p3 = pulseIn(PIN_SIGNAL, LOW);
     Serial.print("p3: ");
    Serial.println(p3);}
    
       if (buttonState != lastButtonState){
    p4 = pulseIn(PIN_SIGNAL, HIGH);
     Serial.print("p4: ");
    Serial.println(p4);}
    
     if (buttonState != lastButtonState){
  p5 = pulseIn(PIN_SIGNAL, LOW);
     Serial.print("p5: ");
    Serial.println(p5);}
    
     if (buttonState != lastButtonState){
  p6 = pulseIn(PIN_SIGNAL, HIGH);
     Serial.print("p6: ");
    Serial.println(p6);}
    
     if (buttonState != lastButtonState){
  p7 = pulseIn(PIN_SIGNAL, LOW);
     Serial.print("p7: ");
    Serial.println(p7);}
    
     if (buttonState != lastButtonState){
   p8 = pulseIn(PIN_SIGNAL, HIGH);
     Serial.print("p8: ");
    Serial.println(p8);}
    
    // affiche le temps total
   temps_total = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
   Serial.print("temps total: ");
        Serial.println(temps_total);
        
    // affiche l'angle inter fermé
      angle2 = (p2 * angle_total) / (temps_total) ;
      Serial.print("angle 2: ");
        Serial.println(angle2);

         // affiche l'angle inter fermé
      angle4 = (p4 * angle_total) / (temps_total) ;
      Serial.print("angle 4: ");
        Serial.println(angle4);

         // affiche l'angle inter fermé
      angle6 = (p6 * angle_total) / (temps_total) ;
      Serial.print("angle 6: ");
        Serial.println(angle6);

         // affiche l'angle inter fermé
      angle8 = (p8 * angle_total) / (temps_total) ;
      Serial.print("angle 8: ");
        Serial.println(angle8);
      }
   
 

  }

zoilgust:
PUNAISE que je me tire les ch'veux à tenter de re-traduire ce programme avec des attachinterrupt ....

la vache ! me manque une case de connaissance là !!

je n'arrive pas à concretiser ce que je souhaite faire en langage C...

revoilà l'explication avec des pieces d'allumeur :smiley:
et voilà l'image de ce que je dois mesurer

ce sont les angles pendant lequel l'inter est ouvert et fermé

:grin:
Pourquoi évoque tu des angles (°) ?
là ou simplement ce que tu dois acquérir est tres simplement la durée temporelle des états de "ta came"/F° échantillonnage ?
Par usure/mauvais positionnement/mauvais usinage/mauvaise conception/ autres... causes

l'angle c'est ce qu'on controle et qu'on regle sur un allumeur => l'angle de came

c'est cet angle que je compare aux valeurs standard (donnée constructeur).

et on lit pleins de choses avec cet angle de came (usure rupteurs, dissymétrie)

zoilgust:
l'angle c'est ce qu'on controle et qu'on regle sur un allumeur => l'angle de came

c'est cet angle que je compare aux valeurs standard (donnée constructeur).

et on lit pleins de choses avec cet angle de came (usure rupteurs, dissymétrie)

et... comment/avec quoi (quelles references physiques ? ) defini tu/accepte comme etant un "angle" un déplacement particulier simplement axé sur un mobile en rotation ? :grin:

Prend un simple "rapporteur" , un angle est défini/admis par rapport à quelle "reference" ? :grin:

Si si On parle d'angle effectivement pour mesurer cela - un autre dessin explicatif

Sur un 4 cylindre (90° =360/4) F sera l'angle pendant lequel le contact est fermé et O l'angle pendant lequel il sera ouvert. Chaque moteur aura son optimal

(source)

Temps total = 4 temps ouvert et 4 temps fermé
Voilà ma réf :wink:
Ensuite règle de 3 sur chaque temps de fermeture /temps total

Oui jml, c'est bien ça, et il me faut cette info axe tournant, l'angle de came n'est pas mesurable au rapporteur