IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Raspberry Pi Discussion :

Comment commuter plusieurs relais simultanément avec le port GPIO ?


Sujet :

Raspberry Pi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2016
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2016
    Messages : 95
    Par défaut Comment commuter plusieurs relais simultanément avec le port GPIO ?
    Bonjour,

    Je cherche un moyen de commander plusieurs relais simultanément, avec mon Raspberry.
    Actuellement, j'utilise la commande gpio, pour contrôler les broches du GPIO

    Voici, en bash, mon premier essai de chenillard :

    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    gpio -g mode 26 out
    gpio -g mode 19 out
    gpio -g mode 13 out
    gpio -g mode 6 out
    gpio -g mode 5 out
    gpio -g mode 21 out
    gpio -g mode 20 out
    gpio -g mode 16 out
    gpio -g mode 12 out
    gpio -g mode 25 out
    gpio -g mode 24 out
    gpio -g mode 23 out
    sleep 5
    while true;
    do
     # Enclenche
     gpio -g write 26 1
     sleep 0.2
     gpio -g write 19 1
     sleep 0.2
     gpio -g write 13 1
     sleep 0.2
     gpio -g write 6 1
     sleep 0.2
     gpio -g write 5 1
     sleep 0.2
     gpio -g write 21 1
     sleep 0.2
     gpio -g write 20 1
     sleep 0.2
     gpio -g write 16 1
     sleep 0.2
     gpio -g write 12 1
     sleep 0.2
     gpio -g write 25 1
     sleep 0.2
     gpio -g write 24 1
     sleep 0.2
     gpio -g write 23 1
     sleep 0.2
     # Déclenche
     gpio -g write 26 0
     sleep 0.2
     gpio -g write 19 0
     sleep 0.2
     gpio -g write 13 0
     sleep 0.2
     gpio -g write 6 0
     sleep 0.2
     gpio -g write 5 0
     sleep 0.2
     gpio -g write 21 0
     sleep 0.2
     gpio -g write 20 0
     sleep 0.2
     gpio -g write 16 0
     sleep 0.2
     gpio -g write 12 0
     sleep 0.2
     gpio -g write 25 0
     sleep 0.2
     gpio -g write 24 0
     sleep 0.2
     gpio -g write 23 0
     sleep 0.2
    done
    Une boucle qui enclenche et déclenche, successivement, les douze premiers relais d'une carte de seize.
    A raison d'un relais manoeuvré toutes les 200 millisecondes.

    Nom : carte16relais.jpg
