Erreur de programmation [programme simple, mais newbee inside]

bonjour a tous

je suis en train de bosser sur un programme assez bête ou il y a des entrées tout ou rien (capteurs ou simplement boutons poussoirs) et qui contrôle des sorties en tout ou rien également! Pour faire simple tout est en O ou 1 :wink:

le but de se programme est de faire fonctionner un petit groupe hydraulique.

Lorsque je testais tout semblait marcher, mais la je viens de tester sur le système réel et je n'ai pas du tout le même fonctionnement ...

en fait rien de fonctionne mise à part la sonnette!!!. La plupart des sorties se mettent à 1 et plus rien!

Je pense que mon problème vient des remises à zéro des variables, mais je ne maitrise pas suffisamment le langage pour trouver mon erreur.

Merci de me filer un petit coup de main

Nico

Tu fais une série de tests avec if qui mettent en route des actions selon quel bouton ou capteur est activé. Jusque là, ok.

mais voilà, tout se remet à zéro si le dernier test (if (!et_bt_hm && !et_bt_dben && !et_ct_ben_bas)) n'est pas vérifié (ton else à la fin ne concerne que le dernier test).

Alors simplement, revois tes tests comme suit :

if (test_variables) {
  action();
} else {
  pas_action();
}

Comme ça, pour chaque BP activé, on fait l'action, sinon on l'arrête.

Ensuite, tu passera pro en remplaçant chaque test juste par la ligne suivante et en virant toutes tes void d'action :

  digitalWrite(pin_où_faut_agir, test_variables);

Bonjour,

Je pense que ton erreur est purement "syntaxique", tu fait une tripoté de if et à la fin on voit un else qui tombe d'on ne sait ou telle un cheveux sur la soupe.

Je te (re)post ton code, c'est exactement le même que le tient à la différence prés que j'ai respecté une mise en forme lissible :

/*
  Atmega 644p
 */

// adressage des pins:  // pin dispo  0,8,9,16,22)   8,9 ==> bt
// en utilisant un #define à la place d'un const int tu gagne presque 200octets de flash et presque 40octets de ram
#define bt_hm       31  // pins d'entrée Pupitre
#define bt_mben     30
#define bt_dben     29
#define bt_pell1    28
#define bt_pell2    27
#define bt_sonnette 25
#define ct_ben_bas  20  // pins d'entrée capteurs
#define ps_beq_rent 18  // bequilles completement rentrées    1 quand rentré
#define ps_beq_sort 17  // bequilles sorties et en pression   1 quand sortie
#define embra       15  // pins de sortie
#define cl_para     14
#define benne       12
#define pell1       6
#define pell2       4
#define dc_beq      3
#define sonnet      2
#define mo_beq      1


void setup() {
  pinMode(embra, OUTPUT);        // initialisation des E/S
  pinMode(cl_para, OUTPUT);
  pinMode(benne, OUTPUT);
  pinMode(pell1, OUTPUT);
  pinMode(pell2, OUTPUT);
  pinMode(dc_beq, OUTPUT);
  pinMode(sonnet, OUTPUT);
  pinMode(mo_beq, OUTPUT);

  pinMode(bt_hm, INPUT); 
  pinMode(bt_mben, INPUT); 
  pinMode(bt_dben, INPUT); 
  pinMode(bt_pell1, INPUT); 
  pinMode(bt_pell2, INPUT); 
  pinMode(bt_sonnette, INPUT); 
  pinMode(ct_ben_bas, INPUT);   
  pinMode(ps_beq_rent, INPUT); 
  pinMode(ps_beq_sort, INPUT);  
}


void loop(){
  int et_bt_hm = digitalRead(bt_hm);  // attribution des etats des variables
  int et_bt_mben = digitalRead(bt_mben);
  int et_bt_dben = digitalRead(bt_dben);
  int et_bt_pell1 = digitalRead(bt_pell1);
  int et_bt_pell2 = digitalRead(bt_pell2);
  int et_bt_sonnette = digitalRead(bt_sonnette);
  int et_ct_ben_bas = digitalRead(ct_ben_bas);
  int et_ps_beq_rent = digitalRead(ps_beq_rent);
  int et_ps_beq_sort = digitalRead(ps_beq_sort);



  // Sonnette alarme
  if (!et_bt_sonnette || et_ps_beq_rent == HIGH)          // sonnette si appui bouton ou bequilles non rentrées
  {
    digitalWrite(sonnet, HIGH);   // activation sonnette
  }

  // Pelle sens1
  if (!et_bt_hm && !et_bt_pell1)                          // vérification de l'homme mort et du BP pelle sens 1
  {
    digitalWrite(embra, HIGH);    // activation embrayage // il y avait une erreur de nom de fontion ici ;)
    digitalWrite(pell1, HIGH);    // pelle sens 1
  }                

  // Pelle sens2
  if (!et_bt_hm && !et_bt_pell2)                          // vérification de l'homme mort et du BP pelle sens 2
  {
    digitalWrite(embra, HIGH);    // activation embrayage
    digitalWrite(pell2, HIGH);    // pelle sens 2
  } 

  // Sortir bequilles et montée benne
  if (!et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH) //vérification  de l'homme mort et BP monte benne et pressostat bequilles non sorties
  {
    digitalWrite(embra, HIGH);    // activation embrayage
    digitalWrite(dc_beq, HIGH);   // sortir bequilles
  }

  if (!et_bt_hm && !et_bt_mben && !et_ps_beq_sort)        //vérification  de l'homme mort et BP monte benne et pressostat bequilles sorties
  {
    digitalWrite(embra, HIGH);    // activation embrayage
    digitalWrite(benne, HIGH);    // monter benne
    digitalWrite(cl_para, HIGH);  // ouvrir clapet parachute
  }

  // Descente benne et remonter bequilles
  if (!et_bt_hm && !et_bt_dben && et_ct_ben_bas == HIGH)  //vérification  de l'homme mort et BP descente benne et capteur benne basse non activé
  {
    digitalWrite(cl_para, HIGH);   // ouvrir clapet parachute
  } 

  if (!et_bt_hm && !et_bt_dben && !et_ct_ben_bas)         //vérification  de l'homme mort et BP descente benne et capteur benne basse activé
  {
    digitalWrite(embra, HIGH);     // activation embrayage
    digitalWrite(mo_beq, HIGH);    // rentrer bequilles
  }
  else // erreur ?
  { // remise des varibles à zero
    digitalWrite(embra, LOW);
    digitalWrite(pell1, LOW);
    digitalWrite(pell2, LOW);
    digitalWrite(cl_para, LOW);
    digitalWrite(mo_beq, LOW);
    // il y avait un ; qui ce baladé, faire de gros patté d'instructions n'apporte rien de bien ;)
    digitalWrite(dc_beq, LOW);
    digitalWrite(benne, LOW);
    digitalWrite(sonnet, LOW);
  }
}

J'ai mis des commentaires sur les passages "étranges".

Aprés lecture de ton code je peut te dire que ton arduino fait très exactement ce que tu lui demande, il place tout les sorties à HIGH selon les conditions qui lui sont donnée mais pour qu'il les repassent à LOW il faut que (!et_bt_hm && !et_bt_dben && !et_ct_ben_bas) == false, est ce que cela est volontaire ou non ? toi seul peut nous le dire :wink:

Edit: Super_Cinci tu est un vrai ninja, le temps que rende le code lisible tu post déjà une réponse :slight_smile:

merci bcp pour votre aide!!

donc tous les deux, vous pensez que faire" des void action n'est pas une bonne idée? je l'avait rajouter car cela me semblait plus lisible!

Merci de votre aide, je vais potassé tout cela :wink:

Merci! merci! Merci !!!

n1c0l45:
donc tous les deux, vous pensez que faire" des void action n'est pas une bonne idée? je l'avait rajouter car cela me semblait plus lisible!

