Problème de sortie qui s'active toute seule

Bonjour,

J'ai pour projet de piloter deux vérins via des électrovannes à l'aide d'une ARDUINO UNO.
Sur mes deux vérins seront posés un capteur début de course et un de fin de course=> il y aura donc 4 capteurs.
Jusque la pas de soucis :)!

Grosso-modo j'aimerais :
1)phase d'initialisation (on ne sait pas ou sont les vérins, je les rentre tout les deux jusqu’à détecter mes capteurs début de course pour chaque vérin).

2)boucle infinie
-vérin 1 sort sa tige=> on détecte capteur fin de course 1
-dès que le capteur est détecté, on rentre la tige de vérin 1 jusqu'à capteur début de course 1
-des que capteur début de course 1 est détecte, c'est le vérin 2 cette fois qui s'actionne
-dès que le capteur fin de course de v2 est détecté, il rentre sa tige
-dès que le capteur début de course de v2 est détecté, on recommence.

Sur mon arduino ça va se traduire par 4 capteurs connectées à 4 entrées analogiques de l'arduino
Mes deux électrovannes connectées à 2 sorties PWM (alors pourquoi PWM, je sais pas, j'ai suivi quelques exemples trouvés sur internet, si quelqu'un d'ailleurs pourrait m'expliquer...).