Affichages : 1568
Taille : 50,8 Ko

    Ensuite, j'ai rédigé un script PHP, destiné à être appelé par une requête Ajax.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    <?php
     $lesBroches = array(26, 19, 13, 6, 5, 21, 20, 16, 12, 25, 24, 23);
     if(isset($_POST['relais']) && $_POST['relais'] >= 0 && $_POST['relais'] < count($lesBroches) && isset($_POST['etat']))
     {
      $leRelais = min(max(0, $_POST['relais']), count($lesBroches));
      $lEtat = min(max(0, $_POST['etat']), 1);
      $commande = 'gpio -g mode '.$lesBroches[$leRelais].' out;sleep 100 ms;gpio -g write '.$lesBroches[$leRelais].' '.$lEtat;
      system($commande);
      //echo($commande);
     }
    ?>

    Le tableau $lesBroches est une table de correspondance, entre le relais (indice du tableau) et le n° de son fil de contrôle, partant du GPIO vers la carte.
    Ce script PHP est invoqué par une requête Ajax :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    var xhrGpio = new XMLHttpRequest();
    ...
    function enclencher(pRelais, pEtat, pDelai)
    {
     var attente = parseInt(Math.random() * pDelai);
     caseGpio.style.backgroundColor = 'transparent';
     caseGpio.innerHTML = '&nbsp;';
     setTimeout
     (
      function(pRelais, pEtat)
      {
       xhrGpio.open('POST', 'ajax/ajaxGpio.php');
       xhrGpio.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
       xhrGpio.send('relais=' + pRelais + '&etat=' + pEtat);
      },
      attente,
      pRelais,
      pEtat
     );
    }

    Cette fonction JavaScript reçoit :
    * Le numéro [0..11] du relais à manoeuvrer.
    * L'état [0/1] à donner au relais : 0=OFF, 1=ON
    * Le temps d'attente avant la manoeuvre.

    Le schéma final de mon application est le suivant :
    Un logiciel en JavaSCript, dont je vous épargne le détail (boutons, événements), sans pertinence ici, invoque la fonction enclencher(pRelais, pEtat, pDelai),
    qui, à son tour, invoque la requête Ajax, située sur la même machine (équipée d'un serveur LAMP), via l'adresse localhost.
    Ladite requête Ajax invoque une commande système gpio, qui manoeuvre les relais.

    Et c'est là l'objet de ma question.
    Car j'ai remarqué qu'en invoquant la commande gpio simultanément, sur deux relais ou plus, un seul d'entre eux était manoeuvré.
    J'ai donc légèrement différé la manoeuvre, en instaurant un temps d'attente aléatoire, passé en troisième paramètre, d'une fonction qui n'en comptait, au départ, que deux.

    Ainsi, je peux appeler ma fonction "enclencher" deux fois simultanément.
    En croisant les doigts, pour que la fonction Math.random() ne génère pas deux valeurs aléatoires trop proches l'une de l'autre.

    J'aimerais pouvoir enclencher, ou déclencher, tous mes douze (ou, plus tard, seize) relais simultanément, en une seule requête Ajax.

    L'idéal serait que je passe, à ma fonction, non pas le numéro et l'état du relais à manoeuvrer, mais un tableau de nbRelais cases, contenant chacune l'état que le relais correspondant doit prendre.

    Rédiger une telle fonction ne me pose aucun problème, mais que doit-elle invoquer ensuite, si la commande gpio a des ratés ?

    Actuellement, j'ai trouvé une solution sale :
    Créer une boucle de répétition, pour réveiller les relais qui ont raté leur commutation au premier ordre :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    relaisDog = function(pRelais)
     {
      // Watchdog d'enclenchement de secours
      if(pRelais < lesEtats.length)
      {
       enclencher(pRelais, parseInt(lesEtats[pRelais]), 500);
       setTimeout(relaisDog, 300, pRelais + 1);
      }
      else
      {
       setTimeout(relaisDog, 500, 0);
      }
     }
    ;
    // Premier appel de lancement
    setTimeout(relaisDog, 1000, 0);

    Comme un chien de garde, qui fait son boulot en arrière-plan, relaisDog répète inlassablement l'état on/off à chaque relais.
    Finalement, après un ou deux tours, tout le monde a compris, tous les relais sont bien commutés.
    De l'extérieur, ça donne l'impression d'un programme indiscipliné : Chacun commute quand il veut.
    Mais qui finit par obéir, avec du retard.

    J'aimerais n'entendre qu'un seul déclic. Comme une troupe qui marche au pas.
    Fiable à 100%, et sans relaisDog, dont je souhaite me débarrasser.
    Existe t'il d'autres commandes que gpio, pour maneuvrer l'état des pins d'un Raspberry ?

    Merci pour votre réponse.
    Christian.

  2. #2
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 152
    Billets dans le blog
    47
    Par défaut
    Bonsoir,

    Bizarre ce délai de 200 ms...

    On doit pouvoir faire ça en Python avec la bibliothèque RPi.GPIO, voir https://sourceforge.net/p/raspberry-.../wiki/Outputs/
    4. To output to several channels at the same time:
    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chan_list = (11,12)
    GPIO.output(chan_list, GPIO.LOW) # all LOW
    GPIO.output(chan_list, (GPIO.HIGH,GPIO.LOW))  # first LOW, second HIGH
    Je ferais davantage confiance au C avec la bibliothèque bcm2835. Au moins, on sait que ça tape directement dans les registres des ports GPIO.
    Tu as une fonction void bcm2835_gpio_set_multi(uint32_t mask) qui semble faire le boulot, voir http://www.airspayce.com/mikem/bcm28...8c0415fc2d419f

    Exemple :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint32_t mask = (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05); // masque pour  GPIO 3 et 5
    bcm2835_gpio_set_multi(mask);	 //mettre GPIO 3 et 5 à l'état haut en une seule opération

  3. #3
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 250
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 250
    Par défaut
    Salut,
    Ce n'est pas normal, je ne vois aucune raison d'être obligé d'attendre 200ms, ou autre, entre deux activations de relais.

    Tu as la doc de ta carte relais ?
    Il y a une alimentation indépendante pour les relais ?

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2016
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2016
    Messages : 95
    Par défaut L'alimentation de ma carte relais
    Ma première carte de quatre relais n'avait pas d'alimentation indépendante, je devais reprendre une masse sur le GPIO du Raspberry.
    La seconde carte, de 16 relais, a une alimentation 220 volts et un transfo intégré.

    Personnellement, je n'ai jamais programmé en Python, ni la moindre idée de son environnement d'exécution.
    Je devrais suivre un bon tuto.

    Je suis plutôt adepte de Java, mais je doute qu'on puisse installer une JVM sur une aussi petite machine qu'un Raspberry.
    Juste pour manoeuvrer des relais, Java me paraît assez lourd.

    Je vais donc étudier Python.

    Merci pour les réponses et les codes sources.

  5. #5
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 152
    Billets dans le blog
    47
    Par défaut
    Python et RPi.GPIO sont préinstallés sur Raspbian, la bibliothèque bcm2835 est légère, facile à installer et gcc est aussi préinstallé.

    Sinon en Java, il y a bien le projet Pi4J.

Discussions similaires

  1. Réponses: 2
    Dernier message: 15/12/2013, 11h22
  2. comment exécuter plusieurs requêtes ensemble avec Pentaho
    Par bfelicien2000 dans le forum Pentaho
    Réponses: 0
    Dernier message: 01/12/2010, 17h31
  3. [VB]Comment lire plusieurs videos simultanément
    Par fablebab dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 12/04/2006, 11h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo