Auteur Sujet: Arduino pilotage PN37  (Lu 52913 fois)

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Re : Re : Arduino pilotage PN37
« Réponse #15 le: février 21, 2016, 12:34:30 pm »
Ma question : est-ce qu'on peut mettre ce test dans le setup, qui attendrait ce premier appui pour donner la main à la loop, ou bien ça ne marche pas et il faut un flag et un if .. else en début de loop ?

On peut mettre ce que l'on veut dans setup.

Bon, ya pas à dire, il faut monter les marches de l'escalier l'une après l'autre.

Je cherche à faire fonctionner ce morceau d'initialisation de mon projet.
Fonction attendue : après la mise sous tension, le programme doit attendre un premier appui sur un bouton poussoir pour entrer dans le loop. Pour ce test, le programme ne doit qu'allumer une led.

J'ai donc un bouton poussoir relié à une entrée avec pull-up intégrée, et un circuit d'allumage de led sur une sortie pwm.
Partant du conseil ci-dessus, j'ai mis un while dans le setup, et je m'attendais que le programme y reste tant que je n'ai pas actionné mon bouton.

Sauf que ça ne marche pas, il ignore superbement le bouton poussoir et allume la diode tout de suite. J'ai mis des espions avec des Serial.print et, à l'évidence, le programme ne cycle pas à l'intérieur de mon while

Mon code :
/* Programme de test de l'utilisation du bouton poussoir éclairage
pour initialiser le programme une fois que tout est vérifié
Pour ce test on utilise Led0 sur pin 5 - on en profite pour tester le pwm
Dans un premier temps on se contente de lire le bouton */


// Déclaration des constantes
const byte pinEclair=7; // affecte l'E/S 7 au bp cyclage éclairage
const byte pinLed0=3; // affecte l'E/S 3 à la led 0

// Déclaration des variables
byte eclair; // état du bouton poussoir de cyclage de l'éclairage
byte flagInit = 0; // flag pour sortir de la boucle d'initialisation. flagInit = 1 pour sortir
byte pwmLed0=255; // pour régler l'éclairement Led0 - provisoire 100 % (255)

void setup() {
  // put your setup code here, to run once:
pinMode(pinLed0, OUTPUT); // déclare pinLed0 comme sortie ; facultatif pour sortie pwm
pinMode(pinEclair, INPUT_PULLUP); // déclare pinEclair en entrée et active la résistance de pullup interne

while (flagInit == 0)
  {
  digitalRead(eclair);
  if(eclair==LOW) flagInit=1;
    }

}
void loop() {
  // put your main code here, to run repeatedly:
analogWrite(pinLed0,pwmLed0);
}

Je n'ai pas trouvé comment insérer le schéma fritzing sans devoir le télécharger quelque part sur le net, mais je peux le faire si ça vous éclaire.

Mes hypothèses de travail :
- le BP est sur une entrée avec pull-up intégrée, donc l'entrée est à HIGH tant que le BP est relâché, et passe à LOW sur appui.
- la boucle while boucle sur elle-même tant que flagInit est à 0 ; flagInit passe à 1 quand la boucle lit un état LOW sur le bouton poussoir nommé eclair, ce qui provoque la sortie à la boucle suivante.

Où est-ce que j'ai faux ?

Désolé de vous mobiliser pour des trucs que  vous devez considérer comme basiques. En attendant je vais aller faire du décor.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #16 le: février 21, 2016, 06:07:43 pm »
Bonjour

digitalRead est une fonction qui renvoie la valeur lue

Dans ton cas, il faut écrire :

eclair = digitalRead(pinEclair);

Tel que c'est écrit :

digitalRead(eclair);

la broche de numéro eclair est lue et le résultat est jeté. On ne sait pas ce que contient éclair mais vu le comportement il contient 0. Le test

if (eclair == LOW) { ... }