faire une fonction n'est vraiment utile que quand on doit faire quelque chose (un calcul, ...) plusieurs fois dans un même code, une fonction utilisé une seul fois est inutile et entraine des erreurs (comme l'appel de pell_sens1 méchamment copier/coller en pell_sens2 ;))

en fait, son erreur est très simple, je fais un code de bas correspondant au sien :

loop(){
  if (condition1){
    actionner_1();
  }
  if (condition2){
    actionner_2();
  }
  if (condition3){
    actionner_3();
  }
  if (condition4){
    actionner_4();
  } else {
    tout_arrêter();
  }
}

Donc si on remplit la condition1, alors on fait actionner1(); mais quelque petites µs après, comme condition4 n'est pas remplie, alors on fait tout_arrêter(); Le résultat est qu'on verra une impulsion de qq µs sur les bonnes pins, mais pas assez pour actionner un vérin.

l'erreur est là, c'est tout aussi simple que de se mettre un doigt dans le nez (ou ailleurs...)

Je suis pas un ninja, mais on a trouvé l'erreur en même temps... :slight_smile:

encore merci

Bon, rien que ces deux tests se contredisent :

// Sortir bequilles et monter benne
  if (!et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH&& et_ps_beq_sort == HIGH )//vérification  de l'homme mort et BP monte benne et pressostat bequilles non sorties
             {
               digitalWrite(embra, HIGH);                   // activation embrayage
               digitalWrite(dc_beq, HIGH);                  // sortir bequilles
             }
  else      {
               digitalWrite(embra, LOW);           
               digitalWrite(dc_beq, LOW);       
            }           

  if (!et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort)     //vérification  de l'homme mort et BP monte benne et pressostat bequilles sorties
             {
               digitalWrite(embra, HIGH);                   // activation embrayage
               digitalWrite(benne, HIGH);                   // monter benne
               digitalWrite(cl_para, HIGH);                 // ouvrir clapet parachute
             }
  else      {
               digitalWrite(embra, LOW);               
               digitalWrite(benne, LOW);                 
               digitalWrite(cl_para, LOW);               
           }

Effectivement, si le premier est vérifié, alors embra sera mis à 1, mais comme le second n'est pas vérifié, embra est remis à 0.

Comme chaque sortie dépend un peu de plusieurs entrées. si je ne prends que ces deux tests, ça donne ça :

embra = dc_beq = et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH && et_ps_beq_sort == HIGH; 
embra = benne = cl_para = et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort

On voit que deux conditions agissent sur embra, donc il faut les réunir. On a donc juste à écrire ça :

digitalWrite(dc_beq, et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH&& et_ps_beq_sort == HIGH);
digitalWrite(embra, (et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH&& et_ps_beq_sort == HIGH)||(et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort));
digitalWrite(benne , et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort);
digitalWrite(cl_para, et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort);

Pour faire plus simple, essaie ce code là : c'est le tien, mais il doit marcher, sinon je ne suis pas un ninja :smiley:

La modif que j'ai faite : c'est remplacer chaque if par un calcul boolean. puis digitalWrite (sortie, t_xxx);. Quand une sortie dépend de plusieurs tests, alors on a des OR dans le digitalWrite. Ca a pour effet que les tests IF ne s'annulent plus les uns les autres...

/*

  Atmega 644p

*/



// adressage des pins:           // pin dispo  0,8,9,16,22)   8,9 ==> bt
#define bt_hm        31         // pins d'entrée Pupitre
#define bt_mben      30
#define bt_dben      29
#define bt_pell1     28
#define bt_pell2     27
#define bt_sonnette  25

// pins d'entrée capteurs
#define ct_ben_bas   20
#define ps_beq_rent  18         // bequilles completement rentrées    1 quand rentré
#define ps_beq_sort  17         // bequilles sorties et en pression   1 quand sortie

#define embra        15         // pins de sortie
#define cl_para      14
#define benne        12
#define pell1         6
#define pell2         4
#define dc_beq        3
#define sonnet        2
#define mo_beq        1