Avant de brancher mes capteurs et mes électrovannes (et tout le tointoin qui va avec (MOSFET etc...) j'ai voulu tester mon programme.
Et c'est la que j'ai vu que malgré la simplicité apparente du truc ben ça plante, en gros je suis pas très douée...(je débute en ARDUINO, peut être ai-je oublié de le mentionner?)

Alors pour tester tout ca, je me suis munie de mon multimètre et j'ai mesuré ma tension aux bornes de mes sorties PMW 9 et 11 tout en alimentant mes entrées A2, A3, A4 et A5 pour simuler mes capteurs.

Voici mon programme:

int electrovanne1=9;
int electrovanne2=11;
int capteur_debut_course_v1=2;
int capteur_fin_course_v1=3;
int capteur_debut_course_v2=4;
int capteur_fin_course_v2=5;
int val_lue_2;
int val_lue_3;
int val_lue_4;
int val_lue_5;

void setup()
{
pinMode(electrovanne1, OUTPUT);
pinMode(electrovanne2, OUTPUT);
pinMode(capteur_debut_course_v1, INPUT);
pinMode(capteur_debut_course_v2, INPUT);
pinMode(capteur_fin_course_v1, INPUT);
pinMode(capteur_fin_course_v2, INPUT);
}

void loop() 
{
//phase d'initialisation, je ne sais pas ou sont mes vérins, je leur demande de rentrer tout les deux.

digitalWrite(electrovanne1, LOW);
digitalWrite(electrovanne2, LOW);

val_lue_2=analogRead(capteur_debut_course_v1);
val_lue_4=analogRead(capteur_debut_course_v2);

//tant que mes DEUX vérins ne sont pas rentrés, j'attends...
while((val_lue_2<=204)||(val_lue_4<=204))
{
val_lue_2=analogRead(capteur_debut_course_v1);
val_lue_4=analogRead(capteur_debut_course_v2);
}

//OUF Ca y est!!
//Je commence ma boucle infinie
while(1)
{
  
  do{
  val_lue_3=analogRead(capteur_fin_course_v1);
  digitalWrite(electrovanne1, HIGH);
  }while(val_lue_3<=204);
  do{
  val_lue_2=analogRead(capteur_debut_course_v1);
  digitalWrite(electrovanne1, LOW);
  }while(analogRead(val_lue_2<=204));
  do{
  val_lue_5=analogRead(capteur_fin_course_v2);
  digitalWrite(electrovanne2, HIGH);
  }while(analogRead(val_lue_5<=204));
  do{
  val_lue_4=analogRead(capteur_debut_course_v2);
  digitalWrite(electrovanne2, LOW);
  }while(analogRead(val_lue_4<=204));  
}
}

Mon soucis ici c'est que malgré que mes entrées A2 et A4 ne soient pas au dessus de 4V comme je lui demande, il passe directement à la boucle infinie, et je me retrouve à mesurer du 5V à la sortie 9 alors qu'il devrait y avoir 0.

Je ne comprend pas trop pourquoi...

Est ce que mon code est erroné?

Ai-je oublié des lignes d’initialisation?

Une autre chose que je ne sais pas c'est si les lignes suivantes sont nécessaires:

pinMode(capteur_debut_course_v1, INPUT);
pinMode(capteur_debut_course_v2, INPUT);
pinMode(capteur_fin_course_v1, INPUT);
pinMode(capteur_fin_course_v2, INPUT);

En effet, est-ce bien utile pour des entrées analogiques? Et si on utilise à la fois l'entrée analogique 1 et l'entrée digitale 1, comment on fait?
(l'erreur ne vient pas de la, même sans ces lignes ça plante).

Je vous remercie par avance de vos retours

Edite ton message et mets le code entre les balises "code"

while((val_lue_2<=204)||(val_lue_4<=204)) //seuils fixés à 4 volts

ce "or" est réservé aux "booleans"

dfgh:

while((val_lue_2<=204)||(val_lue_4<=204)) //seuils fixés à 4 volts

ce "or" est réservé aux "booleans"

Ca tombe bien, l'opérateur "<=" retourne un boolean.
Sachant qu'en plus ce type n'existe pas vraiment en C...
C'est juste une redéfinition d'un type entier.
D'ailleurs les opérateurs logiques, dont ||, fonctionnent très bien avec des byte. Toute valeur différente de 0 est considérée comme 1.

@Lucie :

extrait de ton code :

    do{
    val_lue_2=analogRead(capteur_debut_course_v1);
    digitalWrite(electrovanne1, LOW);
    }while(analogRead(val_lue_2<=204));

Tu peux nous dire ce que fait la dernière ligne, exactement ?

Bonjour,
Comment sont câblés les fins de course?
Ne manquerait-il pas une résistance de tirage (au +5V ou au 0V, suivant comment ils sont branchés)?
A priori, les fins de course sont des interruteurs donc analogRead() n'a pas de sens dans ce cas là.
analogRead() aurait du sens si tu relisais des potentiomètres de recopie de position.
Donc, il faudrait plutôt utiliser digitalRead() pour gére les fins de course.

Bonjour,

Et Merci pour vos réponses.

@bricoleau:

extrait de ton code :
Code: [Select]
do{
val_lue_2=analogRead(capteur_debut_course_v1);
digitalWrite(electrovanne1, LOW);
}while(analogRead(val_lue_2<=204));

Tu peux nous dire ce que fait la dernière ligne, exactement ?

Ce code dit au vérin de rentrer sa tige tant que son capteur début de course n'est pas atteint.

Après peut être que ce code aurait été plus pertinent:

 digitalWrite(electrovanne1, LOW);
 while(analogRead(val_lue_2<=204))
{
val_lue_2=analogRead(capteur_debut_course_v1);
}

@fdufnews:

Les fins de courses sont des capteurs de detection magnétiques SMC rèf D-A90. Si je ne me suis pas trompée,je les câblent en 12Vdc et ils renvoient cette même tension lorsqu'il y a détection. Alors oui je sais y-a un soucis, y a aucun fil relié à la masse, mais il n'y a que deux fils sur ces capteurs... je ne vois pas comment les câbler autrement.

Je joint mon schéma de câblage grossier, ou les moteurs ici seront en fait mes électrovannes.

Bon, tes capteurs contiennent un relais REED donc ils se comportent comme des contacts secs.
Sur les 2 fils qui sortent du capteur, l'un doit être connecté à la masse et l'autre sur l'entrée de l'Arduino. Il faut ajouter une résistance de tirage au +5V sur l'entrée de l'arduino.

Pour commencer tes tests si tu n'as pas de résistances sous la main, tu peux utiliser le pull-up interne des entrées Arduino mais pour un usage industriel ce n'est pas recommandé.
Il faudrait changer tes lignes:

pinMode(capteur_debut_course_v1, INPUT);

par

pinMode(capteur_debut_course_v1, INPUT_PULLUP);

En câblant comme indiqué, tu auras un niveau 0 (LOW) lorsque la position sera atteinte.

Aie aie si ton Arduino est encore en vie t'auras de la chance ... Tu rentres 12V sur les entrée analogiques ells vont grillés si c'est pas déjà fait !!!

Ces capteurs sont à utiliser comme de simple bouton, donc R de pullup.

Oula pas de craintes B@tto.

Je met une résistance entre les 2 quand même!!(Ça suffit non?)
De toute façon, j'ai pas encore mes capteurs donc je n'ai pas envoyé du 12Vdc sur mon ARDUINO.

Pour simuler je relie mes entrées au 5VdC de l'ARDUINO.

Bonjour,

pour des programmes séquentiels , le plus simple à mon avis ,et de simuler un grafcet.

cela a de nombreux avantages et notamment celui de faciliter le dépannage ce qui n'est pas toujours pris en compte lors du développement .Pour un programme simple avec 4 capteurs, cela ne parait pas évident mais cela l'est plus quand le nombre de capteur et de mouvement s'accroit

au début, tu fais un cycle d'initialisation : tu rentres tes 2 vérins ET tu vérifies la présence des capteurs position rentrée et absence de capteur position sortie.

ensuite, tu démarres un cycle avec étape 0 puis vérification des conditions de démarrage (tes 2 vérins rentrés : présence des 2 capteurs vérin rentré ET aucun capteur vérin sorti.

étape 1 : tu sors ton premier vérin.
condition de 1 vers 2 : présence capteur vérin 1 et absence vérin 1 rentré et absence vérin 2 sortie et présence vérin 2 rentré.
étape 2 : tu rentres ton premier vérin

.....

Pour le reste, tes capteurs doivent être de type tout ou rien (0 ou 1) donc entrée digitale .

Il manque des précisions quand aux vérins utilisés : type de technologie (pneumatique, hydraulique, électrique) pour savoir quelle type de sortie utiliser.

Pierre

Lucie_sys:
Oula pas de craintes B@tto.

Je met une résistance entre les 2 quand même!!(Ça suffit non?)

Bin non ça suffit pas ... Pas du tout même. Une résistance limite le courant, pas la tension. Un pont diviseur lui aurait le job.

@fdufnews:

Bon, tes capteurs contiennent un relais REED donc ils se comportent comme des contacts secs.
Sur les 2 fils qui sortent du capteur, l'un doit être connecté à la masse et l'autre sur l'entrée de l'Arduino. Il faut ajouter une résistance de tirage au +5V sur l'entrée de l'arduino.

Pour commencer tes tests si tu n'as pas de résistances sous la main, tu peux utiliser le pull-up interne des entrées Arduino mais pour un usage industriel ce n'est pas recommandé.
Il faudrait changer tes lignes:
Code: [Select]
pinMode(capteur_debut_course_v1, INPUT);

par
Code: [Select]
pinMode(capteur_debut_course_v1, INPUT_PULLUP);

En câblant comme indiqué, tu auras un niveau 0 (LOW) lorsque la position sera atteinte.

Bon effectivement cela parait nettement plus logique pour le câblage des capteurs.
Du coup j'ai remplacé mes entrées analogiques pour les digitales 2,4,7 et 8 et je vais pouvoir tester tout ça.
J'ai des résistances 300 Ohm, cela devrait limiter l'entrée en courant à 16mA.

Du coup j'ai aussi modifier mon schéma.
Merci beaucoup pour tes réponses, je reviens vers toi dès que j'ai testé tout ça!

Bonjour,
300 Ohm ce n'est pas suffisant... il est conseillé d'utiliser des résistances de 10K !
il faut aussi choisir UNE solution, soit INPUT_PULLUP (qui utilise une résistance interne) soit une résistance externe (et là il y à encore 2 possibilités : montage pull-up ou pull-down).

fablath:
300 Ohm ce n'est pas suffisant... il est conseillé d'utiliser des résistances de 10K !

+1 sinon tu vas bouffer énormément de courant pour rien ...

fablath:
il faut aussi choisir UNE solution, soit INPUT_PULLUP (qui utilise une résistance interne) soit une résistance externe (et là il y à encore 2 possibilités : montage pull-up ou pull-down).

Ajoutons cependant que ça n'a rien de dramatique et qua ça fonctionnera quand même. Cependant la solution à privilégier et celle de la R externe car la spec sur l'interne est très large

Merci pour vos conseils!

Bon je vous avoue que je l'ai vu trop tard celui la et que donc j'ai commencé mes tests avec des 300Ohm!

Et comme ça n'a pas fonctionné, j'ai pensé que peut être c'était à cause que " ça bouffait trop de courant" pour l'ARDUINO qui ne peut pas en produire beaucoup.

Donc j'ai mis des 20K (ce que j'avais sous la main quoi!).

Alors dans les deux cas (300 et 20K) ben j'ai mon init qui fonctionne mais à partir de la boucle infinie ça foire.

Voici le code modifié:

int electrovanne1=9;
int electrovanne2=11;
int capteur_debut_course_v1=2;
int capteur_fin_course_v1=4;
int capteur_debut_course_v2=7;
int capteur_fin_course_v2=8;
int val_lue_2;
int val_lue_3;
int val_lue_4;
int val_lue_5;

void setup()
{
pinMode(electrovanne1, OUTPUT);
pinMode(electrovanne2, OUTPUT);
pinMode(capteur_debut_course_v1, INPUT);
pinMode(capteur_debut_course_v2, INPUT);
pinMode(capteur_fin_course_v1, INPUT);
pinMode(capteur_fin_course_v2, INPUT);
}

void loop() 
{
//phase d'init

digitalWrite(electrovanne1, LOW);
digitalWrite(electrovanne2, LOW);

int valeur_debut_course_v1=digitalRead(capteur_debut_course_v1);
int valeur_debut_course_v2=digitalRead(capteur_debut_course_v2);

while((valeur_debut_course_v1==HIGH))
{
  valeur_debut_course_v1=digitalRead(capteur_debut_course_v1);
}
while((valeur_debut_course_v2==HIGH))
{
  valeur_debut_course_v2=digitalRead(capteur_debut_course_v2);
}
  
//fin de phase d'init

  while(1)
  {
    digitalWrite(electrovanne1, HIGH);
    val_lue_3=digitalRead(capteur_fin_course_v1);
    while(val_lue_3==HIGH);
    {
      val_lue_3=digitalRead(capteur_fin_course_v1);
    }
    digitalWrite(electrovanne1, LOW);
    val_lue_2=digitalRead(capteur_debut_course_v1);
    while(val_lue_2==HIGH);
    {
    val_lue_2=digitalRead(capteur_debut_course_v1);
    }
    digitalWrite(electrovanne2, HIGH);
    val_lue_5=digitalRead(capteur_fin_course_v2);
    while(val_lue_5==HIGH);
    {
      val_lue_5=digitalRead(capteur_fin_course_v2);
      }
    digitalWrite(electrovanne2, LOW);
    val_lue_4=digitalRead(capteur_debut_course_v2);
    while(val_lue_4==HIGH); 
   {
     val_lue_4=digitalRead(capteur_debut_course_v2);
    } 
  }
}

En gros, je suis à 0 sur mes sorties 9 et 11. Je mets mes entrées 2 et 7 à la masse=> j'ai 9 qui se met en HIGH.
Par contre quand je met 4 à la masse ben plus rien ne se passe.

Alors si vous avez des idées...

Stoooop !!!!

Eh, les électroniciens, je suis le seul à lire le code ou quoi ? :smiling_imp:

Derrière ma remarque sibylline, il y avait le pointage de ce qui ressemble fortement à une erreur grossière dans le code.
L'objectif était d'inciter à chercher un peu par soi-même, mais bon c'est raté.

Je ne demandais pas ce que sont censées faire les lignes ci-dessous, mais bien ce qu'elles font réellement à l'exécution

Extraits :

do{
    val_lue_2=analogRead(capteur_debut_course_v1);
    digitalWrite(electrovanne1, LOW);
    }while(analogRead(val_lue_2<=204));

C'est la condition du while qui est fausse.

analogRead() prend en paramètre un numéro de pin.
val_lue_2 est une variable dont la valeur est issue d'un analogRead().
L'opérateur logique <= retourne 0 ou 1
while boucle tant que sa condition est différente de 0

Donc là en gros on boucle tant que analogRead(0) ou analogRead(1) retourne une valeur supérieure à 0.

Est-ce vraiment la logique de programme recherchée ?

Vraisemblablement, le analogRead() est en trop dans la condition du while.
Et pareil à deux autres endroits du code

bricoleau:
Stoooop !!!!

Eh, les électroniciens, je suis le seul à lire le code ou quoi ? :smiling_imp:

Elle aurait pu écrire le meilleur code au monde, si l'hardware n'est pas bon il ne sert strictement à rien !

Donc on a simplement fait les choses dans l'ordre ... En plus un mauvais code on ne grille rien ... Il ne tourne pas bien c'est tout.

Pour en revenir maintenant au code :

do{
    val_lue_2=analogRead(capteur_debut_course_v1);
    digitalWrite(electrovanne1, LOW);
    }while(analogRead(val_lue_2<=204));

Pas bon en effet, je pense que ce qu'il était prévu était plutôt :

do{
    val_lue_2=analogRead(capteur_debut_course_v1);
    digitalWrite(electrovanne1, LOW);
    }while(val_lue_2<=204);

De toute manière tout va changer puisque analogRead() va être remplacé par des digitalRead()

Re,

@ B@tto:

Pas bon en effet, je pense que ce qu'il était prévu était plutôt :

Code: [Select]
do{
val_lue_2=analogRead(capteur_debut_course_v1);
digitalWrite(electrovanne1, LOW);
}while(val_lue_2<=204);

De toute manière tout va changer puisque analogRead() va être remplacé par des digitalRead()

Effectivement c'était l'intention. Je voulais exprimer : tant que mon entrée est inférieure à 4VdC.

Maintenant, j'ai tout modifié avec les digital pins mais j'ai toujours un soucis. Voir mon précédent post.

L'init se passe bien mais je dois bloquer sur cette boucle car ma sortie 9 reste à 5Vdc malgré que je mette mon entrée 4 à la masse.

while(val_lue_3==HIGH);

    {
      val_lue_3=digitalRead(capteur_fin_course_v1);
    }

La ou je me pose vraiment des questions c'est que c'est le même fonctionnement que pour l'init mais la ça ne marche pas....

Autre question, j'ai vu que les entrées analogiques peuvent être utilisées en digital pins. Qu'elle est la meilleur solution?

Surtout, comment fais ARDUINO pour distinguer la digitale 2 et l'analogue 2 si on la met en digitale?

En fait c'est une très mauvaise habitude d'identifier les entrées analogique avec des numéros cela pose des problèmes de portage. En effet, les entrées analogiques lorsqu'on les utilisent en I/O logiques prennent les numéros qui suivent le plus haut numéros d'I/O logique. Toutes les cartes n'ont pas le même nombre d'entrées/sorties logiques et donc suivant les cartes (UNO, MEGA par exemple) les broches analogiques sont identifiées différement.

Il faut plutôt utiliser A0, A1, A2 .... voir là : http://www.arduino.cc/en/Tutorial/AnalogInputPins

En fait actuellement avec ton code tu testes les entrées logiques 2, 3, 4 et 5 (D2, D3, D4 et D5)

B@tto:
... En plus un mauvais code on ne grille rien ... Il ne tourne pas bien c'est tout.

+1 !

Je ne suis pas fan des boucles while... pendent ce temps le micro ne peut rien faire d'autre!
Le moniteur série est très pratique pour savoir comment se déroule un code.

Avec des "if" ça pourrait ressembler à ça (je n'ai pas tester...) :

const int electrovanne1 = 9;
const int electrovanne2 = 11;
const int capteur_debut_course_v1 = 2;
const int capteur_fin_course_v1 = 4;
const int capteur_debut_course_v2 = 7;
const int capteur_fin_course_v2 = 8;

int val_debut_course_v1;
int val_fin_course_v1;
int val_debut_course_v2;
int val_fin_course_v2;

byte phase = 0;    // 4 phases : sortie V1, rentrée V1, sortie V2, rentrée V2

void setup()
{
  pinMode(electrovanne1, OUTPUT);
  pinMode(electrovanne2, OUTPUT);
  pinMode(capteur_debut_course_v1, INPUT);
  pinMode(capteur_debut_course_v2, INPUT);
  pinMode(capteur_fin_course_v1, INPUT);
  pinMode(capteur_fin_course_v2, INPUT);

  Serial.begin(9600);

  //phase d'init
  Serial.print("Phase ");
  Serial.print(phase);
  Serial.println(" (init...)");

  digitalWrite(electrovanne1, LOW);
  digitalWrite(electrovanne2, LOW);
}

void loop() 
{
  val_debut_course_v1 = digitalRead(capteur_debut_course_v1);
  val_fin_course_v1 = digitalRead(capteur_fin_course_v1);
  val_debut_course_v2 = digitalRead(capteur_debut_course_v2);
  val_fin_course_v2 = digitalRead(capteur_fin_course_v2);

  if(val_debut_course_v1 == false && val_fin_course_v1 == true
    && val_debut_course_v2 == false && val_fin_course_v2 == true
    && phase == 0)
  {
    phase = 1;
    digitalWrite(electrovanne1, HIGH);

    Serial.print("Phase ");
    Serial.print(phase);
    Serial.println(" : Sortie vérin 1");
  }

  else if(val_debut_course_v1 == true && val_fin_course_v1 == false
    && val_debut_course_v2 == false && val_fin_course_v2 == true
    && phase == 1)
  {
    phase = 2;
    digitalWrite(electrovanne1, LOW);

    Serial.print("Phase ");
    Serial.print(phase);
    Serial.println(" : Rentrée vérin 1");
  }

  else if(val_debut_course_v1 == false && val_fin_course_v1 == true
    && val_debut_course_v2 == false && val_fin_course_v2 == true
    && phase == 2)
  {
    phase = 3;
    digitalWrite(electrovanne2, HIGH);

    Serial.print("Phase ");
    Serial.print(phase);
    Serial.println(" : Sortie vérin 2");
  }

  else if(val_debut_course_v1 == false && val_fin_course_v1 == true
    && val_debut_course_v2 == true && val_fin_course_v2 == false
    && phase == 3)
  {
    phase = 0;
    digitalWrite(electrovanne2, LOW);

    Serial.print("Phase ");
    Serial.print(phase);
    Serial.println(" : Rentrée vérin 2");
  }
}

il manque dans ce code un contrôle du fonctionnement des détecteurs : que fait on si les détecteurs début et fin de courses sont actif en même temps? si on perd le début de course 2 pendant la sortie du vérin 1... si le fin de course ne s'active pas au bout d'un certain temps alors qu'un mouvement est en cours...