sera donc vrai car LOW vaut également 0
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #17 le: février 23, 2016, 08:06:38 pm »
Je ne t'ai pas remercié, Jean-Luc, mais je me suis baffé pour une erreur aussi basique. Mais c'est comme ça que ça rentre.

Je progresse bien (quoique laborieusement), je maîtrise le bouton poussoir qui allume successivement 4 leds, avec l'antirebond Bounce2.

J'attaque TableSchedule, et je bloque sur la récurrence:

J'ai une séquence de 5 actions sur 16 secondes, que je veux dérouler une fois à chaque fois qu'un interrupteur est basculé sur une certaine position.

J'ai lu qu'on peut demander que la séquence se répète à l'infini ou un certain nombre de fois, donc j'ai tendance à mettre maTable.start(1). Correct ?

mais comment maîtriser le démarrage de la séquence, c'est-à-dire qu'elle se lance  1 fois chaque fois que le fameux interrupteur est basculé, et non pas dès le début du programme ? ? On met un maTable.start(1) à l'endroit prévu dans la loop ?  J'ai fait quelques essais en ce sens mais infructueux.

Merci de vos lumières.

(Je l'aurai ... je l'aurai)

Dominique.

Mon code provisoire :

// Test de la bibliothèque ScheduleTable et de la commande d'un optocoupleur
#include <ScheduleTable.h>
#include <Bounce2.h>

ScheduleTable ouvreSonne(5,4500);  // Création de la table

// Création des objets Bounce que j'appelle inter1, inter2
Bounce inter1; // inter pour programme fermeture barrières avec sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil gris
Bounce inter2; // inter pour programme fermeture barrières sans sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil rouge
const byte pinInter1=13; // affecte l'E/S 13 à l'inter en position 1
const byte pinInter2=12; // affecte l'E/S 12 à l'inter en position 2
const byte pinSonne=8;  // affecte l'E/S 8 au pilotage de la sonnerie via optocoupleur. Pour ce test, l'opto allume une led alimentée séparément

 // déclaration des variables
byte actionPN=0; // variable d'état pour le switchcase de pilotage des barrières
byte prevActionPN=0; // l'état précédent de actionPN
float target = 0.0;
byte sonne=LOW; // variable utilisée pour l'impulsion de commande de la sonnerie.

void pulseOn()
{
  sonne=HIGH;
}

void pulseOff()
{
    sonne=LOW;
}

void basculeTarget()
{
  target = 0.0;
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(pinInter1, INPUT_PULLUP); // déclare pinInter1 en entrée et active la résistance de pullup interne
pinMode(pinInter2, INPUT_PULLUP); // déclare pinInter2 en entrée et active la résistance de pullup interne
inter1.attach(pinInter1);
inter1.interval(10);
inter2.attach(pinInter2);
inter2.interval(10);
pinMode(pinSonne, OUTPUT); // déclare pinSonne comme sortie;

// Table des événements de ouvreSonne: impulsions de 500 ms à t=0 et t = 4000, et assigne la valeur 0.0 à target à t = 2000
ouvreSonne.at(0,pulseOn);
ouvreSonne.at(500,pulseOff);
ouvreSonne.at(2000,basculeTarget);
ouvreSonne.at(4000,pulseOn);
ouvreSonne.at(4500,pulseOff);
ouvreSonne.start(1);
}

void loop() {
  // put your main code here, to run repeatedly:
  // les objets Bounce doivent exécuter leur code interne à chaque loop :
  inter1.update();
  inter2.update();
  int value1 = inter1.read();
  int value2 = inter2.read();
  ScheduleTable::update();


// ici on calcule actionPN en fonction de inter1 et inter2
    if ((value1==HIGH) && (value2==LOW))
    {
      actionPN=2;
    }
    else if ((value1==LOW) && (value2==HIGH))
    {
      actionPN=1;
    }
    else {
      actionPN=0;
    }
 /* Serial.print("inter 1  :  ");
  Serial.print(value1);
  Serial.print("  inter2 :  ");
  Serial.print(value2);
  Serial.print("  actionPN  :  ");
  Serial.print(actionPN);
  Serial.print("  Target  :  ");
  Serial.println(target); */
 
  switch (actionPN) // début du switch case de pilotage des barrières
  {
    case 0: // on ouvre les barrières
        if (actionPN != prevActionPN) {target = 1.0; prevActionPN=actionPN;}
        break;
    case 1: // on ferme les barrières avec sonnerie
        digitalWrite(pinSonne,sonne); // allumage d'une led qui visualise l'impulsion de déclenchement de la sonnerie
        prevActionPN=actionPN;
        break;
    case 2: // on ferme les barrières sans sonnerie
        if (actionPN != prevActionPN) {target = 0.0; prevActionPN=actionPN;}
        break;
  } // fin du switch case de pilotage des barrières
    // SlowMotionServo::update(); en attente pour plus tard

}

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #18 le: février 24, 2016, 08:34:52 am »
Oui c'est ça. Tu appelles la fonction start dans loop quand tu détectes la pression sur le bouton.
Cordialement

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Re : Arduino pilotage PN37
« Réponse #19 le: février 25, 2016, 08:03:45 am »
mais comment maîtriser le démarrage de la séquence, c'est-à-dire qu'elle se lance  1 fois chaque fois que le fameux interrupteur est basculé, et non pas dès le début du programme ? ? On met un maTable.start(1) à l'endroit prévu dans la loop ?  J'ai fait quelques essais en ce sens mais infructueux.

Pourrais tu donner le programme qui ne marche pas comme attendu ainsi que le fonctionnement voulu ?
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #20 le: février 25, 2016, 01:19:08 pm »
Je ne sais pas quelle fausse manœuvre j'avais faite en bidouillant, mais, en remettant un maTable.start(1) dans le cas 1 qui m'intéresse, ça fonctionne parfaitement. Ça, ça a l'air réglé.

Mais désormais je coince avec le fonctionnement de SlowMotionServo, qui fonctionnait très bien sur le petit programme d'essai.

Le système à piloter : des barrières de PN commandées par un servo, avec un petit module sonore autonome déclenché et arrêté par une impulsion.

La commande est un inter 2 positions, inter1 et inter2. Inter au centre correspond aux barrières levées, inter1 fermé (état LOW car alimenté par pull-up interne) déclenche le cas 1, inter2 fermé déclenche cas 2.  Les 3 états de cet inter déclenchent des séquences du programme via un switchCase. Ça, ça marche, le programme passe bien par où il doit passer.

3 cycles de commande :
cas 0 les barrières s'ouvrent,
cas 1 une sonnerie se déclenche, puis (+5 sec) les barrières se ferment, puis à la fin la sonnerie s'éteint. (Pour le test la séquence est accélérée)
cas 2 les barrières se ferment sans sonnerie et sans attente.

Cas 0 et cas 2, je n'ai pas besoin de TableSchedule, il devrait suffire de changer la valeur de target pour que SlowMotionServo actionne le servo.
Cas 1, je déclenche la séquence décrite dans TableSchedule. Cette séquence se déroule apparemment bien, car les actions qui concernent la sonnerie (simulée par une led) (fonctions pulseOn, pulseOff) fonctionnent comme prévu, les deux impulsions de 0,5 sec se déclenchent aux instants attendus. L'espion série confirme bien que la valeur de target change comme attendu à t = 2s.

Mon problème actuel, c'est que le servo ne réagit pas du tout, dans aucun des cas. Je dois avoir écrit quelque chose de défectueux ou pas où il faut, ou manquant.

Merci de tes lumières.

// Test de la bibliothèque ScheduleTable, de SlowMotionServo et de la commande d'un optocoupleur
#include <ScheduleTable.h>
#include <Bounce2.h>
#include <Servo.h>
#include <SlowMotionServo.h>

// Création des objets
ScheduleTable ouvreSonne(5,5000);  // Création de la table

Bounce inter1; // inter pour programme fermeture barrières avec sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil gris
Bounce inter2; // inter pour programme fermeture barrières sans sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil rouge

SMSSmooth servoPN; /* Servo with sinusoidal trajectory */

// Déclaration des constantes
const byte pinServo=9; // affecte l'E/S 9 au pilotage du servo
const byte pinInter1=13; // affecte l'E/S 13 à l'inter en position 1
const byte pinInter2=12; // affecte l'E/S 12 à l'inter en position 2
const byte pinSonne=8;  // affecte l'E/S 8 au pilotage de la sonnerie via optocoupleur. Pour ce test, l'opto allume une led alimentée séparément


 // déclaration des variables
byte actionPN=0; // variable d'état pour le switchcase de pilotage des barrières
byte prevActionPN=0; // l'état précédent de actionPN
float target = 0.0; // La cible du servo : target = 0.0 pour barrières fermées.
byte sonne=LOW; // variable utilisée pour l'impulsion de commande de la sonnerie.

void pulseOn()
{
  sonne=HIGH;
}

void pulseOff()
{
    sonne=LOW;
}

void basculeTarget()
{
  target = 0.0;
}

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    pinMode(pinInter1, INPUT_PULLUP); // déclare pinInter1 en entrée et active la résistance de pullup interne
    pinMode(pinInter2, INPUT_PULLUP); // déclare pinInter2 en entrée et active la résistance de pullup interne
    inter1.attach(pinInter1);
    inter1.interval(10);
    inter2.attach(pinInter2);
    inter2.interval(10);
    pinMode(pinSonne, OUTPUT); // déclare pinSonne comme sortie;

    servoPN.setInitialPosition(target);
    servoPN.setMinMax(850, 2100);
    servoPN.setPin(pinServo); /* the servo is connected to pin pinServo */
 
// Table des événements de ouvreSonne: impulsions de 500 ms à t=0 et t = 4000, et assigne la valeur 0.0 à target à t = 2000
    ouvreSonne.at(0,pulseOn);
    ouvreSonne.at(500,pulseOff);
    ouvreSonne.at(2000,basculeTarget);
    ouvreSonne.at(4000,pulseOn);
    ouvreSonne.at(4500,pulseOff);
}

void loop() {
  // put your main code here, to run repeatedly:
  // les objets Bounce doivent exécuter leur code interne à chaque loop :
  inter1.update();
  inter2.update();
  int value1 = inter1.read();
  int value2 = inter2.read();
  ScheduleTable::update();

// ici on calcule actionPN en fonction de inter1 et inter2
    if ((value1==HIGH) && (value2==LOW))
    {
      actionPN=2;
    }
    else if ((value1==LOW) && (value2==HIGH))
    {
      actionPN=1;
    }
    else {
      actionPN=0;
    }
  /* Serial.print("inter 1  :  ");
  Serial.print(value1);
  Serial.print("  inter2 :  ");
  Serial.print(value2);
  Serial.print("  actionPN  :  ");
  Serial.print(actionPN);
  Serial.print("  Target  :  ");
  Serial.println(target);*/

 
  switch (actionPN) // début du switch case de pilotage des barrières
  {
    case 0: // on ouvre les barrières
        if (actionPN != prevActionPN) {target = 1.0; prevActionPN=actionPN;}
        break;
    case 1: // on ferme les barrières avec sonnerie
        if (actionPN != prevActionPN) ouvreSonne.start(1);
        digitalWrite(pinSonne,sonne); // allumage d'une led qui visualise l'impulsion de déclenchement de la sonnerie
        prevActionPN=actionPN;
        break;
    case 2: // on ferme les barrières sans sonnerie
        if (actionPN != prevActionPN) {target = 0.0; prevActionPN=actionPN;}
        break;
} // fin du switch case de pilotage des barrières

  servoPN.goTo(target);
}

« Modifié: février 25, 2016, 01:24:29 pm par Dominique Donnat »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #21 le: février 25, 2016, 01:34:58 pm »
À vue de nez tu n'appelles pas SlowMotionServo::update() dans loop  :)
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #22 le: février 25, 2016, 02:56:10 pm »
Il y a un progrès, le servo a bougé (il s'est remis une fois à la position zéro - ça doit correspondre à la prise en compte de     servoPN.setInitialPosition(target); à la première boucle),

mais ne réagit toujours pas aux changements de target qui eux se passent bien. Comme si servoPN.goTo(target) qui est en fin de loop était ignoré. Il y a encore autre chose.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #23 le: février 25, 2016, 02:59:24 pm »
Le

void basculeTarget()
{
  target = 0.0;
}

Fait que quoique tu fasses, le servo reste à la position 0.0

Ne serait-ce pas plutôt

void basculeTarget()
{
  target = 1.0 - target;
}

De cette manière si target vaut 0.0, le nouveau target vaut 1.0 et si target vaut 1.0, le nouveau target vaut 0.0. Dans ce cas tu aurais effectivement une bascule.
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #24 le: février 25, 2016, 03:37:56 pm »
J'y avais pensé (et c'est pour cela que la fonction s'appelle bascule) mais ensuite, j'ai préféré positionner target à la valeur voulue pour une phase donnée.

Et la variable target bouge bien entre 0.0 et 1.0 comme je le souhaite en fonction des inter, je le contrôle par Serial.print.

Je pars de actionPN = 2, les barrières sont baissées
inter 1  :  1  inter2 :  0  actionPN  :  2  prevActionPN  :  2  Target  :  0.00
inter 1  :  1  inter2 :  0  actionPN  :  2  prevActionPN  :  2  Target  :  0.00
inter 1  :  1  inter2 :  0  actionPN  :  2  prevActionPN  :  2  Target  :  0.00
Je bascule inter2, actionPN passe à 0, target passe immédiatement à 1, les barrières sont censées se lever
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  2  Target  :  0.00
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
.../...
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
inter 1  :  1  inter2 :  1  actionPN  :  0  prevActionPN  :  0  Target  :  1.00
Je positionne inter1 à low, actionPN passe à 1, target reste à 1.0 pendant le nbre de loops correspondant à l'action de ScheduleTable (2s) (65 loops exactement soit une loop de 30 ms) - la sonnerie est censée se déclencher, le barrières ne bougent pas
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  0  Target  :  1.00
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  1  Target  :  1.00
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  1  Target  :  1.00
.../...
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  1  Target  :  1.00
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  1  Target  :  0.00  <-là, les barrières s'abaissent
inter 1  :  0  inter2 :  1  actionPN  :  1  prevActionPN  :  1  Target  :  0.00
etc

Bref, moi dont l'expérience en programmation se résume à des cours de Fortran il y a 40 ans (et un peu de pratique quand même), j'avoue que la programmation objet, c'est un choc culturel !

[Edit : j'ai fait la modif, rien ne change. ]

Qu'est-ce qui peut bien se passer ?
« Modifié: février 25, 2016, 03:50:26 pm par Dominique Donnat »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #25 le: février 25, 2016, 04:36:21 pm »
Il faut que je regarde SlowMotionServo plus en détails mais il est possible que ca se passe mal d'appeler goTo alors que le servo n'est pas arrêté à une position. Essaye de mettre un if (servoPN.isStopped()) autour de serviPN.goTo pour voir.
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #26 le: février 25, 2016, 05:25:30 pm »
Au poil ! Le système réagit exactement comme je voulais. Je peux continuer l'intégration. Merci.

Mais si tu trouves l'explication, je suis preneur. J'aime bien comprendre un minimum (même si je n'en suis pas encore assez avancé).


Et par ailleurs cette méthode .isStopped (tu as dû le faire pour cela) permet que le servo aille au bout de son mouvement, même si on change la consigne en cours de mouvement. Très utile en cas de fausse manœuvre, j'avais cette préoccupation dans un coin de ma to-do list, c'est déjà tout fait ! Merci.
« Modifié: février 25, 2016, 05:36:25 pm par Dominique Donnat »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #27 le: février 25, 2016, 05:47:59 pm »
À froid je n'ai pas d'explication si ce n'est que quand j'ai écrit SlowMotionServo je n'ai pas prévu un changement de goTo en cours de mouvement. 2 solutions, une pas facile car il faut que je réécrive une partie et en regardant rapidement le code je n'ai pas vu d'où ça pouvait coincer : prendre en compte la nouvelle destination en cours de mouvement. Une facile et plus satisfaisante je pense, si le servo n'est pas stoppé, mettre dans un tampon la nouvelle target et une fois que l'ancienne target est atteinte, la prendre en compte. Ça serait mieux que de bloquer si goTo est appelé de manière imprévue :-)
« Modifié: février 25, 2016, 07:58:12 pm par Jean-Luc »
Cordialement

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #28 le: avril 05, 2016, 12:13:45 pm »
Rebonjour à tous,

mon projet de PN a progressé, mais je bute sur un comportement apparemment aléatoire.

Pour mémoire, je pilote un servo qui manœuvre des barrières de PN. La commande du servo fait appel à la bibliothèque SlowMotionServo de Jean-Luc qui fonctionne bien.

Un inter double (1RT, représenté par deux inter inter1 et inter2 sur deux entrées avec pull-up interne activée) pilote le mouvement des barrières. L'un des modes déclenche une séquence (bibliothèque ScheduleTable) avec : déclenchement sonnerie, 5 sec plus tard mouvement de fermeture des barrières qui dure 10 s, puis extinction sonnerie.

La sonnerie est un module externe autonome, le déclenchement et l'extinction se font par mise à la masse impulsionnelle d'une entrée (la même). J'ai installé un optocoupleur pour activer ce "contact".

Mon problème : le déclenchement de la sonnerie par le programme est aléatoire, ou en tout cas réagit à quelque chose que je ne comprends pas.
Après l'init de l'Arduino, la première commande active bien la sonnerie. Puis la sonnerie ne se déclenche plus. La commande issue de l'arduino est correcte (visualisé par une diode, on voit bien les deux impulsions de 0,5sec à chaque cycle). De même, un mise à la masse physique de l'entrée du module sonore active bien la sonnerie.

Je suspecte des problèmes de timing entre le rythme du microcontroleur du module sonore (dont je ne connais rien) et le cycle issu de l'arduino.

Quelqu'un a-t-il déjà rencontré ce genre de problème ? Toute suggestion d'analyse est bonne, merci d'avance.

/* Programme de pilotage du modulino PN37
 *  créé par D. Donnat - février 2016
 */
#include <ScheduleTable.h>
#include <Bounce2.h>
#include <Servo.h>
#include <SlowMotionServo.h>

// Création des objets
    ScheduleTable ouvreSonne(5,18000);  // Création de la table
    Bounce inter1; // inter pour programme fermeture barrières avec sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil gris
    Bounce inter2; // inter pour programme fermeture barrières sans sonnerie ; LOW pour inter activé, pullup interne au + 5V, fil rouge
    Bounce eclair; // instancie un objet bounce pour le bouton poussoir d'éclairage
    SMSSmooth servoPN;

 // déclaration des constantes
    const byte pinServo=9; // affecte l'E/S 9 au pilotage du servo
    const byte pinInter1=13; // affecte l'E/S 13 à l'inter en position 1
    const byte pinInter2=12; // affecte l'E/S 12 à l'inter en position 2
    const byte pinSonne=8;  // affecte l'E/S 8 au pilotage de la sonnerie via optocoupleur
   
    const byte pinLed0=3; // affecte l'E/S 3 à la led 0 lampadaire en façade
    const byte pinLed1=5; // affecte l'E/S 5 à la led 1 grande salle
    const byte pinLed2=6; // affecte l'E/S 6 à la led 2 petite chambre
    const byte pinLed3=11; // affecte l'E/S 11 à la led 3e étage
    const byte pinEclair=7; // affecte l'E/S 7 au bp cyclage éclairage

 // déclaration des variables
    float target = 0.0; // La cible du servo : target = 0.0 pour barrières fermées.
    byte actionPN=0; // variable d'état pour le switchcase de pilotage des barrières
    byte prevActionPN=0; // l'état précédent de actionPN
    byte sonne=LOW; // variable utilisée pour l'impulsion de commande de la sonnerie.
    // byte flagInit = 0; // flag pour sortir de la boucle d'initialisation. flagInit = 1 pour sortir ; à voir plus tard
    byte memoireEclair = HIGH; // état du bouton d'éclairage au cycle précédent
    byte cycleEclair; // compteur de cycle d'éclairage, de 0 à 4 ; 0 = éteint, cycles d'éclairage de 1 à 4
    byte pwmLed0=255; // pour règler l'éclairement Led0 - provisoire 100 % (255)
    byte pwmLed1=255; // pour règler l'éclairement Led1 - provisoire 100 % (255)
    byte pwmLed2=255; // pour règler l'éclairement Led2 - provisoire 100 % (255)
    byte pwmLed3=255; // pour règler l'éclairement Led3 - provisoire 100 % (255)

void pulseOn()
    {
      sonne=HIGH;
    }

void pulseOff()
    {
        sonne=LOW;
    }

void basculeTarget()
    {
      target = 1.0 - target;
    }



void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    servoPN.setInitialPosition(target);
    servoPN.setMinMax(850, 1475);
    servoPN.setPin(pinServo); /* the servo is connected to pin pinServo */

    pinMode(pinInter1, INPUT_PULLUP); // déclare pinInter1 en entrée et active la résistance de pullup interne
    pinMode(pinInter2, INPUT_PULLUP); // déclare pinInter2 en entrée et active la résistance de pullup interne
    pinMode(pinEclair, INPUT_PULLUP); // déclare pinEclair en entrée et active la résistance de pullup interne
    inter1.attach(pinInter1);
    inter1.interval(10);
    inter2.attach(pinInter2);
    inter2.interval(10);
    eclair.attach(pinEclair);
    eclair.interval(10);
    pinMode(pinSonne, OUTPUT); // déclare pinSonne comme sortie;
    pinMode(pinLed0, OUTPUT); // déclare pinLed0 comme sortie
    pinMode(pinLed1, OUTPUT); // déclare pinLed1 comme sortie
    pinMode(pinLed2, OUTPUT); // déclare pinLed2 comme sortie
    pinMode(pinLed3, OUTPUT); // déclare pinLed3 comme sortie
    analogWrite(pinLed0, 0); // on éteint toutes les leds
    analogWrite(pinLed1, 0);
    analogWrite(pinLed2, 0);
    analogWrite(pinLed3, 0);

// Table des événements de ouvreSonne: impulsions de 500 ms à t=500 et t = 16500, et assigne la valeur 0.0 à target à t = 5000
    ouvreSonne.at(500,pulseOn);
    ouvreSonne.at(1000,pulseOff);
    ouvreSonne.at(5500,basculeTarget);
    ouvreSonne.at(16500,pulseOn);
    ouvreSonne.at(17000,pulseOff);
}

void loop() {
  // put your main code here, to run repeatedly:
  // les objets Bounce doivent exécuter leur code interne à chaque loop :
  inter1.update();
  inter2.update();
  eclair.update();
  // Lire la valeur des inter filtrés :
  int value1 = inter1.read();
  int value2 = inter2.read();
  int value3 = eclair.read();

  ScheduleTable::update();
  SlowMotionServo::update();

  // ici on calcule actionPN en fonction de inter1 et inter2
    if ((value1==HIGH) && (value2==LOW))
    {
      actionPN=2;
    }
    else if ((value1==LOW) && (value2==HIGH))
    {
      actionPN=1;
    }
    else {
      actionPN=0;
    }
          Serial.print("inter 1  :  ");
          Serial.print(value1);
          Serial.print("  inter2 :  ");
          Serial.print(value2);
          Serial.print("  actionPN  :  ");
          Serial.print(actionPN);
          Serial.print("  prevActionPN  :  ");
          Serial.print(prevActionPN);
          Serial.print("  Target avant :  ");
          Serial.print(target);

 
  // Code pour gérer le mouvement des barrières
    switch (actionPN) // début du switch case de pilotage des barrières
        {
          case 0: // on ouvre les barrières
              if (actionPN != prevActionPN) {target = 1.0; prevActionPN=actionPN;}
              break;
          case 1: // on ferme les barrières avec sonnerie
              if (actionPN != prevActionPN) ouvreSonne.start(1);
                digitalWrite(pinSonne,sonne); // allumage d'une led qui visualise l'impulsion de déclenchement de la sonnerie
                prevActionPN=actionPN;
               break;
          case 2: // on ferme les barrières sans sonnerie
              if (actionPN != prevActionPN) {target = 0.0; prevActionPN=actionPN;}
              break;
          } // fin du switch case de pilotage des barrières

          Serial.print("  target après :  ");
          Serial.print(target);
          Serial.print("  Sonne  :  ");
          Serial.println(sonne);
    if (servoPN.isStopped()) {
      servoPN.goTo(target);
    }
  // Code pour gérer les séquences d'éclairage
    if ((value3 != memoireEclair) && (value3 == LOW)) cycleEclair++;
    memoireEclair = value3;
    if (cycleEclair > 7) cycleEclair = 0;
   
    switch (cycleEclair)  { // début du switch sur cycleEclair
    case 0: // on n'allume rien
      analogWrite(pinLed0, 0);
      analogWrite(pinLed1, 0);
      analogWrite(pinLed2, 0);
      analogWrite(pinLed3, 0);
      break;
    case 1: // on allume Led0
      analogWrite(pinLed0, pwmLed0);
      break;
    case 2: // on garde Led0 et on allume Led1
      //analogWrite(pinLed0, 0);
      analogWrite(pinLed1, pwmLed1);
      break;
    case 3: // on garde Led0, Led1 et on allume Led2 en plus
      // analogWrite(pinLed1, 0);
      analogWrite(pinLed2, pwmLed2);
      break;
    case 4: // on garde Led0, on éteint Led1 et on garde Led2
      analogWrite(pinLed1, 0);
            break;
    case 5: // on gerde Led0 et Led2, on allume Led3 en plus
      analogWrite(pinLed3, pwmLed3);
      break;
    case 6: // on garde Led0 et Led3, on éteint Led2
      analogWrite(pinLed2, 0);
      break;
    case 7: // on garde Led1, on éteint Led3
      analogWrite(pinLed3, 0);
      break;
  } // fin du switch sur cycleEclair
}

Dominique Donnat

  • Newbie
  • *
  • Messages: 19
    • Voir le profil
Re : Arduino pilotage PN37
« Réponse #29 le: avril 05, 2016, 12:27:46 pm »
Mon module son externe, c'est celui-ci ou un très similaire :
http://www.ebay.fr/itm/LSM-01b-Module-Passage-a-niveau-/252205188851?hash=item3ab899c6f3

Je viens de voir que le "fabricant" propose un module d'interface pour déclenchement par autre chose, mais ça n'existait pas quand je l'ai acheté, et en plus on ne le trouve pas sur son site. Et puis, la commande étant une simple mise à la masse d'une entrée, il n'y en a pas vraiment besoin.