void setup() {

  pinMode(embra, OUTPUT);        // initialisation des E/S
  pinMode(cl_para, OUTPUT);
  pinMode(benne, OUTPUT);
  pinMode(pell1, OUTPUT);
  pinMode(pell2, OUTPUT);
  pinMode(dc_beq, OUTPUT);
  pinMode(sonnet, OUTPUT);
  pinMode(mo_beq, OUTPUT);
 
  pinMode(bt_hm, INPUT);
  pinMode(bt_mben, INPUT);
  pinMode(bt_dben, INPUT);
  pinMode(bt_pell1, INPUT);
  pinMode(bt_pell2, INPUT);
  pinMode(bt_sonnette, INPUT);
 
  pinMode(ct_ben_bas, INPUT);
  pinMode(ps_beq_rent, INPUT);
  pinMode(ps_beq_sort, INPUT); 
}

boolean t_sonnette, t_pelle_s1, t_pelle_s2, t_beq_benne, t_hm_benne, t_benne_beq, t_hm_benne_beq;  // variables de tests capteurs et boutons

void loop(){
 
 
 int et_bt_hm = digitalRead(bt_hm);               // attribution des etats des variables
 int et_bt_mben = digitalRead(bt_mben);
 int et_bt_dben = digitalRead(bt_dben);
 int et_bt_pell1 = digitalRead(bt_pell1);
 int et_bt_pell2 = digitalRead(bt_pell2);
 int et_bt_sonnette = digitalRead(bt_sonnette);
 int et_ct_ben_bas = digitalRead(ct_ben_bas);
 int et_ps_beq_rent = digitalRead(ps_beq_rent);
 int et_ps_beq_sort = digitalRead(ps_beq_sort);
 

// Sonnette alarme
  t_sonnette = (!et_bt_sonnette || et_ps_beq_rent == HIGH);        // sonnette si appui bouton ou bequilles non rentrées

// Pelle sens1
  t_pelle_s1 = (!et_bt_hm && !et_bt_pell1);                        // vérification de l'homme mort et du BP pelle sens 1

// Pelle sens2
  t_pelle_s2 = (!et_bt_hm && !et_bt_pell2);                        // vérification de l'homme mort et du BP pelle sens 2

// Sortir bequilles et monter benne
  t_beq_benne = (!et_bt_hm && !et_bt_mben && et_ps_beq_sort == HIGH&& et_ps_beq_sort == HIGH); //vérification  de l'homme mort et BP monte benne et pressostat bequilles non sorties
  t_hm_benne = (!et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort);     //vérification  de l'homme mort et BP monte benne et pressostat bequilles sorties

 // Descente benne et remonter bequilles
  t_benne_beq = (!et_bt_hm && !et_bt_dben && et_ct_ben_bas == HIGH && et_ct_ben_bas == HIGH); //vérification  de l'homme mort et BP descente benne et capteur benne basse non activé
  t_hm_benne_beq = (!et_bt_hm && !et_bt_dben && !et_ct_ben_bas && !et_ct_ben_bas);      //vérification  de l'homme mort et BP descente benne et capteur benne basse activé


  digitalWrite(sonnet, t_sonnette);                  // activation sonnette
  digitalWrite(embra, t_pelle_s1 || t_pelle_s2 || t_beq_benne || t_hm_benne || t_hm_benne_beq);          // activation embrayage
  digitalWrite(pell1, t_pelle_s1);                   // pelle sens 1
  digitalWrite(pell2, t_pelle_s2);                   // pelle sens 2
  digitalWrite(dc_beq, t_beq_benne);                  // sortir bequilles
  digitalWrite(benne, t_hm_benne);                   // monter benne
  digitalWrite(cl_para, t_hm_benne || t_benne_beq);                 // ouvrir clapet parachute
  digitalWrite(mo_beq, t_hm_benne_beq);                  // rentrer bequilles

}

C'est le petit cadeau du matin...
Maintenant, si tu prends par exemple le digitalWrite suivant :

  digitalWrite(cl_para, t_hm_benne || t_benne_beq);                 // ouvrir clapet parachute

on trouve alors :

  cl_para = (t_hm_benne || t_benne_beq)
             = (!et_bt_hm && !et_bt_mben && !et_ps_beq_sort && !et_ps_beq_sort) || (!et_bt_hm && !et_bt_dben && et_ct_ben_bas == HIGH && et_ct_ben_bas == HIGH)
(...)

Je pense qu'en décomposant l'expression, on doit pouvoir simplifier grandement, limite si tu t'es pas pris la tête pour calculer tes associations pour faire des tests, alors que ce n'était pas nécessaire, et que tu as déjà les formules de tes sorties genre

sortie = entrée1 || (!entrée2 && entrée3)

Si mon code marche, alors en échange, je te demande de le réécrire en simplifiant le tout, sinon c'est trop facile, c'est ton projet, pas le mien! :stuck_out_tongue:

Merci, je viens de comprendre mon erreur!

je vais modifier mon programme pour suivre tes indications (virer les if)

merci

je suis en train de faire les modifs (le programme mis en ligne est en faait une version simplifiée de celui que j'utilise, il y a plus de fonctions)

encore merci de ton aide

n1c0l45:

sketch_nov02a.cpp: In function 'void loop()':
sketch_nov02a:87: error: lvalue required as left operand of assignment

Redonne nous ton code complet pour qu'on puisse regarder ça chez nous :wink:
Ps: je vois pas trop ce que tu nous prépare avec tes opérations logique pointant vers des variables ...
j'ai bien une petite idée de ce que tu compte essayer de faire mais j'attend de voir :wink:

Les digitalWrite(), fallait les garder, car ce sont eux qui mettent 1 ou 0 en sortie hard... ce que tu as fait là ne ressemble plus à grand chose...

en attente du code complet...

Super_Cinci:
Les digitalWrite(), fallait les garder, car ce sont eux qui mettent 1 ou 0 en sortie hard... ce que tu as fait là ne ressemble plus à grand chose...
en attente du code complet...

Il a suivi ton code d'exemple Super_Cinci, perso je trouve cela totalement ignoble de faire un :

t_sonnette = (!et_bt_sonnette || et_ps_beq_rent == HIGH);
digitalWrite(sonnet, t_sonnette);

et encore plus :

digitalWrite(sonnet, (!et_bt_sonnette || et_ps_beq_rent == HIGH));

Un if "normal" ça mange pas de pain et ça rend le code bien plus lisible.

n1c0l45 si tu ne maitrise pas encore totalement la syntaxe "arduino" garde ma version avec des if + accolades,
d'un point de vu optimisation c'est pas top mais le core arduino en soi n'est pas optimisé alors pas la peine de chercher 12h à 14h.
Enfin bon fait comme tu le sens :wink:

skywodd:
Un if "normal" ça mange pas de pain et ça rend le code bien plus lisible.

Je plussoie, une grosse partie des erreurs en programmation viennent de la lisibilité du code.
Ca permet aussi d'avoir plus de "repères".

skywodd:
Il a suivi ton code d'exemple Super_Cinci, perso je trouve cela totalement ignoble de faire un :

t_sonnette = (!et_bt_sonnette || et_ps_beq_rent == HIGH);

digitalWrite(sonnet, t_sonnette);



et encore plus :


digitalWrite(sonnet, (!et_bt_sonnette || et_ps_beq_rent == HIGH));



Un if "normal" ça mange pas de pain et ça rend le code bien plus lisible.

Je sais que tu n'aimes pas trop mes idées, mais pourquoi faire un if sur des valeurs booléennes alors qu'il suffit d'un digitalWrite? je comprends pas du tout ta réaction, car je n'ai fait qu'une équation logique, comme on faisait en première année de BTS. De plus, si tu regardes bien, les sorties dépendent d'entrées mais pas toutes en même temps et pour l'embrayage, c'est assez compliqué. Tu n'as jamais fait d'équations genre "S1 = (!E1 + E2) . E3 + !E4"? c'est exactement ce dont il a besoin ici, et l'utilisation des if devient très compliquée pour résoudre une telle équation et encore moins lisible (à mon sens, à l'école d'il y a 15 ans ou le moindre octet de mémoire valait de l'or, ce qui est un peu le cas de nos arduinos)...

Super_Cinci:
Je sais que tu n'aimes pas trop mes idées, mais pourquoi faire un if sur des valeurs booléennes alors qu'il suffit d'un digitalWrite? je comprends pas du tout ta réaction, car je n'ai fait qu'une équation logique, comme on faisait en première année de BTS. De plus, si tu regardes bien, les sorties dépendent d'entrées mais pas toutes en même temps et pour l'embrayage, c'est assez compliqué. Tu n'as jamais fait d'équations genre "S1 = (!E1 + E2) . E3 + !E4"? c'est exactement ce dont il a besoin ici, et l'utilisation des if devient très compliquée pour résoudre une telle équation et encore moins lisible (à mon sens, à l'école d'il y a 15 ans ou le moindre octet de mémoire valait de l'or, ce qui est un peu le cas de nos arduinos)...

Quand on manipule aisément le langage c on peu se permettre de mettre des équations inline et d'utiliser des astuces pour réduire l'impact mémoire du programme.

Mais ce qu'il ne faut pas oublier :

Je pense que mon problème vient des remises à zéro des variables, mais je ne maitrise pas suffisamment le langage pour trouver mon erreur.

Quand on débute, la solution la plus simple est souvent la meilleur solution :wink:

Une écriture simple, certes inutilement surchargé mais aéré permet de relire son code et trouver une erreur, quand on débute c'est la clef.

Pour ceux qui est de tes idées elle ne me dérange absolument pas :wink:
(Au passage regarde un peu le code du "core arduino", si tu est frileux quand aux optimisations mémoire tu devrais apprécier le char buffer[64] de la fonction serial, ou encore la table de correspondance des broche arduino <> registre en progmem de 400octets, et j'en passe ... ;))

C'est surtout à quel moment on peux ce permettre d'optimiser son code, moi je ne le fais qu'une fois qu'il est fonctionnel d’où le mot "optimisé" lol.
Ce type de code ne facilite pas le debug.
Donc pour un débutant je prendrai en exemple le projet de chico, il y a certaine choses que je ne fais pas sous peine de lui compliquer la compréhension du code :~.
:wink:

C'est ce que je disais : on ne vient pas de la m^me école. J'ai commencé la prog sur 68HC11, avec le bon vieux terminal AIM, tout orange et tout ouvert car ça chauffait grave à 1MHz dedans... Donc avant de toucher les 68HC11, on devait se familiariser avec toute une tripotée de portes logiques, des noircissages de papier, des emmèlements sur les plaques d'essai, voire sur deux plaques... Maintenant, on code sur PC où a mémoire est le dernier des soucis du programmeur. On évitait le test (if) au max, car c'était un risque à faire déborder la pile de 10 octets... Même si j'ai fait l'impasse à ce moment là (heureusement, le sujet du BTS ne comportait pas de micros, ouf!), il me reste des vieux réflexes et ça me va. Je veux bien comprendre qu'aujourd'hui, on n'a plus du tout les mêmes soucis de prog!

Je regarderai le core arduino, oui, car les 450 octets quand on compile "bare minimum", ça me fait mal au cul!

C'est clair que c'est ici où je vois la différence entre un "électronicien" qui cherchera à optimisé la mémoire, un développeur procédural son temps processeur et un développeur objet les dépendances de code.

lol je pensais pas soulever autant de ferveur :wink:

j'ai compris la structure mais c'est vrai que les if me semblaient plus... conviviaux :wink:

en tous cas, merci de votre aide